2 LibreSSL - CAcert web application
3 Copyright (C) 2004-2012 CAcert Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 var CAcert_keygen_IE = function () {
21 /// Makes a new DOM text node
22 var textnode = function (text) {
23 return document.createTextNode(text);
26 /// makes a new <p> element
27 var paragraph = function (text) {
28 var paragraph = document.createElement("p");
29 paragraph.appendChild(textnode(text));
33 /// makes a new <pre> elemtent
34 var pre = function (text) {
35 var pre = document.createElement("pre");
36 pre.appendChild(textnode(text));
40 /// makes a new <option> element
41 var option = function (text, value) {
42 var option = document.createElement("option");
43 if (value !== undefined) {
44 option.setAttribute("value", value);
46 option.appendChild(textnode(text));
50 /// Removes all child nodes from the element
51 var removeChildren = function (element) {
52 element.innerHTML = "";
55 /// Show error message to user from exception
56 var showError = function (message, exception) {
59 "\n\nError: " + exception.message +
60 " (0x" + (0xFFFFFFFF + exception.number + 1).toString(16) +
61 " / " + exception.number + ")"
65 // Get important elements from the DOM
66 var form = document.getElementById("CertReqForm");
67 var securityLevel = document.getElementById("SecurityLevel");
68 var customSettings = document.getElementById("customSettings");
69 var provider = document.getElementById("CspProvider");
70 var algorithm = document.getElementById("algorithm");
71 var algorithmParagraph = document.getElementById("algorithmParagraph");
72 var keySize = document.getElementById("keySize");
73 var keySizeMin = document.getElementById("keySizeMin");
74 var keySizeMax = document.getElementById("keySizeMax");
75 var keySizeStep = document.getElementById("keySizeStep");
76 var genReq = document.getElementById("GenReq");
77 var csr = document.getElementById("CSR");
78 var noActiveX = document.getElementById("noActiveX");
79 var generatingKeyNotice = document.getElementById("generatingKeyNotice");
80 var createRequestErrorChooseAlgorithm = document.getElementById("createRequestErrorChooseAlgorithm");
81 var createRequestErrorConfirmDialogue = document.getElementById("createRequestErrorConfirmDialogue");
82 var createRequestErrorConnectDevice = document.getElementById("createRequestErrorConnectDevice");
83 var createRequestError = document.getElementById("createRequestError");
84 var invalidKeySizeError = document.getElementById("invalidKeySizeError");
85 var unsupportedPlatformError = document.getElementById("unsupportedPlatformError");
87 /// Initialise the CertEnroll code (Vista and higher)
88 /// returns false if initialisation fails
89 var initCertEnroll = function () {
91 var providerList = null;
94 // Try to initialise the ActiveX element. Requires permissions by the user
96 factory = new ActiveXObject("X509Enrollment.CX509EnrollmentWebClassFactory");
99 name: "NoObjectError",
100 message: "Got null at object creation"
104 // also try to create a useless object here so the library gets
105 // initialised and we don't need to check everytime later
106 factory.CreateObject("X509Enrollment.CObjectId");
108 form.style.display = "";
109 noActiveX.style.display = "none";
114 /// Get the selected provider
115 var getProvider = function () {
116 var providerIndex = provider.options[provider.selectedIndex].value;
117 return providerList.ItemByIndex(providerIndex);
120 /// Get the selected algorithm
121 var getAlgorithm = function () {
122 var algorithmIndex = algorithm.options[algorithm.selectedIndex].value;
123 return alg = cspStats.ItemByIndex(algorithmIndex).CspAlgorithm;
126 /// Get the selected key size
127 var getKeySize = function () {
128 var alg = getAlgorithm();
130 var bits = parseInt(keySize.value, 10);
132 (bits < alg.MinLength) ||
133 (bits > alg.MaxLength) ||
135 alg.IncrementLength &&
136 ((bits - alg.MinLength) % alg.IncrementLength !== 0)
145 /// Fill the key size list
146 var getKeySizeList = function () {
151 var alg = getAlgorithm();
154 keySize.setAttribute("min", alg.MinLength);
155 keySize.setAttribute("max", alg.MaxLength);
156 keySize.setAttribute("step", alg.IncrementLength);
157 keySize.setAttribute("value", alg.DefaultLength);
158 keySize.value = ""+alg.DefaultLength;
160 // ugly, but buggy otherwise if done with text nodes
161 keySizeMin.innerHTML = alg.MinLength;
162 keySizeMax.innerHTML = alg.MaxLength;
163 keySizeStep.innerHTML = alg.IncrementLength;
168 /// Fill the algorithm list
169 var getAlgorithmList = function () {
176 var csp = getProvider();
178 cspStats = providerList.GetCspStatusesFromOperations(
179 0x1c, //XCN_NCRYPT_ANY_ASYMMETRIC_OPERATION
180 //0x10, //XCN_NCRYPT_SIGNATURE_OPERATION
181 //0x8, //XCN_NCRYPT_SECRET_AGREEMENT_OPERATION
182 //0x4, //XCN_NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
186 removeChildren(algorithm);
187 for (i = 0; i < cspStats.Count; i++) {
188 var alg = cspStats.ItemByIndex(i).CspAlgorithm;
189 algorithm.appendChild(option(alg.Name, i));
192 return getKeySizeList();
195 /// Fill the crypto provider list
196 var getProviderList = function () {
199 var csps = factory.CreateObject("X509Enrollment.CCspInformations");
201 // Get provider information
202 csps.AddAvailableCsps();
204 removeChildren(provider);
206 for (i = 0; i < csps.Count; i++) {
207 var csp = csps.ItemByIndex(i);
208 provider.appendChild(option(csp.Name, i));
213 return getAlgorithmList();
216 /// Generate a key and create and submit the actual CSR
217 var createCSR = function () {
218 var providerName, algorithmOid, bits;
220 var level = securityLevel.options[securityLevel.selectedIndex];
221 if (level.value === "custom") {
222 providerName = getProvider().Name;
223 var alg = getAlgorithm();
224 algorithmOid = alg.GetAlgorithmOid(0, 0)
227 window.alert(invalidKeySizeError.innerHTML);
231 providerName = "Microsoft Software Key Storage Provider";
233 algorithmOid = factory.CreateObject("X509Enrollment.CObjectId");
234 algorithmOid.InitializeFromValue("1.2.840.113549.1.1.1"); // RSA
235 // "1.2.840.10040.4.1" == DSA
236 // "1.2.840.10046.2.1" == DH
238 if (level.value === "high") {
245 var privateKey = factory.CreateObject("X509Enrollment.CX509PrivateKey");
246 privateKey.ProviderName = providerName;
247 privateKey.Algorithm = algorithmOid;
248 privateKey.Length = bits;
249 privateKey.KeyUsage = 0xffffff; // XCN_NCRYPT_ALLOW_ALL_USAGES
250 privateKey.ExportPolicy = 0x1; // XCN_NCRYPT_ALLOW_EXPORT_FLAG
252 var request = factory.CreateObject("X509Enrollment.CX509CertificateRequestPkcs10");
253 request.InitializeFromPrivateKey(
256 "" // don't use a template
259 var enroll = factory.CreateObject("X509Enrollment.CX509Enrollment");
260 enroll.InitializeFromRequest(request);
262 generatingKeyNotice.style.display = "";
264 // The request needs to be created after we return so the "please wait"
265 // message gets rendered
266 var createCSRHandler = function () {
268 csr.value = enroll.CreateRequest(0x1); //XCN_CRYPT_STRING_BASE64
271 showError(createRequestErrorChooseAlgorithm.innerHTML, e);
274 generatingKeyNotice.style.display = "none";
277 window.setTimeout(createCSRHandler, 0);
279 // Always return false, form is submitted by deferred method
283 /// Call if securityLevel has changed
284 var refreshSecurityLevel = function () {
285 var level = securityLevel.options[securityLevel.selectedIndex];
286 if (level.value === "custom") {
288 customSettings.style.display = "";
290 customSettings.style.display = "none";
294 securityLevel.onchange = refreshSecurityLevel;
295 provider.onchange = getAlgorithmList;
296 algorithm.onchange = getKeySizeList;
297 genReq.onclick = createCSR;
300 } // end of initCertEnroll()
302 /// Initialise Xenroll code (XP and lower)
303 /// returns false if initialisation fails
304 var initXEnroll = function () {
307 providerTypes = Array(
312 5, //PROV_MS_EXCHANGE
314 12, //PROV_RSA_SCHANNEL
316 14, //PROV_EC_ECDSA_SIG
317 15, //PROV_EC_ECNRA_SIG
318 16, //PROV_EC_ECDSA_FULL
319 17, //PROV_EC_ECNRA_FULL
320 18, //PROV_DH_SCHANNEL
321 20, //PROV_SPYRUS_LYNKS
324 23, //PROV_REPLACE_OWF
329 1 << 13, //ALG_CLASS_SIGNATURE
330 //2 << 13, //ALG_CLASS_MSG_ENCRYPT
331 //3 << 13, //ALG_CLASS_DATA_ENCRYPT
332 //4 << 13, //ALG_CLASS_HASH
333 5 << 13 //ALG_CLASS_KEY_EXCHANGE
336 // Try to initialise the ActiveX element.
338 cenroll = new ActiveXObject("CEnroll.CEnroll");
342 name: "NoObjectError",
343 message: "Got null at object creation"
347 form.style.display = "";
348 algorithm.disabled = true;
349 noActiveX.style.display = "none";
354 /// Get the name of the selected provider
355 var getProviderName = function () {
356 return provider.options[provider.selectedIndex].text;
359 /// Get the type of the selected provider
360 var getProviderType = function () {
361 return parseInt(provider.options[provider.selectedIndex].value, 10);
364 var refreshProvider = function () {
365 cenroll.ProviderName = getProviderName();
366 cenroll.ProviderType = getProviderType();
369 /// Get the ID of the selected algorithm
370 var getAlgorithmId = function () {
371 return parseInt(algorithm.options[algorithm.selectedIndex].value, 10);
374 /// Minimum bit length for exchange keys
375 var getMinExKeyLength = function () {
379 return cenroll.GetKeyLen(true, true);
385 /// Maximum bit length for exchange keys
386 var getMaxExKeyLength = function () {
390 return cenroll.GetKeyLen(false, true);
396 /// Step size for exchange keys
397 /// This might not be available on older platforms
398 var getStepExKeyLength = function () {
402 return cenroll.GetKeyLenEx(3, 1);
408 /// Minimum bit length for signature keys
409 var getMinSigKeyLength = function () {
413 return cenroll.GetKeyLen(true, false);
419 /// Maximum bit length for signature keys
420 var getMaxSigKeyLength = function () {
424 return cenroll.GetKeyLen(false, false);
430 /// Step size for signature keys
431 /// This might not be available on older platforms
432 var getStepSigKeyLength = function () {
436 return cenroll.GetKeyLenEx(3, 2);
442 /// Get the selected key size
443 var getKeySize = function () {
444 var bits = parseInt(keySize.value, 10);
446 (bits < getMinSigKeyLength()) ||
447 (bits > getMaxSigKeyLength()) ||
449 getStepSigKeyLength() &&
450 ((bits - getMinSigKeyLength()) % getStepSigKeyLength() !== 0)
459 var getKeySizeLimits = function () {
461 keySize.setAttribute("min", getMinSigKeyLength());
462 keySize.setAttribute("max", getMaxSigKeyLength());
463 if (getStepSigKeyLength()) {
464 keySize.setAttribute("step", getStepSigKeyLength());
467 // ugly, but buggy otherwise if done with text nodes
468 keySizeMin.innerHTML = getMinSigKeyLength();
469 keySizeMax.innerHTML = getMaxSigKeyLength();
470 keySizeStep.innerHTML = getStepSigKeyLength();
472 if (getMinSigKeyLength() === getMaxSigKeyLength()) {
473 keySize.value = getMaxSigKeyLength();
479 /// Fill the algorithm selection box
480 var getAlgorithmList = function () {
485 removeChildren(algorithm);
487 for (i = 0; i < algClasses.length; ++i) {
488 for (j = 0; true; ++j) {
490 var algId = cenroll.EnumAlgs(j, algClasses[i]);
491 var algName = cenroll.GetAlgName(algId);
492 algorithm.appendChild(option(algName, algId));
502 /// Fill the provider selection box
503 var getProviderList = function () {
506 removeChildren(provider);
508 for (i = 0; i < providerTypes.length; ++i) {
509 cenroll.providerType = providerTypes[i];
511 var providerName = "invalid";
512 for (j = 0; true; ++j) {
514 providerName = cenroll.enumProviders(j, 0);
515 provider.appendChild(option(providerName, providerTypes[i]));
522 return getAlgorithmList();
525 var createCSR = function () {
526 var providerName, bits;
528 var level = securityLevel.options[securityLevel.selectedIndex];
529 if (level.value === "custom") {
533 if (bits === false) {
534 window.alert(invalidKeySizeError.innerHTML);
538 cenroll.ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0";
539 cenroll.ProviderType = 1; //PROV_RSA_FULL
541 if (level.value === "high") {
548 cenroll.GenKeyFlags = bits << 16; // keysize is encoded in the uper 16 bits
549 // Allow exporting the private key
550 cenroll.GenKeyFlags = cenroll.GenKeyFlags | 0x1; //CRYPT_EXPORTABLE
552 generatingKeyNotice.style.display = "";
554 // The request needs to be created after we return so the "please wait"
555 // message gets rendered
556 var createCSRHandler = function () {
558 csr.value = cenroll.createPKCS10("", "1.3.6.1.5.5.7.3.2");
561 if (e.number === -2147023673) {
562 // 0x800704c7 => dialogue declined
563 showError(createRequestErrorConfirmDialogue.innerHTML, e);
564 } else if (e.number === -2146435043) {
565 // 0x8010001d => crypto-device not connected
566 showError(createRequestErrorConnectDevice.innerHTML, e);
568 showError(createRequestError.innerHTML, e);
572 generatingKeyNotice.style.display = "none";
576 window.setTimeout(createCSRHandler, 0);
578 // Always return false, form is submitted by deferred method
582 /// Call if securityLevel has changed
583 var refreshSecurityLevel = function () {
584 var level = securityLevel.options[securityLevel.selectedIndex];
585 if (level.value === "custom") {
587 customSettings.style.display = "";
589 customSettings.style.display = "none";
593 securityLevel.onchange = refreshSecurityLevel;
594 provider.onchange = getAlgorithmList;
595 algorithm.onchange = getKeySizeLimits;
596 genReq.onclick = createCSR;
601 // Run the init functions until one is successful
602 if (initCertEnroll()) {
603 form.style.display = "";
604 noActiveX.style.display = "none";
605 } else if (initXEnroll()) {
606 form.style.display = "";
607 noActiveX.style.display = "none";
609 window.alert(unsupportedPlatformError.innerHTML);