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.

409 lines
11 KiB

4 years ago
  1. /**
  2. * Javascript implementation of ASN.1 validators for PKCS#7 v1.5.
  3. *
  4. * @author Dave Longley
  5. * @author Stefan Siegl
  6. *
  7. * Copyright (c) 2012-2015 Digital Bazaar, Inc.
  8. * Copyright (c) 2012 Stefan Siegl <stesie@brokenpipe.de>
  9. *
  10. * The ASN.1 representation of PKCS#7 is as follows
  11. * (see RFC #2315 for details, http://www.ietf.org/rfc/rfc2315.txt):
  12. *
  13. * A PKCS#7 message consists of a ContentInfo on root level, which may
  14. * contain any number of further ContentInfo nested into it.
  15. *
  16. * ContentInfo ::= SEQUENCE {
  17. * contentType ContentType,
  18. * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
  19. * }
  20. *
  21. * ContentType ::= OBJECT IDENTIFIER
  22. *
  23. * EnvelopedData ::= SEQUENCE {
  24. * version Version,
  25. * recipientInfos RecipientInfos,
  26. * encryptedContentInfo EncryptedContentInfo
  27. * }
  28. *
  29. * EncryptedData ::= SEQUENCE {
  30. * version Version,
  31. * encryptedContentInfo EncryptedContentInfo
  32. * }
  33. *
  34. * id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
  35. * us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
  36. *
  37. * SignedData ::= SEQUENCE {
  38. * version INTEGER,
  39. * digestAlgorithms DigestAlgorithmIdentifiers,
  40. * contentInfo ContentInfo,
  41. * certificates [0] IMPLICIT Certificates OPTIONAL,
  42. * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
  43. * signerInfos SignerInfos
  44. * }
  45. *
  46. * SignerInfos ::= SET OF SignerInfo
  47. *
  48. * SignerInfo ::= SEQUENCE {
  49. * version Version,
  50. * issuerAndSerialNumber IssuerAndSerialNumber,
  51. * digestAlgorithm DigestAlgorithmIdentifier,
  52. * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
  53. * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
  54. * encryptedDigest EncryptedDigest,
  55. * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
  56. * }
  57. *
  58. * EncryptedDigest ::= OCTET STRING
  59. *
  60. * Attributes ::= SET OF Attribute
  61. *
  62. * Attribute ::= SEQUENCE {
  63. * attrType OBJECT IDENTIFIER,
  64. * attrValues SET OF AttributeValue
  65. * }
  66. *
  67. * AttributeValue ::= ANY
  68. *
  69. * Version ::= INTEGER
  70. *
  71. * RecipientInfos ::= SET OF RecipientInfo
  72. *
  73. * EncryptedContentInfo ::= SEQUENCE {
  74. * contentType ContentType,
  75. * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
  76. * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
  77. * }
  78. *
  79. * ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  80. *
  81. * The AlgorithmIdentifier contains an Object Identifier (OID) and parameters
  82. * for the algorithm, if any. In the case of AES and DES3, there is only one,
  83. * the IV.
  84. *
  85. * AlgorithmIdentifer ::= SEQUENCE {
  86. * algorithm OBJECT IDENTIFIER,
  87. * parameters ANY DEFINED BY algorithm OPTIONAL
  88. * }
  89. *
  90. * EncryptedContent ::= OCTET STRING
  91. *
  92. * RecipientInfo ::= SEQUENCE {
  93. * version Version,
  94. * issuerAndSerialNumber IssuerAndSerialNumber,
  95. * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
  96. * encryptedKey EncryptedKey
  97. * }
  98. *
  99. * IssuerAndSerialNumber ::= SEQUENCE {
  100. * issuer Name,
  101. * serialNumber CertificateSerialNumber
  102. * }
  103. *
  104. * CertificateSerialNumber ::= INTEGER
  105. *
  106. * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  107. *
  108. * EncryptedKey ::= OCTET STRING
  109. */
  110. var forge = require('./forge');
  111. require('./asn1');
  112. require('./util');
  113. // shortcut for ASN.1 API
  114. var asn1 = forge.asn1;
  115. // shortcut for PKCS#7 API
  116. var p7v = module.exports = forge.pkcs7asn1 = forge.pkcs7asn1 || {};
  117. forge.pkcs7 = forge.pkcs7 || {};
  118. forge.pkcs7.asn1 = p7v;
  119. var contentInfoValidator = {
  120. name: 'ContentInfo',
  121. tagClass: asn1.Class.UNIVERSAL,
  122. type: asn1.Type.SEQUENCE,
  123. constructed: true,
  124. value: [{
  125. name: 'ContentInfo.ContentType',
  126. tagClass: asn1.Class.UNIVERSAL,
  127. type: asn1.Type.OID,
  128. constructed: false,
  129. capture: 'contentType'
  130. }, {
  131. name: 'ContentInfo.content',
  132. tagClass: asn1.Class.CONTEXT_SPECIFIC,
  133. type: 0,
  134. constructed: true,
  135. optional: true,
  136. captureAsn1: 'content'
  137. }]
  138. };
  139. p7v.contentInfoValidator = contentInfoValidator;
  140. var encryptedContentInfoValidator = {
  141. name: 'EncryptedContentInfo',
  142. tagClass: asn1.Class.UNIVERSAL,
  143. type: asn1.Type.SEQUENCE,
  144. constructed: true,
  145. value: [{
  146. name: 'EncryptedContentInfo.contentType',
  147. tagClass: asn1.Class.UNIVERSAL,
  148. type: asn1.Type.OID,
  149. constructed: false,
  150. capture: 'contentType'
  151. }, {
  152. name: 'EncryptedContentInfo.contentEncryptionAlgorithm',
  153. tagClass: asn1.Class.UNIVERSAL,
  154. type: asn1.Type.SEQUENCE,
  155. constructed: true,
  156. value: [{
  157. name: 'EncryptedContentInfo.contentEncryptionAlgorithm.algorithm',
  158. tagClass: asn1.Class.UNIVERSAL,
  159. type: asn1.Type.OID,
  160. constructed: false,
  161. capture: 'encAlgorithm'
  162. }, {
  163. name: 'EncryptedContentInfo.contentEncryptionAlgorithm.parameter',
  164. tagClass: asn1.Class.UNIVERSAL,
  165. captureAsn1: 'encParameter'
  166. }]
  167. }, {
  168. name: 'EncryptedContentInfo.encryptedContent',
  169. tagClass: asn1.Class.CONTEXT_SPECIFIC,
  170. type: 0,
  171. /* The PKCS#7 structure output by OpenSSL somewhat differs from what
  172. * other implementations do generate.
  173. *
  174. * OpenSSL generates a structure like this:
  175. * SEQUENCE {
  176. * ...
  177. * [0]
  178. * 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38
  179. * C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45
  180. * ...
  181. * }
  182. *
  183. * Whereas other implementations (and this PKCS#7 module) generate:
  184. * SEQUENCE {
  185. * ...
  186. * [0] {
  187. * OCTET STRING
  188. * 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38
  189. * C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45
  190. * ...
  191. * }
  192. * }
  193. *
  194. * In order to support both, we just capture the context specific
  195. * field here. The OCTET STRING bit is removed below.
  196. */
  197. capture: 'encryptedContent',
  198. captureAsn1: 'encryptedContentAsn1'
  199. }]
  200. };
  201. p7v.envelopedDataValidator = {
  202. name: 'EnvelopedData',
  203. tagClass: asn1.Class.UNIVERSAL,
  204. type: asn1.Type.SEQUENCE,
  205. constructed: true,
  206. value: [{
  207. name: 'EnvelopedData.Version',
  208. tagClass: asn1.Class.UNIVERSAL,
  209. type: asn1.Type.INTEGER,
  210. constructed: false,
  211. capture: 'version'
  212. }, {
  213. name: 'EnvelopedData.RecipientInfos',
  214. tagClass: asn1.Class.UNIVERSAL,
  215. type: asn1.Type.SET,
  216. constructed: true,
  217. captureAsn1: 'recipientInfos'
  218. }].concat(encryptedContentInfoValidator)
  219. };
  220. p7v.encryptedDataValidator = {
  221. name: 'EncryptedData',
  222. tagClass: asn1.Class.UNIVERSAL,
  223. type: asn1.Type.SEQUENCE,
  224. constructed: true,
  225. value: [{
  226. name: 'EncryptedData.Version',
  227. tagClass: asn1.Class.UNIVERSAL,
  228. type: asn1.Type.INTEGER,
  229. constructed: false,
  230. capture: 'version'
  231. }].concat(encryptedContentInfoValidator)
  232. };
  233. var signerValidator = {
  234. name: 'SignerInfo',
  235. tagClass: asn1.Class.UNIVERSAL,
  236. type: asn1.Type.SEQUENCE,
  237. constructed: true,
  238. value: [{
  239. name: 'SignerInfo.version',
  240. tagClass: asn1.Class.UNIVERSAL,
  241. type: asn1.Type.INTEGER,
  242. constructed: false
  243. }, {
  244. name: 'SignerInfo.issuerAndSerialNumber',
  245. tagClass: asn1.Class.UNIVERSAL,
  246. type: asn1.Type.SEQUENCE,
  247. constructed: true,
  248. value: [{
  249. name: 'SignerInfo.issuerAndSerialNumber.issuer',
  250. tagClass: asn1.Class.UNIVERSAL,
  251. type: asn1.Type.SEQUENCE,
  252. constructed: true,
  253. captureAsn1: 'issuer'
  254. }, {
  255. name: 'SignerInfo.issuerAndSerialNumber.serialNumber',
  256. tagClass: asn1.Class.UNIVERSAL,
  257. type: asn1.Type.INTEGER,
  258. constructed: false,
  259. capture: 'serial'
  260. }]
  261. }, {
  262. name: 'SignerInfo.digestAlgorithm',
  263. tagClass: asn1.Class.UNIVERSAL,
  264. type: asn1.Type.SEQUENCE,
  265. constructed: true,
  266. value: [{
  267. name: 'SignerInfo.digestAlgorithm.algorithm',
  268. tagClass: asn1.Class.UNIVERSAL,
  269. type: asn1.Type.OID,
  270. constructed: false,
  271. capture: 'digestAlgorithm'
  272. }, {
  273. name: 'SignerInfo.digestAlgorithm.parameter',
  274. tagClass: asn1.Class.UNIVERSAL,
  275. constructed: false,
  276. captureAsn1: 'digestParameter',
  277. optional: true
  278. }]
  279. }, {
  280. name: 'SignerInfo.authenticatedAttributes',
  281. tagClass: asn1.Class.CONTEXT_SPECIFIC,
  282. type: 0,
  283. constructed: true,
  284. optional: true,
  285. capture: 'authenticatedAttributes'
  286. }, {
  287. name: 'SignerInfo.digestEncryptionAlgorithm',
  288. tagClass: asn1.Class.UNIVERSAL,
  289. type: asn1.Type.SEQUENCE,
  290. constructed: true,
  291. capture: 'signatureAlgorithm'
  292. }, {
  293. name: 'SignerInfo.encryptedDigest',
  294. tagClass: asn1.Class.UNIVERSAL,
  295. type: asn1.Type.OCTETSTRING,
  296. constructed: false,
  297. capture: 'signature'
  298. }, {
  299. name: 'SignerInfo.unauthenticatedAttributes',
  300. tagClass: asn1.Class.CONTEXT_SPECIFIC,
  301. type: 1,
  302. constructed: true,
  303. optional: true,
  304. capture: 'unauthenticatedAttributes'
  305. }]
  306. };
  307. p7v.signedDataValidator = {
  308. name: 'SignedData',
  309. tagClass: asn1.Class.UNIVERSAL,
  310. type: asn1.Type.SEQUENCE,
  311. constructed: true,
  312. value: [{
  313. name: 'SignedData.Version',
  314. tagClass: asn1.Class.UNIVERSAL,
  315. type: asn1.Type.INTEGER,
  316. constructed: false,
  317. capture: 'version'
  318. }, {
  319. name: 'SignedData.DigestAlgorithms',
  320. tagClass: asn1.Class.UNIVERSAL,
  321. type: asn1.Type.SET,
  322. constructed: true,
  323. captureAsn1: 'digestAlgorithms'
  324. },
  325. contentInfoValidator,
  326. {
  327. name: 'SignedData.Certificates',
  328. tagClass: asn1.Class.CONTEXT_SPECIFIC,
  329. type: 0,
  330. optional: true,
  331. captureAsn1: 'certificates'
  332. }, {
  333. name: 'SignedData.CertificateRevocationLists',
  334. tagClass: asn1.Class.CONTEXT_SPECIFIC,
  335. type: 1,
  336. optional: true,
  337. captureAsn1: 'crls'
  338. }, {
  339. name: 'SignedData.SignerInfos',
  340. tagClass: asn1.Class.UNIVERSAL,
  341. type: asn1.Type.SET,
  342. capture: 'signerInfos',
  343. optional: true,
  344. value: [signerValidator]
  345. }]
  346. };
  347. p7v.recipientInfoValidator = {
  348. name: 'RecipientInfo',
  349. tagClass: asn1.Class.UNIVERSAL,
  350. type: asn1.Type.SEQUENCE,
  351. constructed: true,
  352. value: [{
  353. name: 'RecipientInfo.version',
  354. tagClass: asn1.Class.UNIVERSAL,
  355. type: asn1.Type.INTEGER,
  356. constructed: false,
  357. capture: 'version'
  358. }, {
  359. name: 'RecipientInfo.issuerAndSerial',
  360. tagClass: asn1.Class.UNIVERSAL,
  361. type: asn1.Type.SEQUENCE,
  362. constructed: true,
  363. value: [{
  364. name: 'RecipientInfo.issuerAndSerial.issuer',
  365. tagClass: asn1.Class.UNIVERSAL,
  366. type: asn1.Type.SEQUENCE,
  367. constructed: true,
  368. captureAsn1: 'issuer'
  369. }, {
  370. name: 'RecipientInfo.issuerAndSerial.serialNumber',
  371. tagClass: asn1.Class.UNIVERSAL,
  372. type: asn1.Type.INTEGER,
  373. constructed: false,
  374. capture: 'serial'
  375. }]
  376. }, {
  377. name: 'RecipientInfo.keyEncryptionAlgorithm',
  378. tagClass: asn1.Class.UNIVERSAL,
  379. type: asn1.Type.SEQUENCE,
  380. constructed: true,
  381. value: [{
  382. name: 'RecipientInfo.keyEncryptionAlgorithm.algorithm',
  383. tagClass: asn1.Class.UNIVERSAL,
  384. type: asn1.Type.OID,
  385. constructed: false,
  386. capture: 'encAlgorithm'
  387. }, {
  388. name: 'RecipientInfo.keyEncryptionAlgorithm.parameter',
  389. tagClass: asn1.Class.UNIVERSAL,
  390. constructed: false,
  391. captureAsn1: 'encParameter'
  392. }]
  393. }, {
  394. name: 'RecipientInfo.encryptedKey',
  395. tagClass: asn1.Class.UNIVERSAL,
  396. type: asn1.Type.OCTETSTRING,
  397. constructed: false,
  398. capture: 'encKey'
  399. }]
  400. };