You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							411 lines
						
					
					
						
							11 KiB
						
					
					
				
			
		
		
	
	
							411 lines
						
					
					
						
							11 KiB
						
					
					
				| /**
 | |
|  * Javascript implementation of ASN.1 validators for PKCS#7 v1.5.
 | |
|  *
 | |
|  * @author Dave Longley
 | |
|  * @author Stefan Siegl
 | |
|  *
 | |
|  * Copyright (c) 2012-2015 Digital Bazaar, Inc.
 | |
|  * Copyright (c) 2012 Stefan Siegl <stesie@brokenpipe.de>
 | |
|  *
 | |
|  * The ASN.1 representation of PKCS#7 is as follows
 | |
|  * (see RFC #2315 for details, http://www.ietf.org/rfc/rfc2315.txt):
 | |
|  *
 | |
|  * A PKCS#7 message consists of a ContentInfo on root level, which may
 | |
|  * contain any number of further ContentInfo nested into it.
 | |
|  *
 | |
|  * ContentInfo ::= SEQUENCE {
 | |
|  *   contentType                ContentType,
 | |
|  *   content               [0]  EXPLICIT ANY DEFINED BY contentType OPTIONAL
 | |
|  * }
 | |
|  *
 | |
|  * ContentType ::= OBJECT IDENTIFIER
 | |
|  *
 | |
|  * EnvelopedData ::= SEQUENCE {
 | |
|  *   version                    Version,
 | |
|  *   recipientInfos             RecipientInfos,
 | |
|  *   encryptedContentInfo       EncryptedContentInfo
 | |
|  * }
 | |
|  *
 | |
|  * EncryptedData ::= SEQUENCE {
 | |
|  *   version                    Version,
 | |
|  *   encryptedContentInfo       EncryptedContentInfo
 | |
|  * }
 | |
|  *
 | |
|  * id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
 | |
|  *   us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
 | |
|  *
 | |
|  * SignedData ::= SEQUENCE {
 | |
|  *   version           INTEGER,
 | |
|  *   digestAlgorithms  DigestAlgorithmIdentifiers,
 | |
|  *   contentInfo       ContentInfo,
 | |
|  *   certificates      [0] IMPLICIT Certificates OPTIONAL,
 | |
|  *   crls              [1] IMPLICIT CertificateRevocationLists OPTIONAL,
 | |
|  *   signerInfos       SignerInfos
 | |
|  * }
 | |
|  *
 | |
|  * SignerInfos ::= SET OF SignerInfo
 | |
|  *
 | |
|  * SignerInfo ::= SEQUENCE {
 | |
|  *   version                    Version,
 | |
|  *   issuerAndSerialNumber      IssuerAndSerialNumber,
 | |
|  *   digestAlgorithm            DigestAlgorithmIdentifier,
 | |
|  *   authenticatedAttributes    [0] IMPLICIT Attributes OPTIONAL,
 | |
|  *   digestEncryptionAlgorithm  DigestEncryptionAlgorithmIdentifier,
 | |
|  *   encryptedDigest            EncryptedDigest,
 | |
|  *   unauthenticatedAttributes  [1] IMPLICIT Attributes OPTIONAL
 | |
|  * }
 | |
|  *
 | |
|  * EncryptedDigest ::= OCTET STRING
 | |
|  *
 | |
|  * Attributes ::= SET OF Attribute
 | |
|  *
 | |
|  * Attribute ::= SEQUENCE {
 | |
|  *   attrType    OBJECT IDENTIFIER,
 | |
|  *   attrValues  SET OF AttributeValue
 | |
|  * }
 | |
|  *
 | |
|  * AttributeValue ::= ANY
 | |
|  *
 | |
|  * Version ::= INTEGER
 | |
|  *
 | |
|  * RecipientInfos ::= SET OF RecipientInfo
 | |
|  *
 | |
|  * EncryptedContentInfo ::= SEQUENCE {
 | |
|  *   contentType                 ContentType,
 | |
|  *   contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
 | |
|  *   encryptedContent       [0]  IMPLICIT EncryptedContent OPTIONAL
 | |
|  * }
 | |
|  *
 | |
|  * ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
 | |
|  *
 | |
|  * The AlgorithmIdentifier contains an Object Identifier (OID) and parameters
 | |
|  * for the algorithm, if any. In the case of AES and DES3, there is only one,
 | |
|  * the IV.
 | |
|  *
 | |
|  * AlgorithmIdentifer ::= SEQUENCE {
 | |
|  *    algorithm OBJECT IDENTIFIER,
 | |
|  *    parameters ANY DEFINED BY algorithm OPTIONAL
 | |
|  * }
 | |
|  *
 | |
|  * EncryptedContent ::= OCTET STRING
 | |
|  *
 | |
|  * RecipientInfo ::= SEQUENCE {
 | |
|  *   version                     Version,
 | |
|  *   issuerAndSerialNumber       IssuerAndSerialNumber,
 | |
|  *   keyEncryptionAlgorithm      KeyEncryptionAlgorithmIdentifier,
 | |
|  *   encryptedKey                EncryptedKey
 | |
|  * }
 | |
|  *
 | |
|  * IssuerAndSerialNumber ::= SEQUENCE {
 | |
|  *   issuer                      Name,
 | |
|  *   serialNumber                CertificateSerialNumber
 | |
|  * }
 | |
|  *
 | |
|  * CertificateSerialNumber ::= INTEGER
 | |
|  *
 | |
|  * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
 | |
|  *
 | |
|  * EncryptedKey ::= OCTET STRING
 | |
|  */
 | |
| var forge = require('./forge');
 | |
| require('./asn1');
 | |
| require('./util');
 | |
| 
 | |
| // shortcut for ASN.1 API
 | |
| var asn1 = forge.asn1;
 | |
| 
 | |
| // shortcut for PKCS#7 API
 | |
| var p7v = module.exports = forge.pkcs7asn1 = forge.pkcs7asn1 || {};
 | |
| forge.pkcs7 = forge.pkcs7 || {};
 | |
| forge.pkcs7.asn1 = p7v;
 | |
| 
 | |
| var contentInfoValidator = {
 | |
|   name: 'ContentInfo',
 | |
|   tagClass: asn1.Class.UNIVERSAL,
 | |
|   type: asn1.Type.SEQUENCE,
 | |
|   constructed: true,
 | |
|   value: [{
 | |
|     name: 'ContentInfo.ContentType',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.OID,
 | |
|     constructed: false,
 | |
|     capture: 'contentType'
 | |
|   }, {
 | |
|     name: 'ContentInfo.content',
 | |
|     tagClass: asn1.Class.CONTEXT_SPECIFIC,
 | |
|     type: 0,
 | |
|     constructed: true,
 | |
|     optional: true,
 | |
|     captureAsn1: 'content'
 | |
|   }]
 | |
| };
 | |
| p7v.contentInfoValidator = contentInfoValidator;
 | |
| 
 | |
| var encryptedContentInfoValidator = {
 | |
|   name: 'EncryptedContentInfo',
 | |
|   tagClass: asn1.Class.UNIVERSAL,
 | |
|   type: asn1.Type.SEQUENCE,
 | |
|   constructed: true,
 | |
|   value: [{
 | |
|     name: 'EncryptedContentInfo.contentType',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.OID,
 | |
|     constructed: false,
 | |
|     capture: 'contentType'
 | |
|   }, {
 | |
|     name: 'EncryptedContentInfo.contentEncryptionAlgorithm',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SEQUENCE,
 | |
|     constructed: true,
 | |
|     value: [{
 | |
|       name: 'EncryptedContentInfo.contentEncryptionAlgorithm.algorithm',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       type: asn1.Type.OID,
 | |
|       constructed: false,
 | |
|       capture: 'encAlgorithm'
 | |
|     }, {
 | |
|       name: 'EncryptedContentInfo.contentEncryptionAlgorithm.parameter',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       captureAsn1: 'encParameter'
 | |
|     }]
 | |
|   }, {
 | |
|     name: 'EncryptedContentInfo.encryptedContent',
 | |
|     tagClass: asn1.Class.CONTEXT_SPECIFIC,
 | |
|     type: 0,
 | |
|     /* The PKCS#7 structure output by OpenSSL somewhat differs from what
 | |
|      * other implementations do generate.
 | |
|      *
 | |
|      * OpenSSL generates a structure like this:
 | |
|      * SEQUENCE {
 | |
|      *    ...
 | |
|      *    [0]
 | |
|      *       26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38
 | |
|      *       C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45
 | |
|      *       ...
 | |
|      * }
 | |
|      *
 | |
|      * Whereas other implementations (and this PKCS#7 module) generate:
 | |
|      * SEQUENCE {
 | |
|      *    ...
 | |
|      *    [0] {
 | |
|      *       OCTET STRING
 | |
|      *          26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38
 | |
|      *          C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45
 | |
|      *          ...
 | |
|      *    }
 | |
|      * }
 | |
|      *
 | |
|      * In order to support both, we just capture the context specific
 | |
|      * field here.  The OCTET STRING bit is removed below.
 | |
|      */
 | |
|     capture: 'encryptedContent',
 | |
|     captureAsn1: 'encryptedContentAsn1'
 | |
|   }]
 | |
| };
 | |
| 
 | |
| p7v.envelopedDataValidator = {
 | |
|   name: 'EnvelopedData',
 | |
|   tagClass: asn1.Class.UNIVERSAL,
 | |
|   type: asn1.Type.SEQUENCE,
 | |
|   constructed: true,
 | |
|   value: [{
 | |
|     name: 'EnvelopedData.Version',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.INTEGER,
 | |
|     constructed: false,
 | |
|     capture: 'version'
 | |
|   }, {
 | |
|     name: 'EnvelopedData.RecipientInfos',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SET,
 | |
|     constructed: true,
 | |
|     captureAsn1: 'recipientInfos'
 | |
|   }].concat(encryptedContentInfoValidator)
 | |
| };
 | |
| 
 | |
| p7v.encryptedDataValidator = {
 | |
|   name: 'EncryptedData',
 | |
|   tagClass: asn1.Class.UNIVERSAL,
 | |
|   type: asn1.Type.SEQUENCE,
 | |
|   constructed: true,
 | |
|   value: [{
 | |
|     name: 'EncryptedData.Version',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.INTEGER,
 | |
|     constructed: false,
 | |
|     capture: 'version'
 | |
|   }].concat(encryptedContentInfoValidator)
 | |
| };
 | |
| 
 | |
| var signerValidator = {
 | |
|   name: 'SignerInfo',
 | |
|   tagClass: asn1.Class.UNIVERSAL,
 | |
|   type: asn1.Type.SEQUENCE,
 | |
|   constructed: true,
 | |
|   value: [{
 | |
|     name: 'SignerInfo.version',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.INTEGER,
 | |
|     constructed: false
 | |
|   }, {
 | |
|     name: 'SignerInfo.issuerAndSerialNumber',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SEQUENCE,
 | |
|     constructed: true,
 | |
|     value: [{
 | |
|       name: 'SignerInfo.issuerAndSerialNumber.issuer',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       type: asn1.Type.SEQUENCE,
 | |
|       constructed: true,
 | |
|       captureAsn1: 'issuer'
 | |
|     }, {
 | |
|       name: 'SignerInfo.issuerAndSerialNumber.serialNumber',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       type: asn1.Type.INTEGER,
 | |
|       constructed: false,
 | |
|       capture: 'serial'
 | |
|     }]
 | |
|   }, {
 | |
|     name: 'SignerInfo.digestAlgorithm',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SEQUENCE,
 | |
|     constructed: true,
 | |
|     value: [{
 | |
|       name: 'SignerInfo.digestAlgorithm.algorithm',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       type: asn1.Type.OID,
 | |
|       constructed: false,
 | |
|       capture: 'digestAlgorithm'
 | |
|     }, {
 | |
|       name: 'SignerInfo.digestAlgorithm.parameter',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       constructed: false,
 | |
|       captureAsn1: 'digestParameter',
 | |
|       optional: true
 | |
|     }]
 | |
|   }, {
 | |
|     name: 'SignerInfo.authenticatedAttributes',
 | |
|     tagClass: asn1.Class.CONTEXT_SPECIFIC,
 | |
|     type: 0,
 | |
|     constructed: true,
 | |
|     optional: true,
 | |
|     capture: 'authenticatedAttributes'
 | |
|   }, {
 | |
|     name: 'SignerInfo.digestEncryptionAlgorithm',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SEQUENCE,
 | |
|     constructed: true,
 | |
|     capture: 'signatureAlgorithm'
 | |
|   }, {
 | |
|     name: 'SignerInfo.encryptedDigest',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.OCTETSTRING,
 | |
|     constructed: false,
 | |
|     capture: 'signature'
 | |
|   }, {
 | |
|     name: 'SignerInfo.unauthenticatedAttributes',
 | |
|     tagClass: asn1.Class.CONTEXT_SPECIFIC,
 | |
|     type: 1,
 | |
|     constructed: true,
 | |
|     optional: true,
 | |
|     capture: 'unauthenticatedAttributes'
 | |
|   }]
 | |
| };
 | |
| 
 | |
| p7v.signedDataValidator = {
 | |
|   name: 'SignedData',
 | |
|   tagClass: asn1.Class.UNIVERSAL,
 | |
|   type: asn1.Type.SEQUENCE,
 | |
|   constructed: true,
 | |
|   value: [{
 | |
|     name: 'SignedData.Version',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.INTEGER,
 | |
|     constructed: false,
 | |
|     capture: 'version'
 | |
|   }, {
 | |
|     name: 'SignedData.DigestAlgorithms',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SET,
 | |
|     constructed: true,
 | |
|     captureAsn1: 'digestAlgorithms'
 | |
|   },
 | |
|   contentInfoValidator,
 | |
|   {
 | |
|     name: 'SignedData.Certificates',
 | |
|     tagClass: asn1.Class.CONTEXT_SPECIFIC,
 | |
|     type: 0,
 | |
|     optional: true,
 | |
|     captureAsn1: 'certificates'
 | |
|   }, {
 | |
|     name: 'SignedData.CertificateRevocationLists',
 | |
|     tagClass: asn1.Class.CONTEXT_SPECIFIC,
 | |
|     type: 1,
 | |
|     optional: true,
 | |
|     captureAsn1: 'crls'
 | |
|   }, {
 | |
|     name: 'SignedData.SignerInfos',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SET,
 | |
|     capture: 'signerInfos',
 | |
|     optional: true,
 | |
|     value: [signerValidator]
 | |
|   }]
 | |
| };
 | |
| 
 | |
| p7v.recipientInfoValidator = {
 | |
|   name: 'RecipientInfo',
 | |
|   tagClass: asn1.Class.UNIVERSAL,
 | |
|   type: asn1.Type.SEQUENCE,
 | |
|   constructed: true,
 | |
|   value: [{
 | |
|     name: 'RecipientInfo.version',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.INTEGER,
 | |
|     constructed: false,
 | |
|     capture: 'version'
 | |
|   }, {
 | |
|     name: 'RecipientInfo.issuerAndSerial',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SEQUENCE,
 | |
|     constructed: true,
 | |
|     value: [{
 | |
|       name: 'RecipientInfo.issuerAndSerial.issuer',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       type: asn1.Type.SEQUENCE,
 | |
|       constructed: true,
 | |
|       captureAsn1: 'issuer'
 | |
|     }, {
 | |
|       name: 'RecipientInfo.issuerAndSerial.serialNumber',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       type: asn1.Type.INTEGER,
 | |
|       constructed: false,
 | |
|       capture: 'serial'
 | |
|     }]
 | |
|   }, {
 | |
|     name: 'RecipientInfo.keyEncryptionAlgorithm',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.SEQUENCE,
 | |
|     constructed: true,
 | |
|     value: [{
 | |
|       name: 'RecipientInfo.keyEncryptionAlgorithm.algorithm',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       type: asn1.Type.OID,
 | |
|       constructed: false,
 | |
|       capture: 'encAlgorithm'
 | |
|     }, {
 | |
|       name: 'RecipientInfo.keyEncryptionAlgorithm.parameter',
 | |
|       tagClass: asn1.Class.UNIVERSAL,
 | |
|       constructed: false,
 | |
|       captureAsn1: 'encParameter',
 | |
|       optional: true
 | |
|     }]
 | |
|   }, {
 | |
|     name: 'RecipientInfo.encryptedKey',
 | |
|     tagClass: asn1.Class.UNIVERSAL,
 | |
|     type: asn1.Type.OCTETSTRING,
 | |
|     constructed: false,
 | |
|     capture: 'encKey'
 | |
|   }]
 | |
| };
 |