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'
 | 
						|
  }]
 | 
						|
};
 |