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
);