| /** |
| * 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' |
| }] |
| }, { |
| name: 'RecipientInfo.encryptedKey', |
| tagClass: asn1.Class.UNIVERSAL, |
| type: asn1.Type.OCTETSTRING, |
| constructed: false, |
| capture: 'encKey' |
| }] |
| }; |