corrade-nucleus-nucleons – Blame information for rev 26

Subversion Repositories:
Rev:
Rev Author Line No. Line
22 office 1 /**
2 * Javascript implementation of X.509 and related components (such as
3 * Certification Signing Requests) of a Public Key Infrastructure.
4 *
5 * @author Dave Longley
6 *
7 * Copyright (c) 2010-2014 Digital Bazaar, Inc.
8 *
9 * The ASN.1 representation of an X.509v3 certificate is as follows
10 * (see RFC 2459):
11 *
12 * Certificate ::= SEQUENCE {
13 * tbsCertificate TBSCertificate,
14 * signatureAlgorithm AlgorithmIdentifier,
15 * signatureValue BIT STRING
16 * }
17 *
18 * TBSCertificate ::= SEQUENCE {
19 * version [0] EXPLICIT Version DEFAULT v1,
20 * serialNumber CertificateSerialNumber,
21 * signature AlgorithmIdentifier,
22 * issuer Name,
23 * validity Validity,
24 * subject Name,
25 * subjectPublicKeyInfo SubjectPublicKeyInfo,
26 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
27 * -- If present, version shall be v2 or v3
28 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
29 * -- If present, version shall be v2 or v3
30 * extensions [3] EXPLICIT Extensions OPTIONAL
31 * -- If present, version shall be v3
32 * }
33 *
34 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
35 *
36 * CertificateSerialNumber ::= INTEGER
37 *
38 * Name ::= CHOICE {
39 * // only one possible choice for now
40 * RDNSequence
41 * }
42 *
43 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
44 *
45 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
46 *
47 * AttributeTypeAndValue ::= SEQUENCE {
48 * type AttributeType,
49 * value AttributeValue
50 * }
51 * AttributeType ::= OBJECT IDENTIFIER
52 * AttributeValue ::= ANY DEFINED BY AttributeType
53 *
54 * Validity ::= SEQUENCE {
55 * notBefore Time,
56 * notAfter Time
57 * }
58 *
59 * Time ::= CHOICE {
60 * utcTime UTCTime,
61 * generalTime GeneralizedTime
62 * }
63 *
64 * UniqueIdentifier ::= BIT STRING
65 *
66 * SubjectPublicKeyInfo ::= SEQUENCE {
67 * algorithm AlgorithmIdentifier,
68 * subjectPublicKey BIT STRING
69 * }
70 *
71 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
72 *
73 * Extension ::= SEQUENCE {
74 * extnID OBJECT IDENTIFIER,
75 * critical BOOLEAN DEFAULT FALSE,
76 * extnValue OCTET STRING
77 * }
78 *
79 * The only key algorithm currently supported for PKI is RSA.
80 *
81 * RSASSA-PSS signatures are described in RFC 3447 and RFC 4055.
82 *
83 * PKCS#10 v1.7 describes certificate signing requests:
84 *
85 * CertificationRequestInfo:
86 *
87 * CertificationRequestInfo ::= SEQUENCE {
88 * version INTEGER { v1(0) } (v1,...),
89 * subject Name,
90 * subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
91 * attributes [0] Attributes{{ CRIAttributes }}
92 * }
93 *
94 * Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
95 *
96 * CRIAttributes ATTRIBUTE ::= {
97 * ... -- add any locally defined attributes here -- }
98 *
99 * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
100 * type ATTRIBUTE.&id({IOSet}),
101 * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
102 * }
103 *
104 * CertificationRequest ::= SEQUENCE {
105 * certificationRequestInfo CertificationRequestInfo,
106 * signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
107 * signature BIT STRING
108 * }
109 */
110 var forge = require('./forge');
111 require('./aes');
112 require('./asn1');
113 require('./des');
114 require('./md');
115 require('./mgf');
116 require('./oids');
117 require('./pem');
118 require('./pss');
119 require('./rsa');
120 require('./util');
121  
122 // shortcut for asn.1 API
123 var asn1 = forge.asn1;
124  
125 /* Public Key Infrastructure (PKI) implementation. */
126 var pki = module.exports = forge.pki = forge.pki || {};
127 var oids = pki.oids;
128  
129 // short name OID mappings
130 var _shortNames = {};
131 _shortNames['CN'] = oids['commonName'];
132 _shortNames['commonName'] = 'CN';
133 _shortNames['C'] = oids['countryName'];
134 _shortNames['countryName'] = 'C';
135 _shortNames['L'] = oids['localityName'];
136 _shortNames['localityName'] = 'L';
137 _shortNames['ST'] = oids['stateOrProvinceName'];
138 _shortNames['stateOrProvinceName'] = 'ST';
139 _shortNames['O'] = oids['organizationName'];
140 _shortNames['organizationName'] = 'O';
141 _shortNames['OU'] = oids['organizationalUnitName'];
142 _shortNames['organizationalUnitName'] = 'OU';
143 _shortNames['E'] = oids['emailAddress'];
144 _shortNames['emailAddress'] = 'E';
145  
146 // validator for an SubjectPublicKeyInfo structure
147 // Note: Currently only works with an RSA public key
148 var publicKeyValidator = forge.pki.rsa.publicKeyValidator;
149  
150 // validator for an X.509v3 certificate
151 var x509CertificateValidator = {
152 name: 'Certificate',
153 tagClass: asn1.Class.UNIVERSAL,
154 type: asn1.Type.SEQUENCE,
155 constructed: true,
156 value: [{
157 name: 'Certificate.TBSCertificate',
158 tagClass: asn1.Class.UNIVERSAL,
159 type: asn1.Type.SEQUENCE,
160 constructed: true,
161 captureAsn1: 'tbsCertificate',
162 value: [{
163 name: 'Certificate.TBSCertificate.version',
164 tagClass: asn1.Class.CONTEXT_SPECIFIC,
165 type: 0,
166 constructed: true,
167 optional: true,
168 value: [{
169 name: 'Certificate.TBSCertificate.version.integer',
170 tagClass: asn1.Class.UNIVERSAL,
171 type: asn1.Type.INTEGER,
172 constructed: false,
173 capture: 'certVersion'
174 }]
175 }, {
176 name: 'Certificate.TBSCertificate.serialNumber',
177 tagClass: asn1.Class.UNIVERSAL,
178 type: asn1.Type.INTEGER,
179 constructed: false,
180 capture: 'certSerialNumber'
181 }, {
182 name: 'Certificate.TBSCertificate.signature',
183 tagClass: asn1.Class.UNIVERSAL,
184 type: asn1.Type.SEQUENCE,
185 constructed: true,
186 value: [{
187 name: 'Certificate.TBSCertificate.signature.algorithm',
188 tagClass: asn1.Class.UNIVERSAL,
189 type: asn1.Type.OID,
190 constructed: false,
191 capture: 'certinfoSignatureOid'
192 }, {
193 name: 'Certificate.TBSCertificate.signature.parameters',
194 tagClass: asn1.Class.UNIVERSAL,
195 optional: true,
196 captureAsn1: 'certinfoSignatureParams'
197 }]
198 }, {
199 name: 'Certificate.TBSCertificate.issuer',
200 tagClass: asn1.Class.UNIVERSAL,
201 type: asn1.Type.SEQUENCE,
202 constructed: true,
203 captureAsn1: 'certIssuer'
204 }, {
205 name: 'Certificate.TBSCertificate.validity',
206 tagClass: asn1.Class.UNIVERSAL,
207 type: asn1.Type.SEQUENCE,
208 constructed: true,
209 // Note: UTC and generalized times may both appear so the capture
210 // names are based on their detected order, the names used below
211 // are only for the common case, which validity time really means
212 // "notBefore" and which means "notAfter" will be determined by order
213 value: [{
214 // notBefore (Time) (UTC time case)
215 name: 'Certificate.TBSCertificate.validity.notBefore (utc)',
216 tagClass: asn1.Class.UNIVERSAL,
217 type: asn1.Type.UTCTIME,
218 constructed: false,
219 optional: true,
220 capture: 'certValidity1UTCTime'
221 }, {
222 // notBefore (Time) (generalized time case)
223 name: 'Certificate.TBSCertificate.validity.notBefore (generalized)',
224 tagClass: asn1.Class.UNIVERSAL,
225 type: asn1.Type.GENERALIZEDTIME,
226 constructed: false,
227 optional: true,
228 capture: 'certValidity2GeneralizedTime'
229 }, {
230 // notAfter (Time) (only UTC time is supported)
231 name: 'Certificate.TBSCertificate.validity.notAfter (utc)',
232 tagClass: asn1.Class.UNIVERSAL,
233 type: asn1.Type.UTCTIME,
234 constructed: false,
235 optional: true,
236 capture: 'certValidity3UTCTime'
237 }, {
238 // notAfter (Time) (only UTC time is supported)
239 name: 'Certificate.TBSCertificate.validity.notAfter (generalized)',
240 tagClass: asn1.Class.UNIVERSAL,
241 type: asn1.Type.GENERALIZEDTIME,
242 constructed: false,
243 optional: true,
244 capture: 'certValidity4GeneralizedTime'
245 }]
246 }, {
247 // Name (subject) (RDNSequence)
248 name: 'Certificate.TBSCertificate.subject',
249 tagClass: asn1.Class.UNIVERSAL,
250 type: asn1.Type.SEQUENCE,
251 constructed: true,
252 captureAsn1: 'certSubject'
253 },
254 // SubjectPublicKeyInfo
255 publicKeyValidator,
256 {
257 // issuerUniqueID (optional)
258 name: 'Certificate.TBSCertificate.issuerUniqueID',
259 tagClass: asn1.Class.CONTEXT_SPECIFIC,
260 type: 1,
261 constructed: true,
262 optional: true,
263 value: [{
264 name: 'Certificate.TBSCertificate.issuerUniqueID.id',
265 tagClass: asn1.Class.UNIVERSAL,
266 type: asn1.Type.BITSTRING,
267 constructed: false,
268 // TODO: support arbitrary bit length ids
269 captureBitStringValue: 'certIssuerUniqueId'
270 }]
271 }, {
272 // subjectUniqueID (optional)
273 name: 'Certificate.TBSCertificate.subjectUniqueID',
274 tagClass: asn1.Class.CONTEXT_SPECIFIC,
275 type: 2,
276 constructed: true,
277 optional: true,
278 value: [{
279 name: 'Certificate.TBSCertificate.subjectUniqueID.id',
280 tagClass: asn1.Class.UNIVERSAL,
281 type: asn1.Type.BITSTRING,
282 constructed: false,
283 // TODO: support arbitrary bit length ids
284 captureBitStringValue: 'certSubjectUniqueId'
285 }]
286 }, {
287 // Extensions (optional)
288 name: 'Certificate.TBSCertificate.extensions',
289 tagClass: asn1.Class.CONTEXT_SPECIFIC,
290 type: 3,
291 constructed: true,
292 captureAsn1: 'certExtensions',
293 optional: true
294 }]
295 }, {
296 // AlgorithmIdentifier (signature algorithm)
297 name: 'Certificate.signatureAlgorithm',
298 tagClass: asn1.Class.UNIVERSAL,
299 type: asn1.Type.SEQUENCE,
300 constructed: true,
301 value: [{
302 // algorithm
303 name: 'Certificate.signatureAlgorithm.algorithm',
304 tagClass: asn1.Class.UNIVERSAL,
305 type: asn1.Type.OID,
306 constructed: false,
307 capture: 'certSignatureOid'
308 }, {
309 name: 'Certificate.TBSCertificate.signature.parameters',
310 tagClass: asn1.Class.UNIVERSAL,
311 optional: true,
312 captureAsn1: 'certSignatureParams'
313 }]
314 }, {
315 // SignatureValue
316 name: 'Certificate.signatureValue',
317 tagClass: asn1.Class.UNIVERSAL,
318 type: asn1.Type.BITSTRING,
319 constructed: false,
320 captureBitStringValue: 'certSignature'
321 }]
322 };
323  
324 var rsassaPssParameterValidator = {
325 name: 'rsapss',
326 tagClass: asn1.Class.UNIVERSAL,
327 type: asn1.Type.SEQUENCE,
328 constructed: true,
329 value: [{
330 name: 'rsapss.hashAlgorithm',
331 tagClass: asn1.Class.CONTEXT_SPECIFIC,
332 type: 0,
333 constructed: true,
334 value: [{
335 name: 'rsapss.hashAlgorithm.AlgorithmIdentifier',
336 tagClass: asn1.Class.UNIVERSAL,
337 type: asn1.Class.SEQUENCE,
338 constructed: true,
339 optional: true,
340 value: [{
341 name: 'rsapss.hashAlgorithm.AlgorithmIdentifier.algorithm',
342 tagClass: asn1.Class.UNIVERSAL,
343 type: asn1.Type.OID,
344 constructed: false,
345 capture: 'hashOid'
346 /* parameter block omitted, for SHA1 NULL anyhow. */
347 }]
348 }]
349 }, {
350 name: 'rsapss.maskGenAlgorithm',
351 tagClass: asn1.Class.CONTEXT_SPECIFIC,
352 type: 1,
353 constructed: true,
354 value: [{
355 name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier',
356 tagClass: asn1.Class.UNIVERSAL,
357 type: asn1.Class.SEQUENCE,
358 constructed: true,
359 optional: true,
360 value: [{
361 name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.algorithm',
362 tagClass: asn1.Class.UNIVERSAL,
363 type: asn1.Type.OID,
364 constructed: false,
365 capture: 'maskGenOid'
366 }, {
367 name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.params',
368 tagClass: asn1.Class.UNIVERSAL,
369 type: asn1.Type.SEQUENCE,
370 constructed: true,
371 value: [{
372 name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.params.algorithm',
373 tagClass: asn1.Class.UNIVERSAL,
374 type: asn1.Type.OID,
375 constructed: false,
376 capture: 'maskGenHashOid'
377 /* parameter block omitted, for SHA1 NULL anyhow. */
378 }]
379 }]
380 }]
381 }, {
382 name: 'rsapss.saltLength',
383 tagClass: asn1.Class.CONTEXT_SPECIFIC,
384 type: 2,
385 optional: true,
386 value: [{
387 name: 'rsapss.saltLength.saltLength',
388 tagClass: asn1.Class.UNIVERSAL,
389 type: asn1.Class.INTEGER,
390 constructed: false,
391 capture: 'saltLength'
392 }]
393 }, {
394 name: 'rsapss.trailerField',
395 tagClass: asn1.Class.CONTEXT_SPECIFIC,
396 type: 3,
397 optional: true,
398 value: [{
399 name: 'rsapss.trailer.trailer',
400 tagClass: asn1.Class.UNIVERSAL,
401 type: asn1.Class.INTEGER,
402 constructed: false,
403 capture: 'trailer'
404 }]
405 }]
406 };
407  
408 // validator for a CertificationRequestInfo structure
409 var certificationRequestInfoValidator = {
410 name: 'CertificationRequestInfo',
411 tagClass: asn1.Class.UNIVERSAL,
412 type: asn1.Type.SEQUENCE,
413 constructed: true,
414 captureAsn1: 'certificationRequestInfo',
415 value: [{
416 name: 'CertificationRequestInfo.integer',
417 tagClass: asn1.Class.UNIVERSAL,
418 type: asn1.Type.INTEGER,
419 constructed: false,
420 capture: 'certificationRequestInfoVersion'
421 }, {
422 // Name (subject) (RDNSequence)
423 name: 'CertificationRequestInfo.subject',
424 tagClass: asn1.Class.UNIVERSAL,
425 type: asn1.Type.SEQUENCE,
426 constructed: true,
427 captureAsn1: 'certificationRequestInfoSubject'
428 },
429 // SubjectPublicKeyInfo
430 publicKeyValidator,
431 {
432 name: 'CertificationRequestInfo.attributes',
433 tagClass: asn1.Class.CONTEXT_SPECIFIC,
434 type: 0,
435 constructed: true,
436 optional: true,
437 capture: 'certificationRequestInfoAttributes',
438 value: [{
439 name: 'CertificationRequestInfo.attributes',
440 tagClass: asn1.Class.UNIVERSAL,
441 type: asn1.Type.SEQUENCE,
442 constructed: true,
443 value: [{
444 name: 'CertificationRequestInfo.attributes.type',
445 tagClass: asn1.Class.UNIVERSAL,
446 type: asn1.Type.OID,
447 constructed: false
448 }, {
449 name: 'CertificationRequestInfo.attributes.value',
450 tagClass: asn1.Class.UNIVERSAL,
451 type: asn1.Type.SET,
452 constructed: true
453 }]
454 }]
455 }]
456 };
457  
458 // validator for a CertificationRequest structure
459 var certificationRequestValidator = {
460 name: 'CertificationRequest',
461 tagClass: asn1.Class.UNIVERSAL,
462 type: asn1.Type.SEQUENCE,
463 constructed: true,
464 captureAsn1: 'csr',
465 value: [
466 certificationRequestInfoValidator, {
467 // AlgorithmIdentifier (signature algorithm)
468 name: 'CertificationRequest.signatureAlgorithm',
469 tagClass: asn1.Class.UNIVERSAL,
470 type: asn1.Type.SEQUENCE,
471 constructed: true,
472 value: [{
473 // algorithm
474 name: 'CertificationRequest.signatureAlgorithm.algorithm',
475 tagClass: asn1.Class.UNIVERSAL,
476 type: asn1.Type.OID,
477 constructed: false,
478 capture: 'csrSignatureOid'
479 }, {
480 name: 'CertificationRequest.signatureAlgorithm.parameters',
481 tagClass: asn1.Class.UNIVERSAL,
482 optional: true,
483 captureAsn1: 'csrSignatureParams'
484 }]
485 }, {
486 // signature
487 name: 'CertificationRequest.signature',
488 tagClass: asn1.Class.UNIVERSAL,
489 type: asn1.Type.BITSTRING,
490 constructed: false,
491 captureBitStringValue: 'csrSignature'
492 }]
493 };
494  
495 /**
496 * Converts an RDNSequence of ASN.1 DER-encoded RelativeDistinguishedName
497 * sets into an array with objects that have type and value properties.
498 *
499 * @param rdn the RDNSequence to convert.
500 * @param md a message digest to append type and value to if provided.
501 */
502 pki.RDNAttributesAsArray = function(rdn, md) {
503 var rval = [];
504  
505 // each value in 'rdn' in is a SET of RelativeDistinguishedName
506 var set, attr, obj;
507 for(var si = 0; si < rdn.value.length; ++si) {
508 // get the RelativeDistinguishedName set
509 set = rdn.value[si];
510  
511 // each value in the SET is an AttributeTypeAndValue sequence
512 // containing first a type (an OID) and second a value (defined by
513 // the OID)
514 for(var i = 0; i < set.value.length; ++i) {
515 obj = {};
516 attr = set.value[i];
517 obj.type = asn1.derToOid(attr.value[0].value);
518 obj.value = attr.value[1].value;
519 obj.valueTagClass = attr.value[1].type;
520 // if the OID is known, get its name and short name
521 if(obj.type in oids) {
522 obj.name = oids[obj.type];
523 if(obj.name in _shortNames) {
524 obj.shortName = _shortNames[obj.name];
525 }
526 }
527 if(md) {
528 md.update(obj.type);
529 md.update(obj.value);
530 }
531 rval.push(obj);
532 }
533 }
534  
535 return rval;
536 };
537  
538 /**
539 * Converts ASN.1 CRIAttributes into an array with objects that have type and
540 * value properties.
541 *
542 * @param attributes the CRIAttributes to convert.
543 */
544 pki.CRIAttributesAsArray = function(attributes) {
545 var rval = [];
546  
547 // each value in 'attributes' in is a SEQUENCE with an OID and a SET
548 for(var si = 0; si < attributes.length; ++si) {
549 // get the attribute sequence
550 var seq = attributes[si];
551  
552 // each value in the SEQUENCE containing first a type (an OID) and
553 // second a set of values (defined by the OID)
554 var type = asn1.derToOid(seq.value[0].value);
555 var values = seq.value[1].value;
556 for(var vi = 0; vi < values.length; ++vi) {
557 var obj = {};
558 obj.type = type;
559 obj.value = values[vi].value;
560 obj.valueTagClass = values[vi].type;
561 // if the OID is known, get its name and short name
562 if(obj.type in oids) {
563 obj.name = oids[obj.type];
564 if(obj.name in _shortNames) {
565 obj.shortName = _shortNames[obj.name];
566 }
567 }
568 // parse extensions
569 if(obj.type === oids.extensionRequest) {
570 obj.extensions = [];
571 for(var ei = 0; ei < obj.value.length; ++ei) {
572 obj.extensions.push(pki.certificateExtensionFromAsn1(obj.value[ei]));
573 }
574 }
575 rval.push(obj);
576 }
577 }
578  
579 return rval;
580 };
581  
582 /**
583 * Gets an issuer or subject attribute from its name, type, or short name.
584 *
585 * @param obj the issuer or subject object.
586 * @param options a short name string or an object with:
587 * shortName the short name for the attribute.
588 * name the name for the attribute.
589 * type the type for the attribute.
590 *
591 * @return the attribute.
592 */
593 function _getAttribute(obj, options) {
594 if(typeof options === 'string') {
595 options = {shortName: options};
596 }
597  
598 var rval = null;
599 var attr;
600 for(var i = 0; rval === null && i < obj.attributes.length; ++i) {
601 attr = obj.attributes[i];
602 if(options.type && options.type === attr.type) {
603 rval = attr;
604 } else if(options.name && options.name === attr.name) {
605 rval = attr;
606 } else if(options.shortName && options.shortName === attr.shortName) {
607 rval = attr;
608 }
609 }
610 return rval;
611 }
612  
613 /**
614 * Converts signature parameters from ASN.1 structure.
615 *
616 * Currently only RSASSA-PSS supported. The PKCS#1 v1.5 signature scheme had
617 * no parameters.
618 *
619 * RSASSA-PSS-params ::= SEQUENCE {
620 * hashAlgorithm [0] HashAlgorithm DEFAULT
621 * sha1Identifier,
622 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT
623 * mgf1SHA1Identifier,
624 * saltLength [2] INTEGER DEFAULT 20,
625 * trailerField [3] INTEGER DEFAULT 1
626 * }
627 *
628 * HashAlgorithm ::= AlgorithmIdentifier
629 *
630 * MaskGenAlgorithm ::= AlgorithmIdentifier
631 *
632 * AlgorithmIdentifer ::= SEQUENCE {
633 * algorithm OBJECT IDENTIFIER,
634 * parameters ANY DEFINED BY algorithm OPTIONAL
635 * }
636 *
637 * @param oid The OID specifying the signature algorithm
638 * @param obj The ASN.1 structure holding the parameters
639 * @param fillDefaults Whether to use return default values where omitted
640 * @return signature parameter object
641 */
642 var _readSignatureParameters = function(oid, obj, fillDefaults) {
643 var params = {};
644  
645 if(oid !== oids['RSASSA-PSS']) {
646 return params;
647 }
648  
649 if(fillDefaults) {
650 params = {
651 hash: {
652 algorithmOid: oids['sha1']
653 },
654 mgf: {
655 algorithmOid: oids['mgf1'],
656 hash: {
657 algorithmOid: oids['sha1']
658 }
659 },
660 saltLength: 20
661 };
662 }
663  
664 var capture = {};
665 var errors = [];
666 if(!asn1.validate(obj, rsassaPssParameterValidator, capture, errors)) {
667 var error = new Error('Cannot read RSASSA-PSS parameter block.');
668 error.errors = errors;
669 throw error;
670 }
671  
672 if(capture.hashOid !== undefined) {
673 params.hash = params.hash || {};
674 params.hash.algorithmOid = asn1.derToOid(capture.hashOid);
675 }
676  
677 if(capture.maskGenOid !== undefined) {
678 params.mgf = params.mgf || {};
679 params.mgf.algorithmOid = asn1.derToOid(capture.maskGenOid);
680 params.mgf.hash = params.mgf.hash || {};
681 params.mgf.hash.algorithmOid = asn1.derToOid(capture.maskGenHashOid);
682 }
683  
684 if(capture.saltLength !== undefined) {
685 params.saltLength = capture.saltLength.charCodeAt(0);
686 }
687  
688 return params;
689 };
690  
691 /**
692 * Converts an X.509 certificate from PEM format.
693 *
694 * Note: If the certificate is to be verified then compute hash should
695 * be set to true. This will scan the TBSCertificate part of the ASN.1
696 * object while it is converted so it doesn't need to be converted back
697 * to ASN.1-DER-encoding later.
698 *
699 * @param pem the PEM-formatted certificate.
700 * @param computeHash true to compute the hash for verification.
701 * @param strict true to be strict when checking ASN.1 value lengths, false to
702 * allow truncated values (default: true).
703 *
704 * @return the certificate.
705 */
706 pki.certificateFromPem = function(pem, computeHash, strict) {
707 var msg = forge.pem.decode(pem)[0];
708  
709 if(msg.type !== 'CERTIFICATE' &&
710 msg.type !== 'X509 CERTIFICATE' &&
711 msg.type !== 'TRUSTED CERTIFICATE') {
712 var error = new Error('Could not convert certificate from PEM; PEM header type ' +
713 'is not "CERTIFICATE", "X509 CERTIFICATE", or "TRUSTED CERTIFICATE".');
714 error.headerType = msg.type;
715 throw error;
716 }
717 if(msg.procType && msg.procType.type === 'ENCRYPTED') {
718 throw new Error('Could not convert certificate from PEM; PEM is encrypted.');
719 }
720  
721 // convert DER to ASN.1 object
722 var obj = asn1.fromDer(msg.body, strict);
723  
724 return pki.certificateFromAsn1(obj, computeHash);
725 };
726  
727 /**
728 * Converts an X.509 certificate to PEM format.
729 *
730 * @param cert the certificate.
731 * @param maxline the maximum characters per line, defaults to 64.
732 *
733 * @return the PEM-formatted certificate.
734 */
735 pki.certificateToPem = function(cert, maxline) {
736 // convert to ASN.1, then DER, then PEM-encode
737 var msg = {
738 type: 'CERTIFICATE',
739 body: asn1.toDer(pki.certificateToAsn1(cert)).getBytes()
740 };
741 return forge.pem.encode(msg, {maxline: maxline});
742 };
743  
744 /**
745 * Converts an RSA public key from PEM format.
746 *
747 * @param pem the PEM-formatted public key.
748 *
749 * @return the public key.
750 */
751 pki.publicKeyFromPem = function(pem) {
752 var msg = forge.pem.decode(pem)[0];
753  
754 if(msg.type !== 'PUBLIC KEY' && msg.type !== 'RSA PUBLIC KEY') {
755 var error = new Error('Could not convert public key from PEM; PEM header ' +
756 'type is not "PUBLIC KEY" or "RSA PUBLIC KEY".');
757 error.headerType = msg.type;
758 throw error;
759 }
760 if(msg.procType && msg.procType.type === 'ENCRYPTED') {
761 throw new Error('Could not convert public key from PEM; PEM is encrypted.');
762 }
763  
764 // convert DER to ASN.1 object
765 var obj = asn1.fromDer(msg.body);
766  
767 return pki.publicKeyFromAsn1(obj);
768 };
769  
770 /**
771 * Converts an RSA public key to PEM format (using a SubjectPublicKeyInfo).
772 *
773 * @param key the public key.
774 * @param maxline the maximum characters per line, defaults to 64.
775 *
776 * @return the PEM-formatted public key.
777 */
778 pki.publicKeyToPem = function(key, maxline) {
779 // convert to ASN.1, then DER, then PEM-encode
780 var msg = {
781 type: 'PUBLIC KEY',
782 body: asn1.toDer(pki.publicKeyToAsn1(key)).getBytes()
783 };
784 return forge.pem.encode(msg, {maxline: maxline});
785 };
786  
787 /**
788 * Converts an RSA public key to PEM format (using an RSAPublicKey).
789 *
790 * @param key the public key.
791 * @param maxline the maximum characters per line, defaults to 64.
792 *
793 * @return the PEM-formatted public key.
794 */
795 pki.publicKeyToRSAPublicKeyPem = function(key, maxline) {
796 // convert to ASN.1, then DER, then PEM-encode
797 var msg = {
798 type: 'RSA PUBLIC KEY',
799 body: asn1.toDer(pki.publicKeyToRSAPublicKey(key)).getBytes()
800 };
801 return forge.pem.encode(msg, {maxline: maxline});
802 };
803  
804 /**
805 * Gets a fingerprint for the given public key.
806 *
807 * @param options the options to use.
808 * [md] the message digest object to use (defaults to forge.md.sha1).
809 * [type] the type of fingerprint, such as 'RSAPublicKey',
810 * 'SubjectPublicKeyInfo' (defaults to 'RSAPublicKey').
811 * [encoding] an alternative output encoding, such as 'hex'
812 * (defaults to none, outputs a byte buffer).
813 * [delimiter] the delimiter to use between bytes for 'hex' encoded
814 * output, eg: ':' (defaults to none).
815 *
816 * @return the fingerprint as a byte buffer or other encoding based on options.
817 */
818 pki.getPublicKeyFingerprint = function(key, options) {
819 options = options || {};
820 var md = options.md || forge.md.sha1.create();
821 var type = options.type || 'RSAPublicKey';
822  
823 var bytes;
824 switch(type) {
825 case 'RSAPublicKey':
826 bytes = asn1.toDer(pki.publicKeyToRSAPublicKey(key)).getBytes();
827 break;
828 case 'SubjectPublicKeyInfo':
829 bytes = asn1.toDer(pki.publicKeyToAsn1(key)).getBytes();
830 break;
831 default:
832 throw new Error('Unknown fingerprint type "' + options.type + '".');
833 }
834  
835 // hash public key bytes
836 md.start();
837 md.update(bytes);
838 var digest = md.digest();
839 if(options.encoding === 'hex') {
840 var hex = digest.toHex();
841 if(options.delimiter) {
842 return hex.match(/.{2}/g).join(options.delimiter);
843 }
844 return hex;
845 } else if(options.encoding === 'binary') {
846 return digest.getBytes();
847 } else if(options.encoding) {
848 throw new Error('Unknown encoding "' + options.encoding + '".');
849 }
850 return digest;
851 };
852  
853 /**
854 * Converts a PKCS#10 certification request (CSR) from PEM format.
855 *
856 * Note: If the certification request is to be verified then compute hash
857 * should be set to true. This will scan the CertificationRequestInfo part of
858 * the ASN.1 object while it is converted so it doesn't need to be converted
859 * back to ASN.1-DER-encoding later.
860 *
861 * @param pem the PEM-formatted certificate.
862 * @param computeHash true to compute the hash for verification.
863 * @param strict true to be strict when checking ASN.1 value lengths, false to
864 * allow truncated values (default: true).
865 *
866 * @return the certification request (CSR).
867 */
868 pki.certificationRequestFromPem = function(pem, computeHash, strict) {
869 var msg = forge.pem.decode(pem)[0];
870  
871 if(msg.type !== 'CERTIFICATE REQUEST') {
872 var error = new Error('Could not convert certification request from PEM; ' +
873 'PEM header type is not "CERTIFICATE REQUEST".');
874 error.headerType = msg.type;
875 throw error;
876 }
877 if(msg.procType && msg.procType.type === 'ENCRYPTED') {
878 throw new Error('Could not convert certification request from PEM; ' +
879 'PEM is encrypted.');
880 }
881  
882 // convert DER to ASN.1 object
883 var obj = asn1.fromDer(msg.body, strict);
884  
885 return pki.certificationRequestFromAsn1(obj, computeHash);
886 };
887  
888 /**
889 * Converts a PKCS#10 certification request (CSR) to PEM format.
890 *
891 * @param csr the certification request.
892 * @param maxline the maximum characters per line, defaults to 64.
893 *
894 * @return the PEM-formatted certification request.
895 */
896 pki.certificationRequestToPem = function(csr, maxline) {
897 // convert to ASN.1, then DER, then PEM-encode
898 var msg = {
899 type: 'CERTIFICATE REQUEST',
900 body: asn1.toDer(pki.certificationRequestToAsn1(csr)).getBytes()
901 };
902 return forge.pem.encode(msg, {maxline: maxline});
903 };
904  
905 /**
906 * Creates an empty X.509v3 RSA certificate.
907 *
908 * @return the certificate.
909 */
910 pki.createCertificate = function() {
911 var cert = {};
912 cert.version = 0x02;
913 cert.serialNumber = '00';
914 cert.signatureOid = null;
915 cert.signature = null;
916 cert.siginfo = {};
917 cert.siginfo.algorithmOid = null;
918 cert.validity = {};
919 cert.validity.notBefore = new Date();
920 cert.validity.notAfter = new Date();
921  
922 cert.issuer = {};
923 cert.issuer.getField = function(sn) {
924 return _getAttribute(cert.issuer, sn);
925 };
926 cert.issuer.addField = function(attr) {
927 _fillMissingFields([attr]);
928 cert.issuer.attributes.push(attr);
929 };
930 cert.issuer.attributes = [];
931 cert.issuer.hash = null;
932  
933 cert.subject = {};
934 cert.subject.getField = function(sn) {
935 return _getAttribute(cert.subject, sn);
936 };
937 cert.subject.addField = function(attr) {
938 _fillMissingFields([attr]);
939 cert.subject.attributes.push(attr);
940 };
941 cert.subject.attributes = [];
942 cert.subject.hash = null;
943  
944 cert.extensions = [];
945 cert.publicKey = null;
946 cert.md = null;
947  
948 /**
949 * Sets the subject of this certificate.
950 *
951 * @param attrs the array of subject attributes to use.
952 * @param uniqueId an optional a unique ID to use.
953 */
954 cert.setSubject = function(attrs, uniqueId) {
955 // set new attributes, clear hash
956 _fillMissingFields(attrs);
957 cert.subject.attributes = attrs;
958 delete cert.subject.uniqueId;
959 if(uniqueId) {
960 // TODO: support arbitrary bit length ids
961 cert.subject.uniqueId = uniqueId;
962 }
963 cert.subject.hash = null;
964 };
965  
966 /**
967 * Sets the issuer of this certificate.
968 *
969 * @param attrs the array of issuer attributes to use.
970 * @param uniqueId an optional a unique ID to use.
971 */
972 cert.setIssuer = function(attrs, uniqueId) {
973 // set new attributes, clear hash
974 _fillMissingFields(attrs);
975 cert.issuer.attributes = attrs;
976 delete cert.issuer.uniqueId;
977 if(uniqueId) {
978 // TODO: support arbitrary bit length ids
979 cert.issuer.uniqueId = uniqueId;
980 }
981 cert.issuer.hash = null;
982 };
983  
984 /**
985 * Sets the extensions of this certificate.
986 *
987 * @param exts the array of extensions to use.
988 */
989 cert.setExtensions = function(exts) {
990 for(var i = 0; i < exts.length; ++i) {
991 _fillMissingExtensionFields(exts[i], {cert: cert});
992 }
993 // set new extensions
994 cert.extensions = exts;
995 };
996  
997 /**
998 * Gets an extension by its name or id.
999 *
1000 * @param options the name to use or an object with:
1001 * name the name to use.
1002 * id the id to use.
1003 *
1004 * @return the extension or null if not found.
1005 */
1006 cert.getExtension = function(options) {
1007 if(typeof options === 'string') {
1008 options = {name: options};
1009 }
1010  
1011 var rval = null;
1012 var ext;
1013 for(var i = 0; rval === null && i < cert.extensions.length; ++i) {
1014 ext = cert.extensions[i];
1015 if(options.id && ext.id === options.id) {
1016 rval = ext;
1017 } else if(options.name && ext.name === options.name) {
1018 rval = ext;
1019 }
1020 }
1021 return rval;
1022 };
1023  
1024 /**
1025 * Signs this certificate using the given private key.
1026 *
1027 * @param key the private key to sign with.
1028 * @param md the message digest object to use (defaults to forge.md.sha1).
1029 */
1030 cert.sign = function(key, md) {
1031 // TODO: get signature OID from private key
1032 cert.md = md || forge.md.sha1.create();
1033 var algorithmOid = oids[cert.md.algorithm + 'WithRSAEncryption'];
1034 if(!algorithmOid) {
1035 var error = new Error('Could not compute certificate digest. ' +
1036 'Unknown message digest algorithm OID.');
1037 error.algorithm = cert.md.algorithm;
1038 throw error;
1039 }
1040 cert.signatureOid = cert.siginfo.algorithmOid = algorithmOid;
1041  
1042 // get TBSCertificate, convert to DER
1043 cert.tbsCertificate = pki.getTBSCertificate(cert);
1044 var bytes = asn1.toDer(cert.tbsCertificate);
1045  
1046 // digest and sign
1047 cert.md.update(bytes.getBytes());
1048 cert.signature = key.sign(cert.md);
1049 };
1050  
1051 /**
1052 * Attempts verify the signature on the passed certificate using this
1053 * certificate's public key.
1054 *
1055 * @param child the certificate to verify.
1056 *
1057 * @return true if verified, false if not.
1058 */
1059 cert.verify = function(child) {
1060 var rval = false;
1061  
1062 if(!cert.issued(child)) {
1063 var issuer = child.issuer;
1064 var subject = cert.subject;
1065 var error = new Error('The parent certificate did not issue the given child ' +
1066 'certificate; the child certificate\'s issuer does not match the ' +
1067 'parent\'s subject.');
1068 error.expectedIssuer = issuer.attributes;
1069 error.actualIssuer = subject.attributes;
1070 throw error;
1071 }
1072  
1073 var md = child.md;
1074 if(md === null) {
1075 // check signature OID for supported signature types
1076 if(child.signatureOid in oids) {
1077 var oid = oids[child.signatureOid];
1078 switch(oid) {
1079 case 'sha1WithRSAEncryption':
1080 md = forge.md.sha1.create();
1081 break;
1082 case 'md5WithRSAEncryption':
1083 md = forge.md.md5.create();
1084 break;
1085 case 'sha256WithRSAEncryption':
1086 md = forge.md.sha256.create();
1087 break;
1088 case 'sha512WithRSAEncryption':
1089 md = forge.md.sha512.create();
1090 break;
1091 case 'RSASSA-PSS':
1092 md = forge.md.sha256.create();
1093 break;
1094 }
1095 }
1096 if(md === null) {
1097 var error = new Error('Could not compute certificate digest. ' +
1098 'Unknown signature OID.');
1099 error.signatureOid = child.signatureOid;
1100 throw error;
1101 }
1102  
1103 // produce DER formatted TBSCertificate and digest it
1104 var tbsCertificate = child.tbsCertificate || pki.getTBSCertificate(child);
1105 var bytes = asn1.toDer(tbsCertificate);
1106 md.update(bytes.getBytes());
1107 }
1108  
1109 if(md !== null) {
1110 var scheme;
1111  
1112 switch(child.signatureOid) {
1113 case oids.sha1WithRSAEncryption:
1114 scheme = undefined; /* use PKCS#1 v1.5 padding scheme */
1115 break;
1116 case oids['RSASSA-PSS']:
1117 var hash, mgf;
1118  
1119 /* initialize mgf */
1120 hash = oids[child.signatureParameters.mgf.hash.algorithmOid];
1121 if(hash === undefined || forge.md[hash] === undefined) {
1122 var error = new Error('Unsupported MGF hash function.');
1123 error.oid = child.signatureParameters.mgf.hash.algorithmOid;
1124 error.name = hash;
1125 throw error;
1126 }
1127  
1128 mgf = oids[child.signatureParameters.mgf.algorithmOid];
1129 if(mgf === undefined || forge.mgf[mgf] === undefined) {
1130 var error = new Error('Unsupported MGF function.');
1131 error.oid = child.signatureParameters.mgf.algorithmOid;
1132 error.name = mgf;
1133 throw error;
1134 }
1135  
1136 mgf = forge.mgf[mgf].create(forge.md[hash].create());
1137  
1138 /* initialize hash function */
1139 hash = oids[child.signatureParameters.hash.algorithmOid];
1140 if(hash === undefined || forge.md[hash] === undefined) {
1141 throw {
1142 message: 'Unsupported RSASSA-PSS hash function.',
1143 oid: child.signatureParameters.hash.algorithmOid,
1144 name: hash
1145 };
1146 }
1147  
1148 scheme = forge.pss.create(forge.md[hash].create(), mgf,
1149 child.signatureParameters.saltLength);
1150 break;
1151 }
1152  
1153 // verify signature on cert using public key
1154 rval = cert.publicKey.verify(
1155 md.digest().getBytes(), child.signature, scheme);
1156 }
1157  
1158 return rval;
1159 };
1160  
1161 /**
1162 * Returns true if this certificate's issuer matches the passed
1163 * certificate's subject. Note that no signature check is performed.
1164 *
1165 * @param parent the certificate to check.
1166 *
1167 * @return true if this certificate's issuer matches the passed certificate's
1168 * subject.
1169 */
1170 cert.isIssuer = function(parent) {
1171 var rval = false;
1172  
1173 var i = cert.issuer;
1174 var s = parent.subject;
1175  
1176 // compare hashes if present
1177 if(i.hash && s.hash) {
1178 rval = (i.hash === s.hash);
1179 } else if(i.attributes.length === s.attributes.length) {
1180 // all attributes are the same so issuer matches subject
1181 rval = true;
1182 var iattr, sattr;
1183 for(var n = 0; rval && n < i.attributes.length; ++n) {
1184 iattr = i.attributes[n];
1185 sattr = s.attributes[n];
1186 if(iattr.type !== sattr.type || iattr.value !== sattr.value) {
1187 // attribute mismatch
1188 rval = false;
1189 }
1190 }
1191 }
1192  
1193 return rval;
1194 };
1195  
1196 /**
1197 * Returns true if this certificate's subject matches the issuer of the
1198 * given certificate). Note that not signature check is performed.
1199 *
1200 * @param child the certificate to check.
1201 *
1202 * @return true if this certificate's subject matches the passed
1203 * certificate's issuer.
1204 */
1205 cert.issued = function(child) {
1206 return child.isIssuer(cert);
1207 };
1208  
1209 /**
1210 * Generates the subjectKeyIdentifier for this certificate as byte buffer.
1211 *
1212 * @return the subjectKeyIdentifier for this certificate as byte buffer.
1213 */
1214 cert.generateSubjectKeyIdentifier = function() {
1215 /* See: 4.2.1.2 section of the the RFC3280, keyIdentifier is either:
1216  
1217 (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
1218 value of the BIT STRING subjectPublicKey (excluding the tag,
1219 length, and number of unused bits).
1220  
1221 (2) The keyIdentifier is composed of a four bit type field with
1222 the value 0100 followed by the least significant 60 bits of the
1223 SHA-1 hash of the value of the BIT STRING subjectPublicKey
1224 (excluding the tag, length, and number of unused bit string bits).
1225 */
1226  
1227 // skipping the tag, length, and number of unused bits is the same
1228 // as just using the RSAPublicKey (for RSA keys, which are the
1229 // only ones supported)
1230 return pki.getPublicKeyFingerprint(cert.publicKey, {type: 'RSAPublicKey'});
1231 };
1232  
1233 /**
1234 * Verifies the subjectKeyIdentifier extension value for this certificate
1235 * against its public key. If no extension is found, false will be
1236 * returned.
1237 *
1238 * @return true if verified, false if not.
1239 */
1240 cert.verifySubjectKeyIdentifier = function() {
1241 var oid = oids['subjectKeyIdentifier'];
1242 for(var i = 0; i < cert.extensions.length; ++i) {
1243 var ext = cert.extensions[i];
1244 if(ext.id === oid) {
1245 var ski = cert.generateSubjectKeyIdentifier().getBytes();
1246 return (forge.util.hexToBytes(ext.subjectKeyIdentifier) === ski);
1247 }
1248 }
1249 return false;
1250 };
1251  
1252 return cert;
1253 };
1254  
1255 /**
1256 * Converts an X.509v3 RSA certificate from an ASN.1 object.
1257 *
1258 * Note: If the certificate is to be verified then compute hash should
1259 * be set to true. There is currently no implementation for converting
1260 * a certificate back to ASN.1 so the TBSCertificate part of the ASN.1
1261 * object needs to be scanned before the cert object is created.
1262 *
1263 * @param obj the asn1 representation of an X.509v3 RSA certificate.
1264 * @param computeHash true to compute the hash for verification.
1265 *
1266 * @return the certificate.
1267 */
1268 pki.certificateFromAsn1 = function(obj, computeHash) {
1269 // validate certificate and capture data
1270 var capture = {};
1271 var errors = [];
1272 if(!asn1.validate(obj, x509CertificateValidator, capture, errors)) {
1273 var error = new Error('Cannot read X.509 certificate. ' +
1274 'ASN.1 object is not an X509v3 Certificate.');
1275 error.errors = errors;
1276 throw error;
1277 }
1278  
1279 // get oid
1280 var oid = asn1.derToOid(capture.publicKeyOid);
1281 if(oid !== pki.oids.rsaEncryption) {
1282 throw new Error('Cannot read public key. OID is not RSA.');
1283 }
1284  
1285 // create certificate
1286 var cert = pki.createCertificate();
1287 cert.version = capture.certVersion ?
1288 capture.certVersion.charCodeAt(0) : 0;
1289 var serial = forge.util.createBuffer(capture.certSerialNumber);
1290 cert.serialNumber = serial.toHex();
1291 cert.signatureOid = forge.asn1.derToOid(capture.certSignatureOid);
1292 cert.signatureParameters = _readSignatureParameters(
1293 cert.signatureOid, capture.certSignatureParams, true);
1294 cert.siginfo.algorithmOid = forge.asn1.derToOid(capture.certinfoSignatureOid);
1295 cert.siginfo.parameters = _readSignatureParameters(cert.siginfo.algorithmOid,
1296 capture.certinfoSignatureParams, false);
1297 cert.signature = capture.certSignature;
1298  
1299 var validity = [];
1300 if(capture.certValidity1UTCTime !== undefined) {
1301 validity.push(asn1.utcTimeToDate(capture.certValidity1UTCTime));
1302 }
1303 if(capture.certValidity2GeneralizedTime !== undefined) {
1304 validity.push(asn1.generalizedTimeToDate(
1305 capture.certValidity2GeneralizedTime));
1306 }
1307 if(capture.certValidity3UTCTime !== undefined) {
1308 validity.push(asn1.utcTimeToDate(capture.certValidity3UTCTime));
1309 }
1310 if(capture.certValidity4GeneralizedTime !== undefined) {
1311 validity.push(asn1.generalizedTimeToDate(
1312 capture.certValidity4GeneralizedTime));
1313 }
1314 if(validity.length > 2) {
1315 throw new Error('Cannot read notBefore/notAfter validity times; more ' +
1316 'than two times were provided in the certificate.');
1317 }
1318 if(validity.length < 2) {
1319 throw new Error('Cannot read notBefore/notAfter validity times; they ' +
1320 'were not provided as either UTCTime or GeneralizedTime.');
1321 }
1322 cert.validity.notBefore = validity[0];
1323 cert.validity.notAfter = validity[1];
1324  
1325 // keep TBSCertificate to preserve signature when exporting
1326 cert.tbsCertificate = capture.tbsCertificate;
1327  
1328 if(computeHash) {
1329 // check signature OID for supported signature types
1330 cert.md = null;
1331 if(cert.signatureOid in oids) {
1332 var oid = oids[cert.signatureOid];
1333 switch(oid) {
1334 case 'sha1WithRSAEncryption':
1335 cert.md = forge.md.sha1.create();
1336 break;
1337 case 'md5WithRSAEncryption':
1338 cert.md = forge.md.md5.create();
1339 break;
1340 case 'sha256WithRSAEncryption':
1341 cert.md = forge.md.sha256.create();
1342 break;
1343 case 'sha512WithRSAEncryption':
1344 cert.md = forge.md.sha512.create();
1345 break;
1346 case 'RSASSA-PSS':
1347 cert.md = forge.md.sha256.create();
1348 break;
1349 }
1350 }
1351 if(cert.md === null) {
1352 var error = new Error('Could not compute certificate digest. ' +
1353 'Unknown signature OID.');
1354 error.signatureOid = cert.signatureOid;
1355 throw error;
1356 }
1357  
1358 // produce DER formatted TBSCertificate and digest it
1359 var bytes = asn1.toDer(cert.tbsCertificate);
1360 cert.md.update(bytes.getBytes());
1361 }
1362  
1363 // handle issuer, build issuer message digest
1364 var imd = forge.md.sha1.create();
1365 cert.issuer.getField = function(sn) {
1366 return _getAttribute(cert.issuer, sn);
1367 };
1368 cert.issuer.addField = function(attr) {
1369 _fillMissingFields([attr]);
1370 cert.issuer.attributes.push(attr);
1371 };
1372 cert.issuer.attributes = pki.RDNAttributesAsArray(capture.certIssuer, imd);
1373 if(capture.certIssuerUniqueId) {
1374 cert.issuer.uniqueId = capture.certIssuerUniqueId;
1375 }
1376 cert.issuer.hash = imd.digest().toHex();
1377  
1378 // handle subject, build subject message digest
1379 var smd = forge.md.sha1.create();
1380 cert.subject.getField = function(sn) {
1381 return _getAttribute(cert.subject, sn);
1382 };
1383 cert.subject.addField = function(attr) {
1384 _fillMissingFields([attr]);
1385 cert.subject.attributes.push(attr);
1386 };
1387 cert.subject.attributes = pki.RDNAttributesAsArray(capture.certSubject, smd);
1388 if(capture.certSubjectUniqueId) {
1389 cert.subject.uniqueId = capture.certSubjectUniqueId;
1390 }
1391 cert.subject.hash = smd.digest().toHex();
1392  
1393 // handle extensions
1394 if(capture.certExtensions) {
1395 cert.extensions = pki.certificateExtensionsFromAsn1(capture.certExtensions);
1396 } else {
1397 cert.extensions = [];
1398 }
1399  
1400 // convert RSA public key from ASN.1
1401 cert.publicKey = pki.publicKeyFromAsn1(capture.subjectPublicKeyInfo);
1402  
1403 return cert;
1404 };
1405  
1406 /**
1407 * Converts an ASN.1 extensions object (with extension sequences as its
1408 * values) into an array of extension objects with types and values.
1409 *
1410 * Supported extensions:
1411 *
1412 * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
1413 * KeyUsage ::= BIT STRING {
1414 * digitalSignature (0),
1415 * nonRepudiation (1),
1416 * keyEncipherment (2),
1417 * dataEncipherment (3),
1418 * keyAgreement (4),
1419 * keyCertSign (5),
1420 * cRLSign (6),
1421 * encipherOnly (7),
1422 * decipherOnly (8)
1423 * }
1424 *
1425 * id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 }
1426 * BasicConstraints ::= SEQUENCE {
1427 * cA BOOLEAN DEFAULT FALSE,
1428 * pathLenConstraint INTEGER (0..MAX) OPTIONAL
1429 * }
1430 *
1431 * subjectAltName EXTENSION ::= {
1432 * SYNTAX GeneralNames
1433 * IDENTIFIED BY id-ce-subjectAltName
1434 * }
1435 *
1436 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1437 *
1438 * GeneralName ::= CHOICE {
1439 * otherName [0] INSTANCE OF OTHER-NAME,
1440 * rfc822Name [1] IA5String,
1441 * dNSName [2] IA5String,
1442 * x400Address [3] ORAddress,
1443 * directoryName [4] Name,
1444 * ediPartyName [5] EDIPartyName,
1445 * uniformResourceIdentifier [6] IA5String,
1446 * IPAddress [7] OCTET STRING,
1447 * registeredID [8] OBJECT IDENTIFIER
1448 * }
1449 *
1450 * OTHER-NAME ::= TYPE-IDENTIFIER
1451 *
1452 * EDIPartyName ::= SEQUENCE {
1453 * nameAssigner [0] DirectoryString {ub-name} OPTIONAL,
1454 * partyName [1] DirectoryString {ub-name}
1455 * }
1456 *
1457 * @param exts the extensions ASN.1 with extension sequences to parse.
1458 *
1459 * @return the array.
1460 */
1461 pki.certificateExtensionsFromAsn1 = function(exts) {
1462 var rval = [];
1463 for(var i = 0; i < exts.value.length; ++i) {
1464 // get extension sequence
1465 var extseq = exts.value[i];
1466 for(var ei = 0; ei < extseq.value.length; ++ei) {
1467 rval.push(pki.certificateExtensionFromAsn1(extseq.value[ei]));
1468 }
1469 }
1470  
1471 return rval;
1472 };
1473  
1474 /**
1475 * Parses a single certificate extension from ASN.1.
1476 *
1477 * @param ext the extension in ASN.1 format.
1478 *
1479 * @return the parsed extension as an object.
1480 */
1481 pki.certificateExtensionFromAsn1 = function(ext) {
1482 // an extension has:
1483 // [0] extnID OBJECT IDENTIFIER
1484 // [1] critical BOOLEAN DEFAULT FALSE
1485 // [2] extnValue OCTET STRING
1486 var e = {};
1487 e.id = asn1.derToOid(ext.value[0].value);
1488 e.critical = false;
1489 if(ext.value[1].type === asn1.Type.BOOLEAN) {
1490 e.critical = (ext.value[1].value.charCodeAt(0) !== 0x00);
1491 e.value = ext.value[2].value;
1492 } else {
1493 e.value = ext.value[1].value;
1494 }
1495 // if the oid is known, get its name
1496 if(e.id in oids) {
1497 e.name = oids[e.id];
1498  
1499 // handle key usage
1500 if(e.name === 'keyUsage') {
1501 // get value as BIT STRING
1502 var ev = asn1.fromDer(e.value);
1503 var b2 = 0x00;
1504 var b3 = 0x00;
1505 if(ev.value.length > 1) {
1506 // skip first byte, just indicates unused bits which
1507 // will be padded with 0s anyway
1508 // get bytes with flag bits
1509 b2 = ev.value.charCodeAt(1);
1510 b3 = ev.value.length > 2 ? ev.value.charCodeAt(2) : 0;
1511 }
1512 // set flags
1513 e.digitalSignature = (b2 & 0x80) === 0x80;
1514 e.nonRepudiation = (b2 & 0x40) === 0x40;
1515 e.keyEncipherment = (b2 & 0x20) === 0x20;
1516 e.dataEncipherment = (b2 & 0x10) === 0x10;
1517 e.keyAgreement = (b2 & 0x08) === 0x08;
1518 e.keyCertSign = (b2 & 0x04) === 0x04;
1519 e.cRLSign = (b2 & 0x02) === 0x02;
1520 e.encipherOnly = (b2 & 0x01) === 0x01;
1521 e.decipherOnly = (b3 & 0x80) === 0x80;
1522 } else if(e.name === 'basicConstraints') {
1523 // handle basic constraints
1524 // get value as SEQUENCE
1525 var ev = asn1.fromDer(e.value);
1526 // get cA BOOLEAN flag (defaults to false)
1527 if(ev.value.length > 0 && ev.value[0].type === asn1.Type.BOOLEAN) {
1528 e.cA = (ev.value[0].value.charCodeAt(0) !== 0x00);
1529 } else {
1530 e.cA = false;
1531 }
1532 // get path length constraint
1533 var value = null;
1534 if(ev.value.length > 0 && ev.value[0].type === asn1.Type.INTEGER) {
1535 value = ev.value[0].value;
1536 } else if(ev.value.length > 1) {
1537 value = ev.value[1].value;
1538 }
1539 if(value !== null) {
1540 e.pathLenConstraint = asn1.derToInteger(value);
1541 }
1542 } else if(e.name === 'extKeyUsage') {
1543 // handle extKeyUsage
1544 // value is a SEQUENCE of OIDs
1545 var ev = asn1.fromDer(e.value);
1546 for(var vi = 0; vi < ev.value.length; ++vi) {
1547 var oid = asn1.derToOid(ev.value[vi].value);
1548 if(oid in oids) {
1549 e[oids[oid]] = true;
1550 } else {
1551 e[oid] = true;
1552 }
1553 }
1554 } else if(e.name === 'nsCertType') {
1555 // handle nsCertType
1556 // get value as BIT STRING
1557 var ev = asn1.fromDer(e.value);
1558 var b2 = 0x00;
1559 if(ev.value.length > 1) {
1560 // skip first byte, just indicates unused bits which
1561 // will be padded with 0s anyway
1562 // get bytes with flag bits
1563 b2 = ev.value.charCodeAt(1);
1564 }
1565 // set flags
1566 e.client = (b2 & 0x80) === 0x80;
1567 e.server = (b2 & 0x40) === 0x40;
1568 e.email = (b2 & 0x20) === 0x20;
1569 e.objsign = (b2 & 0x10) === 0x10;
1570 e.reserved = (b2 & 0x08) === 0x08;
1571 e.sslCA = (b2 & 0x04) === 0x04;
1572 e.emailCA = (b2 & 0x02) === 0x02;
1573 e.objCA = (b2 & 0x01) === 0x01;
1574 } else if(
1575 e.name === 'subjectAltName' ||
1576 e.name === 'issuerAltName') {
1577 // handle subjectAltName/issuerAltName
1578 e.altNames = [];
1579  
1580 // ev is a SYNTAX SEQUENCE
1581 var gn;
1582 var ev = asn1.fromDer(e.value);
1583 for(var n = 0; n < ev.value.length; ++n) {
1584 // get GeneralName
1585 gn = ev.value[n];
1586  
1587 var altName = {
1588 type: gn.type,
1589 value: gn.value
1590 };
1591 e.altNames.push(altName);
1592  
1593 // Note: Support for types 1,2,6,7,8
1594 switch(gn.type) {
1595 // rfc822Name
1596 case 1:
1597 // dNSName
1598 case 2:
1599 // uniformResourceIdentifier (URI)
1600 case 6:
1601 break;
1602 // IPAddress
1603 case 7:
1604 // convert to IPv4/IPv6 string representation
1605 altName.ip = forge.util.bytesToIP(gn.value);
1606 break;
1607 // registeredID
1608 case 8:
1609 altName.oid = asn1.derToOid(gn.value);
1610 break;
1611 default:
1612 // unsupported
1613 }
1614 }
1615 } else if(e.name === 'subjectKeyIdentifier') {
1616 // value is an OCTETSTRING w/the hash of the key-type specific
1617 // public key structure (eg: RSAPublicKey)
1618 var ev = asn1.fromDer(e.value);
1619 e.subjectKeyIdentifier = forge.util.bytesToHex(ev.value);
1620 }
1621 }
1622 return e;
1623 };
1624  
1625 /**
1626 * Converts a PKCS#10 certification request (CSR) from an ASN.1 object.
1627 *
1628 * Note: If the certification request is to be verified then compute hash
1629 * should be set to true. There is currently no implementation for converting
1630 * a certificate back to ASN.1 so the CertificationRequestInfo part of the
1631 * ASN.1 object needs to be scanned before the csr object is created.
1632 *
1633 * @param obj the asn1 representation of a PKCS#10 certification request (CSR).
1634 * @param computeHash true to compute the hash for verification.
1635 *
1636 * @return the certification request (CSR).
1637 */
1638 pki.certificationRequestFromAsn1 = function(obj, computeHash) {
1639 // validate certification request and capture data
1640 var capture = {};
1641 var errors = [];
1642 if(!asn1.validate(obj, certificationRequestValidator, capture, errors)) {
1643 var error = new Error('Cannot read PKCS#10 certificate request. ' +
1644 'ASN.1 object is not a PKCS#10 CertificationRequest.');
1645 error.errors = errors;
1646 throw error;
1647 }
1648  
1649 // get oid
1650 var oid = asn1.derToOid(capture.publicKeyOid);
1651 if(oid !== pki.oids.rsaEncryption) {
1652 throw new Error('Cannot read public key. OID is not RSA.');
1653 }
1654  
1655 // create certification request
1656 var csr = pki.createCertificationRequest();
1657 csr.version = capture.csrVersion ? capture.csrVersion.charCodeAt(0) : 0;
1658 csr.signatureOid = forge.asn1.derToOid(capture.csrSignatureOid);
1659 csr.signatureParameters = _readSignatureParameters(
1660 csr.signatureOid, capture.csrSignatureParams, true);
1661 csr.siginfo.algorithmOid = forge.asn1.derToOid(capture.csrSignatureOid);
1662 csr.siginfo.parameters = _readSignatureParameters(
1663 csr.siginfo.algorithmOid, capture.csrSignatureParams, false);
1664 csr.signature = capture.csrSignature;
1665  
1666 // keep CertificationRequestInfo to preserve signature when exporting
1667 csr.certificationRequestInfo = capture.certificationRequestInfo;
1668  
1669 if(computeHash) {
1670 // check signature OID for supported signature types
1671 csr.md = null;
1672 if(csr.signatureOid in oids) {
1673 var oid = oids[csr.signatureOid];
1674 switch(oid) {
1675 case 'sha1WithRSAEncryption':
1676 csr.md = forge.md.sha1.create();
1677 break;
1678 case 'md5WithRSAEncryption':
1679 csr.md = forge.md.md5.create();
1680 break;
1681 case 'sha256WithRSAEncryption':
1682 csr.md = forge.md.sha256.create();
1683 break;
1684 case 'sha512WithRSAEncryption':
1685 csr.md = forge.md.sha512.create();
1686 break;
1687 case 'RSASSA-PSS':
1688 csr.md = forge.md.sha256.create();
1689 break;
1690 }
1691 }
1692 if(csr.md === null) {
1693 var error = new Error('Could not compute certification request digest. ' +
1694 'Unknown signature OID.');
1695 error.signatureOid = csr.signatureOid;
1696 throw error;
1697 }
1698  
1699 // produce DER formatted CertificationRequestInfo and digest it
1700 var bytes = asn1.toDer(csr.certificationRequestInfo);
1701 csr.md.update(bytes.getBytes());
1702 }
1703  
1704 // handle subject, build subject message digest
1705 var smd = forge.md.sha1.create();
1706 csr.subject.getField = function(sn) {
1707 return _getAttribute(csr.subject, sn);
1708 };
1709 csr.subject.addField = function(attr) {
1710 _fillMissingFields([attr]);
1711 csr.subject.attributes.push(attr);
1712 };
1713 csr.subject.attributes = pki.RDNAttributesAsArray(
1714 capture.certificationRequestInfoSubject, smd);
1715 csr.subject.hash = smd.digest().toHex();
1716  
1717 // convert RSA public key from ASN.1
1718 csr.publicKey = pki.publicKeyFromAsn1(capture.subjectPublicKeyInfo);
1719  
1720 // convert attributes from ASN.1
1721 csr.getAttribute = function(sn) {
1722 return _getAttribute(csr, sn);
1723 };
1724 csr.addAttribute = function(attr) {
1725 _fillMissingFields([attr]);
1726 csr.attributes.push(attr);
1727 };
1728 csr.attributes = pki.CRIAttributesAsArray(
1729 capture.certificationRequestInfoAttributes || []);
1730  
1731 return csr;
1732 };
1733  
1734 /**
1735 * Creates an empty certification request (a CSR or certificate signing
1736 * request). Once created, its public key and attributes can be set and then
1737 * it can be signed.
1738 *
1739 * @return the empty certification request.
1740 */
1741 pki.createCertificationRequest = function() {
1742 var csr = {};
1743 csr.version = 0x00;
1744 csr.signatureOid = null;
1745 csr.signature = null;
1746 csr.siginfo = {};
1747 csr.siginfo.algorithmOid = null;
1748  
1749 csr.subject = {};
1750 csr.subject.getField = function(sn) {
1751 return _getAttribute(csr.subject, sn);
1752 };
1753 csr.subject.addField = function(attr) {
1754 _fillMissingFields([attr]);
1755 csr.subject.attributes.push(attr);
1756 };
1757 csr.subject.attributes = [];
1758 csr.subject.hash = null;
1759  
1760 csr.publicKey = null;
1761 csr.attributes = [];
1762 csr.getAttribute = function(sn) {
1763 return _getAttribute(csr, sn);
1764 };
1765 csr.addAttribute = function(attr) {
1766 _fillMissingFields([attr]);
1767 csr.attributes.push(attr);
1768 };
1769 csr.md = null;
1770  
1771 /**
1772 * Sets the subject of this certification request.
1773 *
1774 * @param attrs the array of subject attributes to use.
1775 */
1776 csr.setSubject = function(attrs) {
1777 // set new attributes
1778 _fillMissingFields(attrs);
1779 csr.subject.attributes = attrs;
1780 csr.subject.hash = null;
1781 };
1782  
1783 /**
1784 * Sets the attributes of this certification request.
1785 *
1786 * @param attrs the array of attributes to use.
1787 */
1788 csr.setAttributes = function(attrs) {
1789 // set new attributes
1790 _fillMissingFields(attrs);
1791 csr.attributes = attrs;
1792 };
1793  
1794 /**
1795 * Signs this certification request using the given private key.
1796 *
1797 * @param key the private key to sign with.
1798 * @param md the message digest object to use (defaults to forge.md.sha1).
1799 */
1800 csr.sign = function(key, md) {
1801 // TODO: get signature OID from private key
1802 csr.md = md || forge.md.sha1.create();
1803 var algorithmOid = oids[csr.md.algorithm + 'WithRSAEncryption'];
1804 if(!algorithmOid) {
1805 var error = new Error('Could not compute certification request digest. ' +
1806 'Unknown message digest algorithm OID.');
1807 error.algorithm = csr.md.algorithm;
1808 throw error;
1809 }
1810 csr.signatureOid = csr.siginfo.algorithmOid = algorithmOid;
1811  
1812 // get CertificationRequestInfo, convert to DER
1813 csr.certificationRequestInfo = pki.getCertificationRequestInfo(csr);
1814 var bytes = asn1.toDer(csr.certificationRequestInfo);
1815  
1816 // digest and sign
1817 csr.md.update(bytes.getBytes());
1818 csr.signature = key.sign(csr.md);
1819 };
1820  
1821 /**
1822 * Attempts verify the signature on the passed certification request using
1823 * its public key.
1824 *
1825 * A CSR that has been exported to a file in PEM format can be verified using
1826 * OpenSSL using this command:
1827 *
1828 * openssl req -in <the-csr-pem-file> -verify -noout -text
1829 *
1830 * @return true if verified, false if not.
1831 */
1832 csr.verify = function() {
1833 var rval = false;
1834  
1835 var md = csr.md;
1836 if(md === null) {
1837 // check signature OID for supported signature types
1838 if(csr.signatureOid in oids) {
1839 // TODO: create DRY `OID to md` function
1840 var oid = oids[csr.signatureOid];
1841 switch(oid) {
1842 case 'sha1WithRSAEncryption':
1843 md = forge.md.sha1.create();
1844 break;
1845 case 'md5WithRSAEncryption':
1846 md = forge.md.md5.create();
1847 break;
1848 case 'sha256WithRSAEncryption':
1849 md = forge.md.sha256.create();
1850 break;
1851 case 'sha512WithRSAEncryption':
1852 md = forge.md.sha512.create();
1853 break;
1854 case 'RSASSA-PSS':
1855 md = forge.md.sha256.create();
1856 break;
1857 }
1858 }
1859 if(md === null) {
1860 var error = new Error('Could not compute certification request digest. ' +
1861 'Unknown signature OID.');
1862 error.signatureOid = csr.signatureOid;
1863 throw error;
1864 }
1865  
1866 // produce DER formatted CertificationRequestInfo and digest it
1867 var cri = csr.certificationRequestInfo ||
1868 pki.getCertificationRequestInfo(csr);
1869 var bytes = asn1.toDer(cri);
1870 md.update(bytes.getBytes());
1871 }
1872  
1873 if(md !== null) {
1874 var scheme;
1875  
1876 switch(csr.signatureOid) {
1877 case oids.sha1WithRSAEncryption:
1878 /* use PKCS#1 v1.5 padding scheme */
1879 break;
1880 case oids['RSASSA-PSS']:
1881 var hash, mgf;
1882  
1883 /* initialize mgf */
1884 hash = oids[csr.signatureParameters.mgf.hash.algorithmOid];
1885 if(hash === undefined || forge.md[hash] === undefined) {
1886 var error = new Error('Unsupported MGF hash function.');
1887 error.oid = csr.signatureParameters.mgf.hash.algorithmOid;
1888 error.name = hash;
1889 throw error;
1890 }
1891  
1892 mgf = oids[csr.signatureParameters.mgf.algorithmOid];
1893 if(mgf === undefined || forge.mgf[mgf] === undefined) {
1894 var error = new Error('Unsupported MGF function.');
1895 error.oid = csr.signatureParameters.mgf.algorithmOid;
1896 error.name = mgf;
1897 throw error;
1898 }
1899  
1900 mgf = forge.mgf[mgf].create(forge.md[hash].create());
1901  
1902 /* initialize hash function */
1903 hash = oids[csr.signatureParameters.hash.algorithmOid];
1904 if(hash === undefined || forge.md[hash] === undefined) {
1905 var error = new Error('Unsupported RSASSA-PSS hash function.');
1906 error.oid = csr.signatureParameters.hash.algorithmOid;
1907 error.name = hash;
1908 throw error;
1909 }
1910  
1911 scheme = forge.pss.create(forge.md[hash].create(), mgf,
1912 csr.signatureParameters.saltLength);
1913 break;
1914 }
1915  
1916 // verify signature on csr using its public key
1917 rval = csr.publicKey.verify(
1918 md.digest().getBytes(), csr.signature, scheme);
1919 }
1920  
1921 return rval;
1922 };
1923  
1924 return csr;
1925 };
1926  
1927 /**
1928 * Converts an X.509 subject or issuer to an ASN.1 RDNSequence.
1929 *
1930 * @param obj the subject or issuer (distinguished name).
1931 *
1932 * @return the ASN.1 RDNSequence.
1933 */
1934 function _dnToAsn1(obj) {
1935 // create an empty RDNSequence
1936 var rval = asn1.create(
1937 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
1938  
1939 // iterate over attributes
1940 var attr, set;
1941 var attrs = obj.attributes;
1942 for(var i = 0; i < attrs.length; ++i) {
1943 attr = attrs[i];
1944 var value = attr.value;
1945  
1946 // reuse tag class for attribute value if available
1947 var valueTagClass = asn1.Type.PRINTABLESTRING;
1948 if('valueTagClass' in attr) {
1949 valueTagClass = attr.valueTagClass;
1950  
1951 if(valueTagClass === asn1.Type.UTF8) {
1952 value = forge.util.encodeUtf8(value);
1953 }
1954 // FIXME: handle more encodings
1955 }
1956  
1957 // create a RelativeDistinguishedName set
1958 // each value in the set is an AttributeTypeAndValue first
1959 // containing the type (an OID) and second the value
1960 set = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [
1961 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
1962 // AttributeType
1963 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
1964 asn1.oidToDer(attr.type).getBytes()),
1965 // AttributeValue
1966 asn1.create(asn1.Class.UNIVERSAL, valueTagClass, false, value)
1967 ])
1968 ]);
1969 rval.value.push(set);
1970 }
1971  
1972 return rval;
1973 }
1974  
1975 /**
1976 * Gets all printable attributes (typically of an issuer or subject) in a
1977 * simplified JSON format for display.
1978 *
1979 * @param attrs the attributes.
1980 *
1981 * @return the JSON for display.
1982 */
1983 function _getAttributesAsJson(attrs) {
1984 var rval = {};
1985 for(var i = 0; i < attrs.length; ++i) {
1986 var attr = attrs[i];
1987 if(attr.shortName && (
1988 attr.valueTagClass === asn1.Type.UTF8 ||
1989 attr.valueTagClass === asn1.Type.PRINTABLESTRING ||
1990 attr.valueTagClass === asn1.Type.IA5STRING)) {
1991 var value = attr.value;
1992 if(attr.valueTagClass === asn1.Type.UTF8) {
1993 value = forge.util.encodeUtf8(attr.value);
1994 }
1995 if(!(attr.shortName in rval)) {
1996 rval[attr.shortName] = value;
1997 } else if(forge.util.isArray(rval[attr.shortName])) {
1998 rval[attr.shortName].push(value);
1999 } else {
2000 rval[attr.shortName] = [rval[attr.shortName], value];
2001 }
2002 }
2003 }
2004 return rval;
2005 }
2006  
2007 /**
2008 * Fills in missing fields in attributes.
2009 *
2010 * @param attrs the attributes to fill missing fields in.
2011 */
2012 function _fillMissingFields(attrs) {
2013 var attr;
2014 for(var i = 0; i < attrs.length; ++i) {
2015 attr = attrs[i];
2016  
2017 // populate missing name
2018 if(typeof attr.name === 'undefined') {
2019 if(attr.type && attr.type in pki.oids) {
2020 attr.name = pki.oids[attr.type];
2021 } else if(attr.shortName && attr.shortName in _shortNames) {
2022 attr.name = pki.oids[_shortNames[attr.shortName]];
2023 }
2024 }
2025  
2026 // populate missing type (OID)
2027 if(typeof attr.type === 'undefined') {
2028 if(attr.name && attr.name in pki.oids) {
2029 attr.type = pki.oids[attr.name];
2030 } else {
2031 var error = new Error('Attribute type not specified.');
2032 error.attribute = attr;
2033 throw error;
2034 }
2035 }
2036  
2037 // populate missing shortname
2038 if(typeof attr.shortName === 'undefined') {
2039 if(attr.name && attr.name in _shortNames) {
2040 attr.shortName = _shortNames[attr.name];
2041 }
2042 }
2043  
2044 // convert extensions to value
2045 if(attr.type === oids.extensionRequest) {
2046 attr.valueConstructed = true;
2047 attr.valueTagClass = asn1.Type.SEQUENCE;
2048 if(!attr.value && attr.extensions) {
2049 attr.value = [];
2050 for(var ei = 0; ei < attr.extensions.length; ++ei) {
2051 attr.value.push(pki.certificateExtensionToAsn1(
2052 _fillMissingExtensionFields(attr.extensions[ei])));
2053 }
2054 }
2055 }
2056  
2057 if(typeof attr.value === 'undefined') {
2058 var error = new Error('Attribute value not specified.');
2059 error.attribute = attr;
2060 throw error;
2061 }
2062 }
2063 }
2064  
2065 /**
2066 * Fills in missing fields in certificate extensions.
2067 *
2068 * @param e the extension.
2069 * @param [options] the options to use.
2070 * [cert] the certificate the extensions are for.
2071 *
2072 * @return the extension.
2073 */
2074 function _fillMissingExtensionFields(e, options) {
2075 options = options || {};
2076  
2077 // populate missing name
2078 if(typeof e.name === 'undefined') {
2079 if(e.id && e.id in pki.oids) {
2080 e.name = pki.oids[e.id];
2081 }
2082 }
2083  
2084 // populate missing id
2085 if(typeof e.id === 'undefined') {
2086 if(e.name && e.name in pki.oids) {
2087 e.id = pki.oids[e.name];
2088 } else {
2089 var error = new Error('Extension ID not specified.');
2090 error.extension = e;
2091 throw error;
2092 }
2093 }
2094  
2095 if(typeof e.value !== 'undefined') {
2096 return e;
2097 }
2098  
2099 // handle missing value:
2100  
2101 // value is a BIT STRING
2102 if(e.name === 'keyUsage') {
2103 // build flags
2104 var unused = 0;
2105 var b2 = 0x00;
2106 var b3 = 0x00;
2107 if(e.digitalSignature) {
2108 b2 |= 0x80;
2109 unused = 7;
2110 }
2111 if(e.nonRepudiation) {
2112 b2 |= 0x40;
2113 unused = 6;
2114 }
2115 if(e.keyEncipherment) {
2116 b2 |= 0x20;
2117 unused = 5;
2118 }
2119 if(e.dataEncipherment) {
2120 b2 |= 0x10;
2121 unused = 4;
2122 }
2123 if(e.keyAgreement) {
2124 b2 |= 0x08;
2125 unused = 3;
2126 }
2127 if(e.keyCertSign) {
2128 b2 |= 0x04;
2129 unused = 2;
2130 }
2131 if(e.cRLSign) {
2132 b2 |= 0x02;
2133 unused = 1;
2134 }
2135 if(e.encipherOnly) {
2136 b2 |= 0x01;
2137 unused = 0;
2138 }
2139 if(e.decipherOnly) {
2140 b3 |= 0x80;
2141 unused = 7;
2142 }
2143  
2144 // create bit string
2145 var value = String.fromCharCode(unused);
2146 if(b3 !== 0) {
2147 value += String.fromCharCode(b2) + String.fromCharCode(b3);
2148 } else if(b2 !== 0) {
2149 value += String.fromCharCode(b2);
2150 }
2151 e.value = asn1.create(
2152 asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, value);
2153 } else if(e.name === 'basicConstraints') {
2154 // basicConstraints is a SEQUENCE
2155 e.value = asn1.create(
2156 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2157 // cA BOOLEAN flag defaults to false
2158 if(e.cA) {
2159 e.value.value.push(asn1.create(
2160 asn1.Class.UNIVERSAL, asn1.Type.BOOLEAN, false,
2161 String.fromCharCode(0xFF)));
2162 }
2163 if('pathLenConstraint' in e) {
2164 e.value.value.push(asn1.create(
2165 asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
2166 asn1.integerToDer(e.pathLenConstraint).getBytes()));
2167 }
2168 } else if(e.name === 'extKeyUsage') {
2169 // extKeyUsage is a SEQUENCE of OIDs
2170 e.value = asn1.create(
2171 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2172 var seq = e.value.value;
2173 for(var key in e) {
2174 if(e[key] !== true) {
2175 continue;
2176 }
2177 // key is name in OID map
2178 if(key in oids) {
2179 seq.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID,
2180 false, asn1.oidToDer(oids[key]).getBytes()));
2181 } else if(key.indexOf('.') !== -1) {
2182 // assume key is an OID
2183 seq.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID,
2184 false, asn1.oidToDer(key).getBytes()));
2185 }
2186 }
2187 } else if(e.name === 'nsCertType') {
2188 // nsCertType is a BIT STRING
2189 // build flags
2190 var unused = 0;
2191 var b2 = 0x00;
2192  
2193 if(e.client) {
2194 b2 |= 0x80;
2195 unused = 7;
2196 }
2197 if(e.server) {
2198 b2 |= 0x40;
2199 unused = 6;
2200 }
2201 if(e.email) {
2202 b2 |= 0x20;
2203 unused = 5;
2204 }
2205 if(e.objsign) {
2206 b2 |= 0x10;
2207 unused = 4;
2208 }
2209 if(e.reserved) {
2210 b2 |= 0x08;
2211 unused = 3;
2212 }
2213 if(e.sslCA) {
2214 b2 |= 0x04;
2215 unused = 2;
2216 }
2217 if(e.emailCA) {
2218 b2 |= 0x02;
2219 unused = 1;
2220 }
2221 if(e.objCA) {
2222 b2 |= 0x01;
2223 unused = 0;
2224 }
2225  
2226 // create bit string
2227 var value = String.fromCharCode(unused);
2228 if(b2 !== 0) {
2229 value += String.fromCharCode(b2);
2230 }
2231 e.value = asn1.create(
2232 asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, value);
2233 } else if(e.name === 'subjectAltName' || e.name === 'issuerAltName') {
2234 // SYNTAX SEQUENCE
2235 e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2236  
2237 var altName;
2238 for(var n = 0; n < e.altNames.length; ++n) {
2239 altName = e.altNames[n];
2240 var value = altName.value;
2241 // handle IP
2242 if(altName.type === 7 && altName.ip) {
2243 value = forge.util.bytesFromIP(altName.ip);
2244 if(value === null) {
2245 var error = new Error(
2246 'Extension "ip" value is not a valid IPv4 or IPv6 address.');
2247 error.extension = e;
2248 throw error;
2249 }
2250 } else if(altName.type === 8) {
2251 // handle OID
2252 if(altName.oid) {
2253 value = asn1.oidToDer(asn1.oidToDer(altName.oid));
2254 } else {
2255 // deprecated ... convert value to OID
2256 value = asn1.oidToDer(value);
2257 }
2258 }
2259 e.value.value.push(asn1.create(
2260 asn1.Class.CONTEXT_SPECIFIC, altName.type, false,
2261 value));
2262 }
2263 } else if(e.name === 'subjectKeyIdentifier' && options.cert) {
2264 var ski = options.cert.generateSubjectKeyIdentifier();
2265 e.subjectKeyIdentifier = ski.toHex();
2266 // OCTETSTRING w/digest
2267 e.value = asn1.create(
2268 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, ski.getBytes());
2269 } else if(e.name === 'authorityKeyIdentifier' && options.cert) {
2270 // SYNTAX SEQUENCE
2271 e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2272 var seq = e.value.value;
2273  
2274 if(e.keyIdentifier) {
2275 var keyIdentifier = (e.keyIdentifier === true ?
2276 options.cert.generateSubjectKeyIdentifier().getBytes() :
2277 e.keyIdentifier);
2278 seq.push(
2279 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, false, keyIdentifier));
2280 }
2281  
2282 if(e.authorityCertIssuer) {
2283 var authorityCertIssuer = [
2284 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 4, true, [
2285 _dnToAsn1(e.authorityCertIssuer === true ?
2286 options.cert.issuer : e.authorityCertIssuer)
2287 ])
2288 ];
2289 seq.push(
2290 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, authorityCertIssuer));
2291 }
2292  
2293 if(e.serialNumber) {
2294 var serialNumber = forge.util.hexToBytes(e.serialNumber === true ?
2295 options.cert.serialNumber : e.serialNumber);
2296 seq.push(
2297 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, false, serialNumber));
2298 }
2299 } else if (e.name === 'cRLDistributionPoints') {
2300 e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2301 var seq = e.value.value;
2302  
2303 // Create sub SEQUENCE of DistributionPointName
2304 var subSeq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2305  
2306 // Create fullName CHOICE
2307 var fullNameGeneralNames = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, []);
2308 var altName;
2309 for(var n = 0; n < e.altNames.length; ++n) {
2310 altName = e.altNames[n];
2311 var value = altName.value;
2312 // handle IP
2313 if(altName.type === 7 && altName.ip) {
2314 value = forge.util.bytesFromIP(altName.ip);
2315 if(value === null) {
2316 var error = new Error(
2317 'Extension "ip" value is not a valid IPv4 or IPv6 address.');
2318 error.extension = e;
2319 throw error;
2320 }
2321 } else if(altName.type === 8) {
2322 // handle OID
2323 if(altName.oid) {
2324 value = asn1.oidToDer(asn1.oidToDer(altName.oid));
2325 } else {
2326 // deprecated ... convert value to OID
2327 value = asn1.oidToDer(value);
2328 }
2329 }
2330 fullNameGeneralNames.value.push(asn1.create(
2331 asn1.Class.CONTEXT_SPECIFIC, altName.type, false,
2332 value));
2333 }
2334  
2335 // Add to the parent SEQUENCE
2336 subSeq.value.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [fullNameGeneralNames]));
2337 seq.push(subSeq);
2338 }
2339  
2340 // ensure value has been defined by now
2341 if(typeof e.value === 'undefined') {
2342 var error = new Error('Extension value not specified.');
2343 error.extension = e;
2344 throw error;
2345 }
2346  
2347 return e;
2348 }
2349  
2350 /**
2351 * Convert signature parameters object to ASN.1
2352 *
2353 * @param {String} oid Signature algorithm OID
2354 * @param params The signature parametrs object
2355 * @return ASN.1 object representing signature parameters
2356 */
2357 function _signatureParametersToAsn1(oid, params) {
2358 switch(oid) {
2359 case oids['RSASSA-PSS']:
2360 var parts = [];
2361  
2362 if(params.hash.algorithmOid !== undefined) {
2363 parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [
2364 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2365 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
2366 asn1.oidToDer(params.hash.algorithmOid).getBytes()),
2367 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '')
2368 ])
2369 ]));
2370 }
2371  
2372 if(params.mgf.algorithmOid !== undefined) {
2373 parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [
2374 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2375 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
2376 asn1.oidToDer(params.mgf.algorithmOid).getBytes()),
2377 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2378 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
2379 asn1.oidToDer(params.mgf.hash.algorithmOid).getBytes()),
2380 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '')
2381 ])
2382 ])
2383 ]));
2384 }
2385  
2386 if(params.saltLength !== undefined) {
2387 parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, true, [
2388 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
2389 asn1.integerToDer(params.saltLength).getBytes())
2390 ]));
2391 }
2392  
2393 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, parts);
2394  
2395 default:
2396 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '');
2397 }
2398 }
2399  
2400 /**
2401 * Converts a certification request's attributes to an ASN.1 set of
2402 * CRIAttributes.
2403 *
2404 * @param csr certification request.
2405 *
2406 * @return the ASN.1 set of CRIAttributes.
2407 */
2408 function _CRIAttributesToAsn1(csr) {
2409 // create an empty context-specific container
2410 var rval = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, []);
2411  
2412 // no attributes, return empty container
2413 if(csr.attributes.length === 0) {
2414 return rval;
2415 }
2416  
2417 // each attribute has a sequence with a type and a set of values
2418 var attrs = csr.attributes;
2419 for(var i = 0; i < attrs.length; ++i) {
2420 var attr = attrs[i];
2421 var value = attr.value;
2422  
2423 // reuse tag class for attribute value if available
2424 var valueTagClass = asn1.Type.UTF8;
2425 if('valueTagClass' in attr) {
2426 valueTagClass = attr.valueTagClass;
2427 }
2428 if(valueTagClass === asn1.Type.UTF8) {
2429 value = forge.util.encodeUtf8(value);
2430 }
2431 var valueConstructed = false;
2432 if('valueConstructed' in attr) {
2433 valueConstructed = attr.valueConstructed;
2434 }
2435 // FIXME: handle more encodings
2436  
2437 // create a RelativeDistinguishedName set
2438 // each value in the set is an AttributeTypeAndValue first
2439 // containing the type (an OID) and second the value
2440 var seq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2441 // AttributeType
2442 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
2443 asn1.oidToDer(attr.type).getBytes()),
2444 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [
2445 // AttributeValue
2446 asn1.create(
2447 asn1.Class.UNIVERSAL, valueTagClass, valueConstructed, value)
2448 ])
2449 ]);
2450 rval.value.push(seq);
2451 }
2452  
2453 return rval;
2454 }
2455  
2456 /**
2457 * Gets the ASN.1 TBSCertificate part of an X.509v3 certificate.
2458 *
2459 * @param cert the certificate.
2460 *
2461 * @return the asn1 TBSCertificate.
2462 */
2463 pki.getTBSCertificate = function(cert) {
2464 // TBSCertificate
2465 var tbs = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2466 // version
2467 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [
2468 // integer
2469 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
2470 asn1.integerToDer(cert.version).getBytes())
2471 ]),
2472 // serialNumber
2473 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
2474 forge.util.hexToBytes(cert.serialNumber)),
2475 // signature
2476 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2477 // algorithm
2478 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
2479 asn1.oidToDer(cert.siginfo.algorithmOid).getBytes()),
2480 // parameters
2481 _signatureParametersToAsn1(
2482 cert.siginfo.algorithmOid, cert.siginfo.parameters)
2483 ]),
2484 // issuer
2485 _dnToAsn1(cert.issuer),
2486 // validity
2487 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2488 // notBefore
2489 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.UTCTIME, false,
2490 asn1.dateToUtcTime(cert.validity.notBefore)),
2491 // notAfter
2492 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.UTCTIME, false,
2493 asn1.dateToUtcTime(cert.validity.notAfter))
2494 ]),
2495 // subject
2496 _dnToAsn1(cert.subject),
2497 // SubjectPublicKeyInfo
2498 pki.publicKeyToAsn1(cert.publicKey)
2499 ]);
2500  
2501 if(cert.issuer.uniqueId) {
2502 // issuerUniqueID (optional)
2503 tbs.value.push(
2504 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [
2505 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false,
2506 // TODO: support arbitrary bit length ids
2507 String.fromCharCode(0x00) +
2508 cert.issuer.uniqueId
2509 )
2510 ])
2511 );
2512 }
2513 if(cert.subject.uniqueId) {
2514 // subjectUniqueID (optional)
2515 tbs.value.push(
2516 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, true, [
2517 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false,
2518 // TODO: support arbitrary bit length ids
2519 String.fromCharCode(0x00) +
2520 cert.subject.uniqueId
2521 )
2522 ])
2523 );
2524 }
2525  
2526 if(cert.extensions.length > 0) {
2527 // extensions (optional)
2528 tbs.value.push(pki.certificateExtensionsToAsn1(cert.extensions));
2529 }
2530  
2531 return tbs;
2532 };
2533  
2534 /**
2535 * Gets the ASN.1 CertificationRequestInfo part of a
2536 * PKCS#10 CertificationRequest.
2537 *
2538 * @param csr the certification request.
2539 *
2540 * @return the asn1 CertificationRequestInfo.
2541 */
2542 pki.getCertificationRequestInfo = function(csr) {
2543 // CertificationRequestInfo
2544 var cri = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2545 // version
2546 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
2547 asn1.integerToDer(csr.version).getBytes()),
2548 // subject
2549 _dnToAsn1(csr.subject),
2550 // SubjectPublicKeyInfo
2551 pki.publicKeyToAsn1(csr.publicKey),
2552 // attributes
2553 _CRIAttributesToAsn1(csr)
2554 ]);
2555  
2556 return cri;
2557 };
2558  
2559 /**
2560 * Converts a DistinguishedName (subject or issuer) to an ASN.1 object.
2561 *
2562 * @param dn the DistinguishedName.
2563 *
2564 * @return the asn1 representation of a DistinguishedName.
2565 */
2566 pki.distinguishedNameToAsn1 = function(dn) {
2567 return _dnToAsn1(dn);
2568 };
2569  
2570 /**
2571 * Converts an X.509v3 RSA certificate to an ASN.1 object.
2572 *
2573 * @param cert the certificate.
2574 *
2575 * @return the asn1 representation of an X.509v3 RSA certificate.
2576 */
2577 pki.certificateToAsn1 = function(cert) {
2578 // prefer cached TBSCertificate over generating one
2579 var tbsCertificate = cert.tbsCertificate || pki.getTBSCertificate(cert);
2580  
2581 // Certificate
2582 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2583 // TBSCertificate
2584 tbsCertificate,
2585 // AlgorithmIdentifier (signature algorithm)
2586 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2587 // algorithm
2588 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
2589 asn1.oidToDer(cert.signatureOid).getBytes()),
2590 // parameters
2591 _signatureParametersToAsn1(cert.signatureOid, cert.signatureParameters)
2592 ]),
2593 // SignatureValue
2594 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false,
2595 String.fromCharCode(0x00) + cert.signature)
2596 ]);
2597 };
2598  
2599 /**
2600 * Converts X.509v3 certificate extensions to ASN.1.
2601 *
2602 * @param exts the extensions to convert.
2603 *
2604 * @return the extensions in ASN.1 format.
2605 */
2606 pki.certificateExtensionsToAsn1 = function(exts) {
2607 // create top-level extension container
2608 var rval = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 3, true, []);
2609  
2610 // create extension sequence (stores a sequence for each extension)
2611 var seq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2612 rval.value.push(seq);
2613  
2614 for(var i = 0; i < exts.length; ++i) {
2615 seq.value.push(pki.certificateExtensionToAsn1(exts[i]));
2616 }
2617  
2618 return rval;
2619 };
2620  
2621 /**
2622 * Converts a single certificate extension to ASN.1.
2623 *
2624 * @param ext the extension to convert.
2625 *
2626 * @return the extension in ASN.1 format.
2627 */
2628 pki.certificateExtensionToAsn1 = function(ext) {
2629 // create a sequence for each extension
2630 var extseq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
2631  
2632 // extnID (OID)
2633 extseq.value.push(asn1.create(
2634 asn1.Class.UNIVERSAL, asn1.Type.OID, false,
2635 asn1.oidToDer(ext.id).getBytes()));
2636  
2637 // critical defaults to false
2638 if(ext.critical) {
2639 // critical BOOLEAN DEFAULT FALSE
2640 extseq.value.push(asn1.create(
2641 asn1.Class.UNIVERSAL, asn1.Type.BOOLEAN, false,
2642 String.fromCharCode(0xFF)));
2643 }
2644  
2645 var value = ext.value;
2646 if(typeof ext.value !== 'string') {
2647 // value is asn.1
2648 value = asn1.toDer(value).getBytes();
2649 }
2650  
2651 // extnValue (OCTET STRING)
2652 extseq.value.push(asn1.create(
2653 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, value));
2654  
2655 return extseq;
2656 };
2657  
2658 /**
2659 * Converts a PKCS#10 certification request to an ASN.1 object.
2660 *
2661 * @param csr the certification request.
2662 *
2663 * @return the asn1 representation of a certification request.
2664 */
2665 pki.certificationRequestToAsn1 = function(csr) {
2666 // prefer cached CertificationRequestInfo over generating one
2667 var cri = csr.certificationRequestInfo ||
2668 pki.getCertificationRequestInfo(csr);
2669  
2670 // Certificate
2671 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2672 // CertificationRequestInfo
2673 cri,
2674 // AlgorithmIdentifier (signature algorithm)
2675 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
2676 // algorithm
2677 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false,
2678 asn1.oidToDer(csr.signatureOid).getBytes()),
2679 // parameters
2680 _signatureParametersToAsn1(csr.signatureOid, csr.signatureParameters)
2681 ]),
2682 // signature
2683 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false,
2684 String.fromCharCode(0x00) + csr.signature)
2685 ]);
2686 };
2687  
2688 /**
2689 * Creates a CA store.
2690 *
2691 * @param certs an optional array of certificate objects or PEM-formatted
2692 * certificate strings to add to the CA store.
2693 *
2694 * @return the CA store.
2695 */
2696 pki.createCaStore = function(certs) {
2697 // create CA store
2698 var caStore = {
2699 // stored certificates
2700 certs: {}
2701 };
2702  
2703 /**
2704 * Gets the certificate that issued the passed certificate or its
2705 * 'parent'.
2706 *
2707 * @param cert the certificate to get the parent for.
2708 *
2709 * @return the parent certificate or null if none was found.
2710 */
2711 caStore.getIssuer = function(cert) {
2712 var rval = getBySubject(cert.issuer);
2713  
2714 // see if there are multiple matches
2715 /*if(forge.util.isArray(rval)) {
2716 // TODO: resolve multiple matches by checking
2717 // authorityKey/subjectKey/issuerUniqueID/other identifiers, etc.
2718 // FIXME: or alternatively do authority key mapping
2719 // if possible (X.509v1 certs can't work?)
2720 throw new Error('Resolving multiple issuer matches not implemented yet.');
2721 }*/
2722  
2723 return rval;
2724 };
2725  
2726 /**
2727 * Adds a trusted certificate to the store.
2728 *
2729 * @param cert the certificate to add as a trusted certificate (either a
2730 * pki.certificate object or a PEM-formatted certificate).
2731 */
2732 caStore.addCertificate = function(cert) {
2733 // convert from pem if necessary
2734 if(typeof cert === 'string') {
2735 cert = forge.pki.certificateFromPem(cert);
2736 }
2737  
2738 ensureSubjectHasHash(cert.subject);
2739  
2740 if(!caStore.hasCertificate(cert)) { // avoid duplicate certificates in store
2741 if(cert.subject.hash in caStore.certs) {
2742 // subject hash already exists, append to array
2743 var tmp = caStore.certs[cert.subject.hash];
2744 if(!forge.util.isArray(tmp)) {
2745 tmp = [tmp];
2746 }
2747 tmp.push(cert);
2748 caStore.certs[cert.subject.hash] = tmp;
2749 } else {
2750 caStore.certs[cert.subject.hash] = cert;
2751 }
2752 }
2753 };
2754  
2755 /**
2756 * Checks to see if the given certificate is in the store.
2757 *
2758 * @param cert the certificate to check (either a pki.certificate or a
2759 * PEM-formatted certificate).
2760 *
2761 * @return true if the certificate is in the store, false if not.
2762 */
2763 caStore.hasCertificate = function(cert) {
2764 // convert from pem if necessary
2765 if(typeof cert === 'string') {
2766 cert = forge.pki.certificateFromPem(cert);
2767 }
2768  
2769 var match = getBySubject(cert.subject);
2770 if(!match) {
2771 return false;
2772 }
2773 if(!forge.util.isArray(match)) {
2774 match = [match];
2775 }
2776 // compare DER-encoding of certificates
2777 var der1 = asn1.toDer(pki.certificateToAsn1(cert)).getBytes();
2778 for(var i = 0; i < match.length; ++i) {
2779 var der2 = asn1.toDer(pki.certificateToAsn1(match[i])).getBytes();
2780 if(der1 === der2) {
2781 return true;
2782 }
2783 }
2784 return false;
2785 };
2786  
2787 /**
2788 * Lists all of the certificates kept in the store.
2789 *
2790 * @return an array of all of the pki.certificate objects in the store.
2791 */
2792 caStore.listAllCertificates = function() {
2793 var certList = [];
2794  
2795 for(var hash in caStore.certs) {
2796 if(caStore.certs.hasOwnProperty(hash)) {
2797 var value = caStore.certs[hash];
2798 if(!forge.util.isArray(value)) {
2799 certList.push(value);
2800 } else {
2801 for(var i = 0; i < value.length; ++i) {
2802 certList.push(value[i]);
2803 }
2804 }
2805 }
2806 }
2807  
2808 return certList;
2809 };
2810  
2811 /**
2812 * Removes a certificate from the store.
2813 *
2814 * @param cert the certificate to remove (either a pki.certificate or a
2815 * PEM-formatted certificate).
2816 *
2817 * @return the certificate that was removed or null if the certificate
2818 * wasn't in store.
2819 */
2820 caStore.removeCertificate = function(cert) {
2821 var result;
2822  
2823 // convert from pem if necessary
2824 if(typeof cert === 'string') {
2825 cert = forge.pki.certificateFromPem(cert);
2826 }
2827 ensureSubjectHasHash(cert.subject);
2828 if(!caStore.hasCertificate(cert)) {
2829 return null;
2830 }
2831  
2832 var match = getBySubject(cert.subject);
2833  
2834 if(!forge.util.isArray(match)) {
2835 result = caStore.certs[cert.subject.hash];
2836 delete caStore.certs[cert.subject.hash];
2837 return result;
2838 }
2839  
2840 // compare DER-encoding of certificates
2841 var der1 = asn1.toDer(pki.certificateToAsn1(cert)).getBytes();
2842 for(var i = 0; i < match.length; ++i) {
2843 var der2 = asn1.toDer(pki.certificateToAsn1(match[i])).getBytes();
2844 if(der1 === der2) {
2845 result = match[i];
2846 match.splice(i, 1);
2847 }
2848 }
2849 if(match.length === 0) {
2850 delete caStore.certs[cert.subject.hash];
2851 }
2852  
2853 return result;
2854 };
2855  
2856 function getBySubject(subject) {
2857 ensureSubjectHasHash(subject);
2858 return caStore.certs[subject.hash] || null;
2859 }
2860  
2861 function ensureSubjectHasHash(subject) {
2862 // produce subject hash if it doesn't exist
2863 if(!subject.hash) {
2864 var md = forge.md.sha1.create();
2865 subject.attributes = pki.RDNAttributesAsArray(_dnToAsn1(subject), md);
2866 subject.hash = md.digest().toHex();
2867 }
2868 }
2869  
2870 // auto-add passed in certs
2871 if(certs) {
2872 // parse PEM-formatted certificates as necessary
2873 for(var i = 0; i < certs.length; ++i) {
2874 var cert = certs[i];
2875 caStore.addCertificate(cert);
2876 }
2877 }
2878  
2879 return caStore;
2880 };
2881  
2882 /**
2883 * Certificate verification errors, based on TLS.
2884 */
2885 pki.certificateError = {
2886 bad_certificate: 'forge.pki.BadCertificate',
2887 unsupported_certificate: 'forge.pki.UnsupportedCertificate',
2888 certificate_revoked: 'forge.pki.CertificateRevoked',
2889 certificate_expired: 'forge.pki.CertificateExpired',
2890 certificate_unknown: 'forge.pki.CertificateUnknown',
2891 unknown_ca: 'forge.pki.UnknownCertificateAuthority'
2892 };
2893  
2894 /**
2895 * Verifies a certificate chain against the given Certificate Authority store
2896 * with an optional custom verify callback.
2897 *
2898 * @param caStore a certificate store to verify against.
2899 * @param chain the certificate chain to verify, with the root or highest
2900 * authority at the end (an array of certificates).
2901 * @param verify called for every certificate in the chain.
2902 *
2903 * The verify callback has the following signature:
2904 *
2905 * verified - Set to true if certificate was verified, otherwise the
2906 * pki.certificateError for why the certificate failed.
2907 * depth - The current index in the chain, where 0 is the end point's cert.
2908 * certs - The certificate chain, *NOTE* an empty chain indicates an anonymous
2909 * end point.
2910 *
2911 * The function returns true on success and on failure either the appropriate
2912 * pki.certificateError or an object with 'error' set to the appropriate
2913 * pki.certificateError and 'message' set to a custom error message.
2914 *
2915 * @return true if successful, error thrown if not.
2916 */
2917 pki.verifyCertificateChain = function(caStore, chain, verify) {
2918 /* From: RFC3280 - Internet X.509 Public Key Infrastructure Certificate
2919 Section 6: Certification Path Validation
2920 See inline parentheticals related to this particular implementation.
2921  
2922 The primary goal of path validation is to verify the binding between
2923 a subject distinguished name or a subject alternative name and subject
2924 public key, as represented in the end entity certificate, based on the
2925 public key of the trust anchor. This requires obtaining a sequence of
2926 certificates that support that binding. That sequence should be provided
2927 in the passed 'chain'. The trust anchor should be in the given CA
2928 store. The 'end entity' certificate is the certificate provided by the
2929 end point (typically a server) and is the first in the chain.
2930  
2931 To meet this goal, the path validation process verifies, among other
2932 things, that a prospective certification path (a sequence of n
2933 certificates or a 'chain') satisfies the following conditions:
2934  
2935 (a) for all x in {1, ..., n-1}, the subject of certificate x is
2936 the issuer of certificate x+1;
2937  
2938 (b) certificate 1 is issued by the trust anchor;
2939  
2940 (c) certificate n is the certificate to be validated; and
2941  
2942 (d) for all x in {1, ..., n}, the certificate was valid at the
2943 time in question.
2944  
2945 Note that here 'n' is index 0 in the chain and 1 is the last certificate
2946 in the chain and it must be signed by a certificate in the connection's
2947 CA store.
2948  
2949 The path validation process also determines the set of certificate
2950 policies that are valid for this path, based on the certificate policies
2951 extension, policy mapping extension, policy constraints extension, and
2952 inhibit any-policy extension.
2953  
2954 Note: Policy mapping extension not supported (Not Required).
2955  
2956 Note: If the certificate has an unsupported critical extension, then it
2957 must be rejected.
2958  
2959 Note: A certificate is self-issued if the DNs that appear in the subject
2960 and issuer fields are identical and are not empty.
2961  
2962 The path validation algorithm assumes the following seven inputs are
2963 provided to the path processing logic. What this specific implementation
2964 will use is provided parenthetically:
2965  
2966 (a) a prospective certification path of length n (the 'chain')
2967 (b) the current date/time: ('now').
2968 (c) user-initial-policy-set: A set of certificate policy identifiers
2969 naming the policies that are acceptable to the certificate user.
2970 The user-initial-policy-set contains the special value any-policy
2971 if the user is not concerned about certificate policy
2972 (Not implemented. Any policy is accepted).
2973 (d) trust anchor information, describing a CA that serves as a trust
2974 anchor for the certification path. The trust anchor information
2975 includes:
2976  
2977 (1) the trusted issuer name,
2978 (2) the trusted public key algorithm,
2979 (3) the trusted public key, and
2980 (4) optionally, the trusted public key parameters associated
2981 with the public key.
2982  
2983 (Trust anchors are provided via certificates in the CA store).
2984  
2985 The trust anchor information may be provided to the path processing
2986 procedure in the form of a self-signed certificate. The trusted anchor
2987 information is trusted because it was delivered to the path processing
2988 procedure by some trustworthy out-of-band procedure. If the trusted
2989 public key algorithm requires parameters, then the parameters are
2990 provided along with the trusted public key (No parameters used in this
2991 implementation).
2992  
2993 (e) initial-policy-mapping-inhibit, which indicates if policy mapping is
2994 allowed in the certification path.
2995 (Not implemented, no policy checking)
2996  
2997 (f) initial-explicit-policy, which indicates if the path must be valid
2998 for at least one of the certificate policies in the user-initial-
2999 policy-set.
3000 (Not implemented, no policy checking)
3001  
3002 (g) initial-any-policy-inhibit, which indicates whether the
3003 anyPolicy OID should be processed if it is included in a
3004 certificate.
3005 (Not implemented, so any policy is valid provided that it is
3006 not marked as critical) */
3007  
3008 /* Basic Path Processing:
3009  
3010 For each certificate in the 'chain', the following is checked:
3011  
3012 1. The certificate validity period includes the current time.
3013 2. The certificate was signed by its parent (where the parent is either
3014 the next in the chain or from the CA store). Allow processing to
3015 continue to the next step if no parent is found but the certificate is
3016 in the CA store.
3017 3. TODO: The certificate has not been revoked.
3018 4. The certificate issuer name matches the parent's subject name.
3019 5. TODO: If the certificate is self-issued and not the final certificate
3020 in the chain, skip this step, otherwise verify that the subject name
3021 is within one of the permitted subtrees of X.500 distinguished names
3022 and that each of the alternative names in the subjectAltName extension
3023 (critical or non-critical) is within one of the permitted subtrees for
3024 that name type.
3025 6. TODO: If the certificate is self-issued and not the final certificate
3026 in the chain, skip this step, otherwise verify that the subject name
3027 is not within one of the excluded subtrees for X.500 distinguished
3028 names and none of the subjectAltName extension names are excluded for
3029 that name type.
3030 7. The other steps in the algorithm for basic path processing involve
3031 handling the policy extension which is not presently supported in this
3032 implementation. Instead, if a critical policy extension is found, the
3033 certificate is rejected as not supported.
3034 8. If the certificate is not the first or if its the only certificate in
3035 the chain (having no parent from the CA store or is self-signed) and it
3036 has a critical key usage extension, verify that the keyCertSign bit is
3037 set. If the key usage extension exists, verify that the basic
3038 constraints extension exists. If the basic constraints extension exists,
3039 verify that the cA flag is set. If pathLenConstraint is set, ensure that
3040 the number of certificates that precede in the chain (come earlier
3041 in the chain as implemented below), excluding the very first in the
3042 chain (typically the end-entity one), isn't greater than the
3043 pathLenConstraint. This constraint limits the number of intermediate
3044 CAs that may appear below a CA before only end-entity certificates
3045 may be issued. */
3046  
3047 // copy cert chain references to another array to protect against changes
3048 // in verify callback
3049 chain = chain.slice(0);
3050 var certs = chain.slice(0);
3051  
3052 // get current date
3053 var now = new Date();
3054  
3055 // verify each cert in the chain using its parent, where the parent
3056 // is either the next in the chain or from the CA store
3057 var first = true;
3058 var error = null;
3059 var depth = 0;
3060 do {
3061 var cert = chain.shift();
3062 var parent = null;
3063 var selfSigned = false;
3064  
3065 // 1. check valid time
3066 if(now < cert.validity.notBefore || now > cert.validity.notAfter) {
3067 error = {
3068 message: 'Certificate is not valid yet or has expired.',
3069 error: pki.certificateError.certificate_expired,
3070 notBefore: cert.validity.notBefore,
3071 notAfter: cert.validity.notAfter,
3072 now: now
3073 };
3074 }
3075  
3076 // 2. verify with parent from chain or CA store
3077 if(error === null) {
3078 parent = chain[0] || caStore.getIssuer(cert);
3079 if(parent === null) {
3080 // check for self-signed cert
3081 if(cert.isIssuer(cert)) {
3082 selfSigned = true;
3083 parent = cert;
3084 }
3085 }
3086  
3087 if(parent) {
3088 // FIXME: current CA store implementation might have multiple
3089 // certificates where the issuer can't be determined from the
3090 // certificate (happens rarely with, eg: old certificates) so normalize
3091 // by always putting parents into an array
3092 // TODO: there's may be an extreme degenerate case currently uncovered
3093 // where an old intermediate certificate seems to have a matching parent
3094 // but none of the parents actually verify ... but the intermediate
3095 // is in the CA and it should pass this check; needs investigation
3096 var parents = parent;
3097 if(!forge.util.isArray(parents)) {
3098 parents = [parents];
3099 }
3100  
3101 // try to verify with each possible parent (typically only one)
3102 var verified = false;
3103 while(!verified && parents.length > 0) {
3104 parent = parents.shift();
3105 try {
3106 verified = parent.verify(cert);
3107 } catch(ex) {
3108 // failure to verify, don't care why, try next one
3109 }
3110 }
3111  
3112 if(!verified) {
3113 error = {
3114 message: 'Certificate signature is invalid.',
3115 error: pki.certificateError.bad_certificate
3116 };
3117 }
3118 }
3119  
3120 if(error === null && (!parent || selfSigned) &&
3121 !caStore.hasCertificate(cert)) {
3122 // no parent issuer and certificate itself is not trusted
3123 error = {
3124 message: 'Certificate is not trusted.',
3125 error: pki.certificateError.unknown_ca
3126 };
3127 }
3128 }
3129  
3130 // TODO: 3. check revoked
3131  
3132 // 4. check for matching issuer/subject
3133 if(error === null && parent && !cert.isIssuer(parent)) {
3134 // parent is not issuer
3135 error = {
3136 message: 'Certificate issuer is invalid.',
3137 error: pki.certificateError.bad_certificate
3138 };
3139 }
3140  
3141 // 5. TODO: check names with permitted names tree
3142  
3143 // 6. TODO: check names against excluded names tree
3144  
3145 // 7. check for unsupported critical extensions
3146 if(error === null) {
3147 // supported extensions
3148 var se = {
3149 keyUsage: true,
3150 basicConstraints: true
3151 };
3152 for(var i = 0; error === null && i < cert.extensions.length; ++i) {
3153 var ext = cert.extensions[i];
3154 if(ext.critical && !(ext.name in se)) {
3155 error = {
3156 message:
3157 'Certificate has an unsupported critical extension.',
3158 error: pki.certificateError.unsupported_certificate
3159 };
3160 }
3161 }
3162 }
3163  
3164 // 8. check for CA if cert is not first or is the only certificate
3165 // remaining in chain with no parent or is self-signed
3166 if(error === null &&
3167 (!first || (chain.length === 0 && (!parent || selfSigned)))) {
3168 // first check keyUsage extension and then basic constraints
3169 var bcExt = cert.getExtension('basicConstraints');
3170 var keyUsageExt = cert.getExtension('keyUsage');
3171 if(keyUsageExt !== null) {
3172 // keyCertSign must be true and there must be a basic
3173 // constraints extension
3174 if(!keyUsageExt.keyCertSign || bcExt === null) {
3175 // bad certificate
3176 error = {
3177 message:
3178 'Certificate keyUsage or basicConstraints conflict ' +
3179 'or indicate that the certificate is not a CA. ' +
3180 'If the certificate is the only one in the chain or ' +
3181 'isn\'t the first then the certificate must be a ' +
3182 'valid CA.',
3183 error: pki.certificateError.bad_certificate
3184 };
3185 }
3186 }
3187 // basic constraints cA flag must be set
3188 if(error === null && bcExt !== null && !bcExt.cA) {
3189 // bad certificate
3190 error = {
3191 message:
3192 'Certificate basicConstraints indicates the certificate ' +
3193 'is not a CA.',
3194 error: pki.certificateError.bad_certificate
3195 };
3196 }
3197 // if error is not null and keyUsage is available, then we know it
3198 // has keyCertSign and there is a basic constraints extension too,
3199 // which means we can check pathLenConstraint (if it exists)
3200 if(error === null && keyUsageExt !== null &&
3201 'pathLenConstraint' in bcExt) {
3202 // pathLen is the maximum # of intermediate CA certs that can be
3203 // found between the current certificate and the end-entity (depth 0)
3204 // certificate; this number does not include the end-entity (depth 0,
3205 // last in the chain) even if it happens to be a CA certificate itself
3206 var pathLen = depth - 1;
3207 if(pathLen > bcExt.pathLenConstraint) {
3208 // pathLenConstraint violated, bad certificate
3209 error = {
3210 message:
3211 'Certificate basicConstraints pathLenConstraint violated.',
3212 error: pki.certificateError.bad_certificate
3213 };
3214 }
3215 }
3216 }
3217  
3218 // call application callback
3219 var vfd = (error === null) ? true : error.error;
3220 var ret = verify ? verify(vfd, depth, certs) : vfd;
3221 if(ret === true) {
3222 // clear any set error
3223 error = null;
3224 } else {
3225 // if passed basic tests, set default message and alert
3226 if(vfd === true) {
3227 error = {
3228 message: 'The application rejected the certificate.',
3229 error: pki.certificateError.bad_certificate
3230 };
3231 }
3232  
3233 // check for custom error info
3234 if(ret || ret === 0) {
3235 // set custom message and error
3236 if(typeof ret === 'object' && !forge.util.isArray(ret)) {
3237 if(ret.message) {
3238 error.message = ret.message;
3239 }
3240 if(ret.error) {
3241 error.error = ret.error;
3242 }
3243 } else if(typeof ret === 'string') {
3244 // set custom error
3245 error.error = ret;
3246 }
3247 }
3248  
3249 // throw error
3250 throw error;
3251 }
3252  
3253 // no longer first cert in chain
3254 first = false;
3255 ++depth;
3256 } while(chain.length > 0);
3257  
3258 return true;
3259 };