/security/nss/lib/pkcs7/p7local.c

http://github.com/zpao/v8monkey · C · 1353 lines · 785 code · 158 blank · 410 comment · 198 complexity · 9e830ac871cc6b7404153ac2ebac610f MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. /*
  37. * Support routines for PKCS7 implementation, none of which are exported.
  38. * This file should only contain things that are needed by both the
  39. * encoding/creation side *and* the decoding/decryption side. Anything
  40. * else should be static routines in the appropriate file.
  41. *
  42. * $Id: p7local.c,v 1.15 2011/08/21 01:14:17 wtc%google.com Exp $
  43. */
  44. #include "p7local.h"
  45. #include "cryptohi.h"
  46. #include "secasn1.h"
  47. #include "secoid.h"
  48. #include "secitem.h"
  49. #include "pk11func.h"
  50. #include "secpkcs5.h"
  51. #include "secerr.h"
  52. /*
  53. * -------------------------------------------------------------------
  54. * Cipher stuff.
  55. */
  56. typedef SECStatus (*sec_pkcs7_cipher_function) (void *,
  57. unsigned char *,
  58. unsigned *,
  59. unsigned int,
  60. const unsigned char *,
  61. unsigned int);
  62. typedef SECStatus (*sec_pkcs7_cipher_destroy) (void *, PRBool);
  63. #define BLOCK_SIZE 4096
  64. struct sec_pkcs7_cipher_object {
  65. void *cx;
  66. sec_pkcs7_cipher_function doit;
  67. sec_pkcs7_cipher_destroy destroy;
  68. PRBool encrypt;
  69. int block_size;
  70. int pad_size;
  71. int pending_count;
  72. unsigned char pending_buf[BLOCK_SIZE];
  73. };
  74. SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate)
  75. SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate)
  76. SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
  77. SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
  78. SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate)
  79. /*
  80. * Create a cipher object to do decryption, based on the given bulk
  81. * encryption key and algorithm identifier (which may include an iv).
  82. *
  83. * XXX This interface, or one similar, would be really nice available
  84. * in general... I tried to keep the pkcs7-specific stuff (mostly
  85. * having to do with padding) out of here.
  86. *
  87. * XXX Once both are working, it might be nice to combine this and the
  88. * function below (for starting up encryption) into one routine, and just
  89. * have two simple cover functions which call it.
  90. */
  91. sec_PKCS7CipherObject *
  92. sec_PKCS7CreateDecryptObject (PK11SymKey *key, SECAlgorithmID *algid)
  93. {
  94. sec_PKCS7CipherObject *result;
  95. SECOidTag algtag;
  96. void *ciphercx;
  97. CK_MECHANISM_TYPE cryptoMechType;
  98. PK11SlotInfo *slot;
  99. SECItem *param = NULL;
  100. result = (struct sec_pkcs7_cipher_object*)
  101. PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object));
  102. if (result == NULL)
  103. return NULL;
  104. ciphercx = NULL;
  105. algtag = SECOID_GetAlgorithmTag (algid);
  106. if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
  107. SECItem *pwitem;
  108. pwitem = (SECItem *)PK11_GetSymKeyUserData(key);
  109. if (!pwitem) {
  110. PORT_Free(result);
  111. return NULL;
  112. }
  113. cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
  114. if (cryptoMechType == CKM_INVALID_MECHANISM) {
  115. PORT_Free(result);
  116. SECITEM_FreeItem(param,PR_TRUE);
  117. return NULL;
  118. }
  119. } else {
  120. cryptoMechType = PK11_AlgtagToMechanism(algtag);
  121. param = PK11_ParamFromAlgid(algid);
  122. if (param == NULL) {
  123. PORT_Free(result);
  124. return NULL;
  125. }
  126. }
  127. result->pad_size = PK11_GetBlockSize(cryptoMechType, param);
  128. slot = PK11_GetSlotFromKey(key);
  129. result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size;
  130. PK11_FreeSlot(slot);
  131. ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT,
  132. key, param);
  133. SECITEM_FreeItem(param,PR_TRUE);
  134. if (ciphercx == NULL) {
  135. PORT_Free (result);
  136. return NULL;
  137. }
  138. result->cx = ciphercx;
  139. result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp;
  140. result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext;
  141. result->encrypt = PR_FALSE;
  142. result->pending_count = 0;
  143. return result;
  144. }
  145. /*
  146. * Create a cipher object to do encryption, based on the given bulk
  147. * encryption key and algorithm tag. Fill in the algorithm identifier
  148. * (which may include an iv) appropriately.
  149. *
  150. * XXX This interface, or one similar, would be really nice available
  151. * in general... I tried to keep the pkcs7-specific stuff (mostly
  152. * having to do with padding) out of here.
  153. *
  154. * XXX Once both are working, it might be nice to combine this and the
  155. * function above (for starting up decryption) into one routine, and just
  156. * have two simple cover functions which call it.
  157. */
  158. sec_PKCS7CipherObject *
  159. sec_PKCS7CreateEncryptObject (PRArenaPool *poolp, PK11SymKey *key,
  160. SECOidTag algtag, SECAlgorithmID *algid)
  161. {
  162. sec_PKCS7CipherObject *result;
  163. void *ciphercx;
  164. SECStatus rv;
  165. CK_MECHANISM_TYPE cryptoMechType;
  166. PK11SlotInfo *slot;
  167. SECItem *param = NULL;
  168. PRBool needToEncodeAlgid = PR_FALSE;
  169. result = (struct sec_pkcs7_cipher_object*)
  170. PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object));
  171. if (result == NULL)
  172. return NULL;
  173. ciphercx = NULL;
  174. if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
  175. SECItem *pwitem;
  176. pwitem = (SECItem *)PK11_GetSymKeyUserData(key);
  177. if (!pwitem) {
  178. PORT_Free(result);
  179. return NULL;
  180. }
  181. cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
  182. if (cryptoMechType == CKM_INVALID_MECHANISM) {
  183. PORT_Free(result);
  184. SECITEM_FreeItem(param,PR_TRUE);
  185. return NULL;
  186. }
  187. } else {
  188. cryptoMechType = PK11_AlgtagToMechanism(algtag);
  189. param = PK11_GenerateNewParam(cryptoMechType, key);
  190. if (param == NULL) {
  191. PORT_Free(result);
  192. return NULL;
  193. }
  194. needToEncodeAlgid = PR_TRUE;
  195. }
  196. result->pad_size = PK11_GetBlockSize(cryptoMechType,param);
  197. slot = PK11_GetSlotFromKey(key);
  198. result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size;
  199. PK11_FreeSlot(slot);
  200. ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
  201. key, param);
  202. if (ciphercx == NULL) {
  203. PORT_Free (result);
  204. SECITEM_FreeItem(param,PR_TRUE);
  205. return NULL;
  206. }
  207. /*
  208. * These are placed after the CreateContextBySymKey() because some
  209. * mechanisms have to generate their IVs from their card (i.e. FORTEZZA).
  210. * Don't move it from here.
  211. */
  212. if (needToEncodeAlgid) {
  213. rv = PK11_ParamToAlgid(algtag,param,poolp,algid);
  214. if(rv != SECSuccess) {
  215. PORT_Free (result);
  216. SECITEM_FreeItem(param,PR_TRUE);
  217. return NULL;
  218. }
  219. }
  220. SECITEM_FreeItem(param,PR_TRUE);
  221. result->cx = ciphercx;
  222. result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp;
  223. result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext;
  224. result->encrypt = PR_TRUE;
  225. result->pending_count = 0;
  226. return result;
  227. }
  228. /*
  229. * Destroy the cipher object.
  230. */
  231. static void
  232. sec_pkcs7_destroy_cipher (sec_PKCS7CipherObject *obj)
  233. {
  234. (* obj->destroy) (obj->cx, PR_TRUE);
  235. PORT_Free (obj);
  236. }
  237. void
  238. sec_PKCS7DestroyDecryptObject (sec_PKCS7CipherObject *obj)
  239. {
  240. PORT_Assert (obj != NULL);
  241. if (obj == NULL)
  242. return;
  243. PORT_Assert (! obj->encrypt);
  244. sec_pkcs7_destroy_cipher (obj);
  245. }
  246. void
  247. sec_PKCS7DestroyEncryptObject (sec_PKCS7CipherObject *obj)
  248. {
  249. PORT_Assert (obj != NULL);
  250. if (obj == NULL)
  251. return;
  252. PORT_Assert (obj->encrypt);
  253. sec_pkcs7_destroy_cipher (obj);
  254. }
  255. /*
  256. * XXX I think all of the following lengths should be longs instead
  257. * of ints, but our current crypto interface uses ints, so I did too.
  258. */
  259. /*
  260. * What will be the output length of the next call to decrypt?
  261. * Result can be used to perform memory allocations. Note that the amount
  262. * is exactly accurate only when not doing a block cipher or when final
  263. * is false, otherwise it is an upper bound on the amount because until
  264. * we see the data we do not know how many padding bytes there are
  265. * (always between 1 and bsize).
  266. *
  267. * Note that this can return zero, which does not mean that the decrypt
  268. * operation can be skipped! (It simply means that there are not enough
  269. * bytes to make up an entire block; the bytes will be reserved until
  270. * there are enough to encrypt/decrypt at least one block.) However,
  271. * if zero is returned it *does* mean that no output buffer need be
  272. * passed in to the subsequent decrypt operation, as no output bytes
  273. * will be stored.
  274. */
  275. unsigned int
  276. sec_PKCS7DecryptLength (sec_PKCS7CipherObject *obj, unsigned int input_len,
  277. PRBool final)
  278. {
  279. int blocks, block_size;
  280. PORT_Assert (! obj->encrypt);
  281. block_size = obj->block_size;
  282. /*
  283. * If this is not a block cipher, then we always have the same
  284. * number of output bytes as we had input bytes.
  285. */
  286. if (block_size == 0)
  287. return input_len;
  288. /*
  289. * On the final call, we will always use up all of the pending
  290. * bytes plus all of the input bytes, *but*, there will be padding
  291. * at the end and we cannot predict how many bytes of padding we
  292. * will end up removing. The amount given here is actually known
  293. * to be at least 1 byte too long (because we know we will have
  294. * at least 1 byte of padding), but seemed clearer/better to me.
  295. */
  296. if (final)
  297. return obj->pending_count + input_len;
  298. /*
  299. * Okay, this amount is exactly what we will output on the
  300. * next cipher operation. We will always hang onto the last
  301. * 1 - block_size bytes for non-final operations. That is,
  302. * we will do as many complete blocks as we can *except* the
  303. * last block (complete or partial). (This is because until
  304. * we know we are at the end, we cannot know when to interpret
  305. * and removing the padding byte(s), which are guaranteed to
  306. * be there.)
  307. */
  308. blocks = (obj->pending_count + input_len - 1) / block_size;
  309. return blocks * block_size;
  310. }
  311. /*
  312. * What will be the output length of the next call to encrypt?
  313. * Result can be used to perform memory allocations.
  314. *
  315. * Note that this can return zero, which does not mean that the encrypt
  316. * operation can be skipped! (It simply means that there are not enough
  317. * bytes to make up an entire block; the bytes will be reserved until
  318. * there are enough to encrypt/decrypt at least one block.) However,
  319. * if zero is returned it *does* mean that no output buffer need be
  320. * passed in to the subsequent encrypt operation, as no output bytes
  321. * will be stored.
  322. */
  323. unsigned int
  324. sec_PKCS7EncryptLength (sec_PKCS7CipherObject *obj, unsigned int input_len,
  325. PRBool final)
  326. {
  327. int blocks, block_size;
  328. int pad_size;
  329. PORT_Assert (obj->encrypt);
  330. block_size = obj->block_size;
  331. pad_size = obj->pad_size;
  332. /*
  333. * If this is not a block cipher, then we always have the same
  334. * number of output bytes as we had input bytes.
  335. */
  336. if (block_size == 0)
  337. return input_len;
  338. /*
  339. * On the final call, we only send out what we need for
  340. * remaining bytes plus the padding. (There is always padding,
  341. * so even if we have an exact number of blocks as input, we
  342. * will add another full block that is just padding.)
  343. */
  344. if (final) {
  345. if (pad_size == 0) {
  346. return obj->pending_count + input_len;
  347. } else {
  348. blocks = (obj->pending_count + input_len) / pad_size;
  349. blocks++;
  350. return blocks*pad_size;
  351. }
  352. }
  353. /*
  354. * Now, count the number of complete blocks of data we have.
  355. */
  356. blocks = (obj->pending_count + input_len) / block_size;
  357. return blocks * block_size;
  358. }
  359. /*
  360. * Decrypt a given length of input buffer (starting at "input" and
  361. * containing "input_len" bytes), placing the decrypted bytes in
  362. * "output" and storing the output length in "*output_len_p".
  363. * "obj" is the return value from sec_PKCS7CreateDecryptObject.
  364. * When "final" is true, this is the last of the data to be decrypted.
  365. *
  366. * This is much more complicated than it sounds when the cipher is
  367. * a block-type, meaning that the decryption function will only
  368. * operate on whole blocks. But our caller is operating stream-wise,
  369. * and can pass in any number of bytes. So we need to keep track
  370. * of block boundaries. We save excess bytes between calls in "obj".
  371. * We also need to determine which bytes are padding, and remove
  372. * them from the output. We can only do this step when we know we
  373. * have the final block of data. PKCS #7 specifies that the padding
  374. * used for a block cipher is a string of bytes, each of whose value is
  375. * the same as the length of the padding, and that all data is padded.
  376. * (Even data that starts out with an exact multiple of blocks gets
  377. * added to it another block, all of which is padding.)
  378. */
  379. SECStatus
  380. sec_PKCS7Decrypt (sec_PKCS7CipherObject *obj, unsigned char *output,
  381. unsigned int *output_len_p, unsigned int max_output_len,
  382. const unsigned char *input, unsigned int input_len,
  383. PRBool final)
  384. {
  385. int blocks, bsize, pcount, padsize;
  386. unsigned int max_needed, ifraglen, ofraglen, output_len;
  387. unsigned char *pbuf;
  388. SECStatus rv;
  389. PORT_Assert (! obj->encrypt);
  390. /*
  391. * Check that we have enough room for the output. Our caller should
  392. * already handle this; failure is really an internal error (i.e. bug).
  393. */
  394. max_needed = sec_PKCS7DecryptLength (obj, input_len, final);
  395. PORT_Assert (max_output_len >= max_needed);
  396. if (max_output_len < max_needed) {
  397. /* PORT_SetError (XXX); */
  398. return SECFailure;
  399. }
  400. /*
  401. * hardware encryption does not like small decryption sizes here, so we
  402. * allow both blocking and padding.
  403. */
  404. bsize = obj->block_size;
  405. padsize = obj->pad_size;
  406. /*
  407. * When no blocking or padding work to do, we can simply call the
  408. * cipher function and we are done.
  409. */
  410. if (bsize == 0) {
  411. return (* obj->doit) (obj->cx, output, output_len_p, max_output_len,
  412. input, input_len);
  413. }
  414. pcount = obj->pending_count;
  415. pbuf = obj->pending_buf;
  416. output_len = 0;
  417. if (pcount) {
  418. /*
  419. * Try to fill in an entire block, starting with the bytes
  420. * we already have saved away.
  421. */
  422. while (input_len && pcount < bsize) {
  423. pbuf[pcount++] = *input++;
  424. input_len--;
  425. }
  426. /*
  427. * If we have at most a whole block and this is not our last call,
  428. * then we are done for now. (We do not try to decrypt a lone
  429. * single block because we cannot interpret the padding bytes
  430. * until we know we are handling the very last block of all input.)
  431. */
  432. if (input_len == 0 && !final) {
  433. obj->pending_count = pcount;
  434. if (output_len_p)
  435. *output_len_p = 0;
  436. return SECSuccess;
  437. }
  438. /*
  439. * Given the logic above, we expect to have a full block by now.
  440. * If we do not, there is something wrong, either with our own
  441. * logic or with (length of) the data given to us.
  442. */
  443. PORT_Assert ((padsize == 0) || (pcount % padsize) == 0);
  444. if ((padsize != 0) && (pcount % padsize) != 0) {
  445. PORT_Assert (final);
  446. PORT_SetError (SEC_ERROR_BAD_DATA);
  447. return SECFailure;
  448. }
  449. /*
  450. * Decrypt the block.
  451. */
  452. rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
  453. pbuf, pcount);
  454. if (rv != SECSuccess)
  455. return rv;
  456. /*
  457. * For now anyway, all of our ciphers have the same number of
  458. * bytes of output as they do input. If this ever becomes untrue,
  459. * then sec_PKCS7DecryptLength needs to be made smarter!
  460. */
  461. PORT_Assert (ofraglen == pcount);
  462. /*
  463. * Account for the bytes now in output.
  464. */
  465. max_output_len -= ofraglen;
  466. output_len += ofraglen;
  467. output += ofraglen;
  468. }
  469. /*
  470. * If this is our last call, we expect to have an exact number of
  471. * blocks left to be decrypted; we will decrypt them all.
  472. *
  473. * If not our last call, we always save between 1 and bsize bytes
  474. * until next time. (We must do this because we cannot be sure
  475. * that none of the decrypted bytes are padding bytes until we
  476. * have at least another whole block of data. You cannot tell by
  477. * looking -- the data could be anything -- you can only tell by
  478. * context, knowing you are looking at the last block.) We could
  479. * decrypt a whole block now but it is easier if we just treat it
  480. * the same way we treat partial block bytes.
  481. */
  482. if (final) {
  483. if (padsize) {
  484. blocks = input_len / padsize;
  485. ifraglen = blocks * padsize;
  486. } else ifraglen = input_len;
  487. PORT_Assert (ifraglen == input_len);
  488. if (ifraglen != input_len) {
  489. PORT_SetError (SEC_ERROR_BAD_DATA);
  490. return SECFailure;
  491. }
  492. } else {
  493. blocks = (input_len - 1) / bsize;
  494. ifraglen = blocks * bsize;
  495. PORT_Assert (ifraglen < input_len);
  496. pcount = input_len - ifraglen;
  497. PORT_Memcpy (pbuf, input + ifraglen, pcount);
  498. obj->pending_count = pcount;
  499. }
  500. if (ifraglen) {
  501. rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
  502. input, ifraglen);
  503. if (rv != SECSuccess)
  504. return rv;
  505. /*
  506. * For now anyway, all of our ciphers have the same number of
  507. * bytes of output as they do input. If this ever becomes untrue,
  508. * then sec_PKCS7DecryptLength needs to be made smarter!
  509. */
  510. PORT_Assert (ifraglen == ofraglen);
  511. if (ifraglen != ofraglen) {
  512. PORT_SetError (SEC_ERROR_BAD_DATA);
  513. return SECFailure;
  514. }
  515. output_len += ofraglen;
  516. } else {
  517. ofraglen = 0;
  518. }
  519. /*
  520. * If we just did our very last block, "remove" the padding by
  521. * adjusting the output length.
  522. */
  523. if (final && (padsize != 0)) {
  524. unsigned int padlen = *(output + ofraglen - 1);
  525. if (padlen == 0 || padlen > padsize) {
  526. PORT_SetError (SEC_ERROR_BAD_DATA);
  527. return SECFailure;
  528. }
  529. output_len -= padlen;
  530. }
  531. PORT_Assert (output_len_p != NULL || output_len == 0);
  532. if (output_len_p != NULL)
  533. *output_len_p = output_len;
  534. return SECSuccess;
  535. }
  536. /*
  537. * Encrypt a given length of input buffer (starting at "input" and
  538. * containing "input_len" bytes), placing the encrypted bytes in
  539. * "output" and storing the output length in "*output_len_p".
  540. * "obj" is the return value from sec_PKCS7CreateEncryptObject.
  541. * When "final" is true, this is the last of the data to be encrypted.
  542. *
  543. * This is much more complicated than it sounds when the cipher is
  544. * a block-type, meaning that the encryption function will only
  545. * operate on whole blocks. But our caller is operating stream-wise,
  546. * and can pass in any number of bytes. So we need to keep track
  547. * of block boundaries. We save excess bytes between calls in "obj".
  548. * We also need to add padding bytes at the end. PKCS #7 specifies
  549. * that the padding used for a block cipher is a string of bytes,
  550. * each of whose value is the same as the length of the padding,
  551. * and that all data is padded. (Even data that starts out with
  552. * an exact multiple of blocks gets added to it another block,
  553. * all of which is padding.)
  554. *
  555. * XXX I would kind of like to combine this with the function above
  556. * which does decryption, since they have a lot in common. But the
  557. * tricky parts about padding and filling blocks would be much
  558. * harder to read that way, so I left them separate. At least for
  559. * now until it is clear that they are right.
  560. */
  561. SECStatus
  562. sec_PKCS7Encrypt (sec_PKCS7CipherObject *obj, unsigned char *output,
  563. unsigned int *output_len_p, unsigned int max_output_len,
  564. const unsigned char *input, unsigned int input_len,
  565. PRBool final)
  566. {
  567. int blocks, bsize, padlen, pcount, padsize;
  568. unsigned int max_needed, ifraglen, ofraglen, output_len;
  569. unsigned char *pbuf;
  570. SECStatus rv;
  571. PORT_Assert (obj->encrypt);
  572. /*
  573. * Check that we have enough room for the output. Our caller should
  574. * already handle this; failure is really an internal error (i.e. bug).
  575. */
  576. max_needed = sec_PKCS7EncryptLength (obj, input_len, final);
  577. PORT_Assert (max_output_len >= max_needed);
  578. if (max_output_len < max_needed) {
  579. /* PORT_SetError (XXX); */
  580. return SECFailure;
  581. }
  582. bsize = obj->block_size;
  583. padsize = obj->pad_size;
  584. /*
  585. * When no blocking and padding work to do, we can simply call the
  586. * cipher function and we are done.
  587. */
  588. if (bsize == 0) {
  589. return (* obj->doit) (obj->cx, output, output_len_p, max_output_len,
  590. input, input_len);
  591. }
  592. pcount = obj->pending_count;
  593. pbuf = obj->pending_buf;
  594. output_len = 0;
  595. if (pcount) {
  596. /*
  597. * Try to fill in an entire block, starting with the bytes
  598. * we already have saved away.
  599. */
  600. while (input_len && pcount < bsize) {
  601. pbuf[pcount++] = *input++;
  602. input_len--;
  603. }
  604. /*
  605. * If we do not have a full block and we know we will be
  606. * called again, then we are done for now.
  607. */
  608. if (pcount < bsize && !final) {
  609. obj->pending_count = pcount;
  610. if (output_len_p != NULL)
  611. *output_len_p = 0;
  612. return SECSuccess;
  613. }
  614. /*
  615. * If we have a whole block available, encrypt it.
  616. */
  617. if ((padsize == 0) || (pcount % padsize) == 0) {
  618. rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
  619. pbuf, pcount);
  620. if (rv != SECSuccess)
  621. return rv;
  622. /*
  623. * For now anyway, all of our ciphers have the same number of
  624. * bytes of output as they do input. If this ever becomes untrue,
  625. * then sec_PKCS7EncryptLength needs to be made smarter!
  626. */
  627. PORT_Assert (ofraglen == pcount);
  628. /*
  629. * Account for the bytes now in output.
  630. */
  631. max_output_len -= ofraglen;
  632. output_len += ofraglen;
  633. output += ofraglen;
  634. pcount = 0;
  635. }
  636. }
  637. if (input_len) {
  638. PORT_Assert (pcount == 0);
  639. blocks = input_len / bsize;
  640. ifraglen = blocks * bsize;
  641. if (ifraglen) {
  642. rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
  643. input, ifraglen);
  644. if (rv != SECSuccess)
  645. return rv;
  646. /*
  647. * For now anyway, all of our ciphers have the same number of
  648. * bytes of output as they do input. If this ever becomes untrue,
  649. * then sec_PKCS7EncryptLength needs to be made smarter!
  650. */
  651. PORT_Assert (ifraglen == ofraglen);
  652. max_output_len -= ofraglen;
  653. output_len += ofraglen;
  654. output += ofraglen;
  655. }
  656. pcount = input_len - ifraglen;
  657. PORT_Assert (pcount < bsize);
  658. if (pcount)
  659. PORT_Memcpy (pbuf, input + ifraglen, pcount);
  660. }
  661. if (final) {
  662. padlen = padsize - (pcount % padsize);
  663. PORT_Memset (pbuf + pcount, padlen, padlen);
  664. rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len,
  665. pbuf, pcount+padlen);
  666. if (rv != SECSuccess)
  667. return rv;
  668. /*
  669. * For now anyway, all of our ciphers have the same number of
  670. * bytes of output as they do input. If this ever becomes untrue,
  671. * then sec_PKCS7EncryptLength needs to be made smarter!
  672. */
  673. PORT_Assert (ofraglen == (pcount+padlen));
  674. output_len += ofraglen;
  675. } else {
  676. obj->pending_count = pcount;
  677. }
  678. PORT_Assert (output_len_p != NULL || output_len == 0);
  679. if (output_len_p != NULL)
  680. *output_len_p = output_len;
  681. return SECSuccess;
  682. }
  683. /*
  684. * End of cipher stuff.
  685. * -------------------------------------------------------------------
  686. */
  687. /*
  688. * -------------------------------------------------------------------
  689. * XXX The following Attribute stuff really belongs elsewhere.
  690. * The Attribute type is *not* part of pkcs7 but rather X.501.
  691. * But for now, since PKCS7 is the only customer of attributes,
  692. * we define them here. Once there is a use outside of PKCS7,
  693. * then change the attribute types and functions from internal
  694. * to external naming convention, and move them elsewhere!
  695. */
  696. /*
  697. * Look through a set of attributes and find one that matches the
  698. * specified object ID. If "only" is true, then make sure that
  699. * there is not more than one attribute of the same type. Otherwise,
  700. * just return the first one found. (XXX Does anybody really want
  701. * that first-found behavior? It was like that when I found it...)
  702. */
  703. SEC_PKCS7Attribute *
  704. sec_PKCS7FindAttribute (SEC_PKCS7Attribute **attrs, SECOidTag oidtag,
  705. PRBool only)
  706. {
  707. SECOidData *oid;
  708. SEC_PKCS7Attribute *attr1, *attr2;
  709. if (attrs == NULL)
  710. return NULL;
  711. oid = SECOID_FindOIDByTag(oidtag);
  712. if (oid == NULL)
  713. return NULL;
  714. while ((attr1 = *attrs++) != NULL) {
  715. if (attr1->type.len == oid->oid.len && PORT_Memcmp (attr1->type.data,
  716. oid->oid.data,
  717. oid->oid.len) == 0)
  718. break;
  719. }
  720. if (attr1 == NULL)
  721. return NULL;
  722. if (!only)
  723. return attr1;
  724. while ((attr2 = *attrs++) != NULL) {
  725. if (attr2->type.len == oid->oid.len && PORT_Memcmp (attr2->type.data,
  726. oid->oid.data,
  727. oid->oid.len) == 0)
  728. break;
  729. }
  730. if (attr2 != NULL)
  731. return NULL;
  732. return attr1;
  733. }
  734. /*
  735. * Return the single attribute value, doing some sanity checking first:
  736. * - Multiple values are *not* expected.
  737. * - Empty values are *not* expected.
  738. */
  739. SECItem *
  740. sec_PKCS7AttributeValue(SEC_PKCS7Attribute *attr)
  741. {
  742. SECItem *value;
  743. if (attr == NULL)
  744. return NULL;
  745. value = attr->values[0];
  746. if (value == NULL || value->data == NULL || value->len == 0)
  747. return NULL;
  748. if (attr->values[1] != NULL)
  749. return NULL;
  750. return value;
  751. }
  752. static const SEC_ASN1Template *
  753. sec_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding)
  754. {
  755. const SEC_ASN1Template *theTemplate;
  756. SEC_PKCS7Attribute *attribute;
  757. SECOidData *oiddata;
  758. PRBool encoded;
  759. PORT_Assert (src_or_dest != NULL);
  760. if (src_or_dest == NULL)
  761. return NULL;
  762. attribute = (SEC_PKCS7Attribute*)src_or_dest;
  763. if (encoding && attribute->encoded)
  764. return SEC_ASN1_GET(SEC_AnyTemplate);
  765. oiddata = attribute->typeTag;
  766. if (oiddata == NULL) {
  767. oiddata = SECOID_FindOID(&attribute->type);
  768. attribute->typeTag = oiddata;
  769. }
  770. if (oiddata == NULL) {
  771. encoded = PR_TRUE;
  772. theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
  773. } else {
  774. switch (oiddata->offset) {
  775. default:
  776. encoded = PR_TRUE;
  777. theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
  778. break;
  779. case SEC_OID_PKCS9_EMAIL_ADDRESS:
  780. case SEC_OID_RFC1274_MAIL:
  781. case SEC_OID_PKCS9_UNSTRUCTURED_NAME:
  782. encoded = PR_FALSE;
  783. theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate);
  784. break;
  785. case SEC_OID_PKCS9_CONTENT_TYPE:
  786. encoded = PR_FALSE;
  787. theTemplate = SEC_ASN1_GET(SEC_ObjectIDTemplate);
  788. break;
  789. case SEC_OID_PKCS9_MESSAGE_DIGEST:
  790. encoded = PR_FALSE;
  791. theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate);
  792. break;
  793. case SEC_OID_PKCS9_SIGNING_TIME:
  794. encoded = PR_FALSE;
  795. theTemplate = SEC_ASN1_GET(CERT_TimeChoiceTemplate);
  796. break;
  797. /* XXX Want other types here, too */
  798. }
  799. }
  800. if (encoding) {
  801. /*
  802. * If we are encoding and we think we have an already-encoded value,
  803. * then the code which initialized this attribute should have set
  804. * the "encoded" property to true (and we would have returned early,
  805. * up above). No devastating error, but that code should be fixed.
  806. * (It could indicate that the resulting encoded bytes are wrong.)
  807. */
  808. PORT_Assert (!encoded);
  809. } else {
  810. /*
  811. * We are decoding; record whether the resulting value is
  812. * still encoded or not.
  813. */
  814. attribute->encoded = encoded;
  815. }
  816. return theTemplate;
  817. }
  818. static const SEC_ASN1TemplateChooserPtr sec_attr_chooser
  819. = sec_attr_choose_attr_value_template;
  820. static const SEC_ASN1Template sec_pkcs7_attribute_template[] = {
  821. { SEC_ASN1_SEQUENCE,
  822. 0, NULL, sizeof(SEC_PKCS7Attribute) },
  823. { SEC_ASN1_OBJECT_ID,
  824. offsetof(SEC_PKCS7Attribute,type) },
  825. { SEC_ASN1_DYNAMIC | SEC_ASN1_SET_OF,
  826. offsetof(SEC_PKCS7Attribute,values),
  827. &sec_attr_chooser },
  828. { 0 }
  829. };
  830. static const SEC_ASN1Template sec_pkcs7_set_of_attribute_template[] = {
  831. { SEC_ASN1_SET_OF, 0, sec_pkcs7_attribute_template },
  832. };
  833. /*
  834. * If you are wondering why this routine does not reorder the attributes
  835. * first, and might be tempted to make it do so, see the comment by the
  836. * call to ReorderAttributes in p7encode.c. (Or, see who else calls this
  837. * and think long and hard about the implications of making it always
  838. * do the reordering.)
  839. */
  840. SECItem *
  841. sec_PKCS7EncodeAttributes (PRArenaPool *poolp, SECItem *dest, void *src)
  842. {
  843. return SEC_ASN1EncodeItem (poolp, dest, src,
  844. sec_pkcs7_set_of_attribute_template);
  845. }
  846. /*
  847. * Make sure that the order of the attributes guarantees valid DER
  848. * (which must be in lexigraphically ascending order for a SET OF);
  849. * if reordering is necessary it will be done in place (in attrs).
  850. */
  851. SECStatus
  852. sec_PKCS7ReorderAttributes (SEC_PKCS7Attribute **attrs)
  853. {
  854. PRArenaPool *poolp;
  855. int num_attrs, i, pass, besti;
  856. unsigned int j;
  857. SECItem **enc_attrs;
  858. SEC_PKCS7Attribute **new_attrs;
  859. /*
  860. * I think we should not be called with NULL. But if we are,
  861. * call it a success anyway, because the order *is* okay.
  862. */
  863. PORT_Assert (attrs != NULL);
  864. if (attrs == NULL)
  865. return SECSuccess;
  866. /*
  867. * Count how many attributes we are dealing with here.
  868. */
  869. num_attrs = 0;
  870. while (attrs[num_attrs] != NULL)
  871. num_attrs++;
  872. /*
  873. * Again, I think we should have some attributes here.
  874. * But if we do not, or if there is only one, then call it
  875. * a success because it also already has a fine order.
  876. */
  877. PORT_Assert (num_attrs);
  878. if (num_attrs == 0 || num_attrs == 1)
  879. return SECSuccess;
  880. /*
  881. * Allocate an arena for us to work with, so it is easy to
  882. * clean up all of the memory (fairly small pieces, really).
  883. */
  884. poolp = PORT_NewArena (1024); /* XXX what is right value? */
  885. if (poolp == NULL)
  886. return SECFailure; /* no memory; nothing we can do... */
  887. /*
  888. * Allocate arrays to hold the individual encodings which we will use
  889. * for comparisons and the reordered attributes as they are sorted.
  890. */
  891. enc_attrs=(SECItem**)PORT_ArenaZAlloc(poolp, num_attrs*sizeof(SECItem *));
  892. new_attrs = (SEC_PKCS7Attribute**)PORT_ArenaZAlloc (poolp,
  893. num_attrs * sizeof(SEC_PKCS7Attribute *));
  894. if (enc_attrs == NULL || new_attrs == NULL) {
  895. PORT_FreeArena (poolp, PR_FALSE);
  896. return SECFailure;
  897. }
  898. /*
  899. * DER encode each individual attribute.
  900. */
  901. for (i = 0; i < num_attrs; i++) {
  902. enc_attrs[i] = SEC_ASN1EncodeItem (poolp, NULL, attrs[i],
  903. sec_pkcs7_attribute_template);
  904. if (enc_attrs[i] == NULL) {
  905. PORT_FreeArena (poolp, PR_FALSE);
  906. return SECFailure;
  907. }
  908. }
  909. /*
  910. * Now compare and sort them; this is not the most efficient sorting
  911. * method, but it is just fine for the problem at hand, because the
  912. * number of attributes is (always) going to be small.
  913. */
  914. for (pass = 0; pass < num_attrs; pass++) {
  915. /*
  916. * Find the first not-yet-accepted attribute. (Once one is
  917. * sorted into the other array, it is cleared from enc_attrs.)
  918. */
  919. for (i = 0; i < num_attrs; i++) {
  920. if (enc_attrs[i] != NULL)
  921. break;
  922. }
  923. PORT_Assert (i < num_attrs);
  924. besti = i;
  925. /*
  926. * Find the lowest (lexigraphically) encoding. One that is
  927. * shorter than all the rest is known to be "less" because each
  928. * attribute is of the same type (a SEQUENCE) and so thus the
  929. * first octet of each is the same, and the second octet is
  930. * the length (or the length of the length with the high bit
  931. * set, followed by the length, which also works out to always
  932. * order the shorter first). Two (or more) that have the
  933. * same length need to be compared byte by byte until a mismatch
  934. * is found.
  935. */
  936. for (i = besti + 1; i < num_attrs; i++) {
  937. if (enc_attrs[i] == NULL) /* slot already handled */
  938. continue;
  939. if (enc_attrs[i]->len != enc_attrs[besti]->len) {
  940. if (enc_attrs[i]->len < enc_attrs[besti]->len)
  941. besti = i;
  942. continue;
  943. }
  944. for (j = 0; j < enc_attrs[i]->len; j++) {
  945. if (enc_attrs[i]->data[j] < enc_attrs[besti]->data[j]) {
  946. besti = i;
  947. break;
  948. }
  949. }
  950. /*
  951. * For this not to be true, we would have to have encountered
  952. * two *identical* attributes, which I think we should not see.
  953. * So assert if it happens, but even if it does, let it go
  954. * through; the ordering of the two does not matter.
  955. */
  956. PORT_Assert (j < enc_attrs[i]->len);
  957. }
  958. /*
  959. * Now we have found the next-lowest one; copy it over and
  960. * remove it from enc_attrs.
  961. */
  962. new_attrs[pass] = attrs[besti];
  963. enc_attrs[besti] = NULL;
  964. }
  965. /*
  966. * Now new_attrs has the attributes in the order we want;
  967. * copy them back into the attrs array we started with.
  968. */
  969. for (i = 0; i < num_attrs; i++)
  970. attrs[i] = new_attrs[i];
  971. PORT_FreeArena (poolp, PR_FALSE);
  972. return SECSuccess;
  973. }
  974. /*
  975. * End of attribute stuff.
  976. * -------------------------------------------------------------------
  977. */
  978. /*
  979. * Templates and stuff. Keep these at the end of the file.
  980. */
  981. /* forward declaration */
  982. static const SEC_ASN1Template *
  983. sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding);
  984. static const SEC_ASN1TemplateChooserPtr sec_pkcs7_chooser
  985. = sec_pkcs7_choose_content_template;
  986. const SEC_ASN1Template sec_PKCS7ContentInfoTemplate[] = {
  987. { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
  988. 0, NULL, sizeof(SEC_PKCS7ContentInfo) },
  989. { SEC_ASN1_OBJECT_ID,
  990. offsetof(SEC_PKCS7ContentInfo,contentType) },
  991. { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM
  992. | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  993. offsetof(SEC_PKCS7ContentInfo,content),
  994. &sec_pkcs7_chooser },
  995. { 0 }
  996. };
  997. /* XXX These names should change from external to internal convention. */
  998. static const SEC_ASN1Template SEC_PKCS7SignerInfoTemplate[] = {
  999. { SEC_ASN1_SEQUENCE,
  1000. 0, NULL, sizeof(SEC_PKCS7SignerInfo) },
  1001. { SEC_ASN1_INTEGER,
  1002. offsetof(SEC_PKCS7SignerInfo,version) },
  1003. { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
  1004. offsetof(SEC_PKCS7SignerInfo,issuerAndSN),
  1005. SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) },
  1006. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  1007. offsetof(SEC_PKCS7SignerInfo,digestAlg),
  1008. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1009. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  1010. offsetof(SEC_PKCS7SignerInfo,authAttr),
  1011. sec_pkcs7_set_of_attribute_template },
  1012. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  1013. offsetof(SEC_PKCS7SignerInfo,digestEncAlg),
  1014. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1015. { SEC_ASN1_OCTET_STRING,
  1016. offsetof(SEC_PKCS7SignerInfo,encDigest) },
  1017. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  1018. offsetof(SEC_PKCS7SignerInfo,unAuthAttr),
  1019. sec_pkcs7_set_of_attribute_template },
  1020. { 0 }
  1021. };
  1022. static const SEC_ASN1Template SEC_PKCS7SignedDataTemplate[] = {
  1023. { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
  1024. 0, NULL, sizeof(SEC_PKCS7SignedData) },
  1025. { SEC_ASN1_INTEGER,
  1026. offsetof(SEC_PKCS7SignedData,version) },
  1027. { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
  1028. offsetof(SEC_PKCS7SignedData,digestAlgorithms),
  1029. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1030. { SEC_ASN1_INLINE,
  1031. offsetof(SEC_PKCS7SignedData,contentInfo),
  1032. sec_PKCS7ContentInfoTemplate },
  1033. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
  1034. SEC_ASN1_XTRN | 0,
  1035. offsetof(SEC_PKCS7SignedData,rawCerts),
  1036. SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
  1037. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
  1038. SEC_ASN1_XTRN | 1,
  1039. offsetof(SEC_PKCS7SignedData,crls),
  1040. SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) },
  1041. { SEC_ASN1_SET_OF,
  1042. offsetof(SEC_PKCS7SignedData,signerInfos),
  1043. SEC_PKCS7SignerInfoTemplate },
  1044. { 0 }
  1045. };
  1046. static const SEC_ASN1Template SEC_PointerToPKCS7SignedDataTemplate[] = {
  1047. { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedDataTemplate }
  1048. };
  1049. static const SEC_ASN1Template SEC_PKCS7RecipientInfoTemplate[] = {
  1050. { SEC_ASN1_SEQUENCE,
  1051. 0, NULL, sizeof(SEC_PKCS7RecipientInfo) },
  1052. { SEC_ASN1_INTEGER,
  1053. offsetof(SEC_PKCS7RecipientInfo,version) },
  1054. { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
  1055. offsetof(SEC_PKCS7RecipientInfo,issuerAndSN),
  1056. SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) },
  1057. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  1058. offsetof(SEC_PKCS7RecipientInfo,keyEncAlg),
  1059. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1060. { SEC_ASN1_OCTET_STRING,
  1061. offsetof(SEC_PKCS7RecipientInfo,encKey) },
  1062. { 0 }
  1063. };
  1064. static const SEC_ASN1Template SEC_PKCS7EncryptedContentInfoTemplate[] = {
  1065. { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
  1066. 0, NULL, sizeof(SEC_PKCS7EncryptedContentInfo) },
  1067. { SEC_ASN1_OBJECT_ID,
  1068. offsetof(SEC_PKCS7EncryptedContentInfo,contentType) },
  1069. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  1070. offsetof(SEC_PKCS7EncryptedContentInfo,contentEncAlg),
  1071. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1072. { SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_CONTEXT_SPECIFIC |
  1073. SEC_ASN1_XTRN | 0,
  1074. offsetof(SEC_PKCS7EncryptedContentInfo,encContent),
  1075. SEC_ASN1_SUB(SEC_OctetStringTemplate) },
  1076. { 0 }
  1077. };
  1078. static const SEC_ASN1Template SEC_PKCS7EnvelopedDataTemplate[] = {
  1079. { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
  1080. 0, NULL, sizeof(SEC_PKCS7EnvelopedData) },
  1081. { SEC_ASN1_INTEGER,
  1082. offsetof(SEC_PKCS7EnvelopedData,version) },
  1083. { SEC_ASN1_SET_OF,
  1084. offsetof(SEC_PKCS7EnvelopedData,recipientInfos),
  1085. SEC_PKCS7RecipientInfoTemplate },
  1086. { SEC_ASN1_INLINE,
  1087. offsetof(SEC_PKCS7EnvelopedData,encContentInfo),
  1088. SEC_PKCS7EncryptedContentInfoTemplate },
  1089. { 0 }
  1090. };
  1091. static const SEC_ASN1Template SEC_PointerToPKCS7EnvelopedDataTemplate[] = {
  1092. { SEC_ASN1_POINTER, 0, SEC_PKCS7EnvelopedDataTemplate }
  1093. };
  1094. static const SEC_ASN1Template SEC_PKCS7SignedAndEnvelopedDataTemplate[] = {
  1095. { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
  1096. 0, NULL, sizeof(SEC_PKCS7SignedAndEnvelopedData) },
  1097. { SEC_ASN1_INTEGER,
  1098. offsetof(SEC_PKCS7SignedAndEnvelopedData,version) },
  1099. { SEC_ASN1_SET_OF,
  1100. offsetof(SEC_PKCS7SignedAndEnvelopedData,recipientInfos),
  1101. SEC_PKCS7RecipientInfoTemplate },
  1102. { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
  1103. offsetof(SEC_PKCS7SignedAndEnvelopedData,digestAlgorithms),
  1104. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1105. { SEC_ASN1_INLINE,
  1106. offsetof(SEC_PKCS7SignedAndEnvelopedData,encContentInfo),
  1107. SEC_PKCS7EncryptedContentInfoTemplate },
  1108. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
  1109. SEC_ASN1_XTRN | 0,
  1110. offsetof(SEC_PKCS7SignedAndEnvelopedData,rawCerts),
  1111. SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
  1112. { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
  1113. SEC_ASN1_XTRN | 1,
  1114. offsetof(SEC_PKCS7SignedAndEnvelopedData,crls),
  1115. SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) },
  1116. { SEC_ASN1_SET_OF,
  1117. offsetof(SEC_PKCS7SignedAndEnvelopedData,signerInfos),
  1118. SEC_PKCS7SignerInfoTemplate },
  1119. { 0 }
  1120. };
  1121. static const SEC_ASN1Template
  1122. SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate[] = {
  1123. { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedAndEnvelopedDataTemplate }
  1124. };
  1125. static const SEC_ASN1Template SEC_PKCS7DigestedDataTemplate[] = {
  1126. { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
  1127. 0, NULL, sizeof(SEC_PKCS7DigestedData) },
  1128. { SEC_ASN1_INTEGER,
  1129. offsetof(SEC_PKCS7DigestedData,version) },
  1130. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  1131. offsetof(SEC_PKCS7DigestedData,digestAlg),
  1132. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1133. { SEC_ASN1_INLINE,
  1134. offsetof(SEC_PKCS7DigestedData,contentInfo),
  1135. sec_PKCS7ContentInfoTemplate },
  1136. { SEC_ASN1_OCTET_STRING,
  1137. offsetof(SEC_PKCS7DigestedData,digest) },
  1138. { 0 }
  1139. };
  1140. static const SEC_ASN1Template SEC_PointerToPKCS7DigestedDataTemplate[] = {
  1141. { SEC_ASN1_POINTER, 0, SEC_PKCS7DigestedDataTemplate }
  1142. };
  1143. static const SEC_ASN1Template SEC_PKCS7EncryptedDataTemplate[] = {
  1144. { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
  1145. 0, NULL, sizeof(SEC_PKCS7EncryptedData) },
  1146. { SEC_ASN1_INTEGER,
  1147. offsetof(SEC_PKCS7EncryptedData,version) },
  1148. { SEC_ASN1_INLINE,
  1149. offsetof(SEC_PKCS7EncryptedData,encContentInfo),
  1150. SEC_PKCS7EncryptedContentInfoTemplate },
  1151. { 0 }
  1152. };
  1153. static const SEC_ASN1Template SEC_PointerToPKCS7EncryptedDataTemplate[] = {
  1154. { SEC_ASN1_POINTER, 0, SEC_PKCS7EncryptedDataTemplate }
  1155. };
  1156. static const SEC_ASN1Template *
  1157. sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding)
  1158. {
  1159. const SEC_ASN1Template *theTemplate;
  1160. SEC_PKCS7ContentInfo *cinfo;
  1161. SECOidTag kind;
  1162. PORT_Assert (src_or_dest != NULL);
  1163. if (src_or_dest == NULL)
  1164. return NULL;
  1165. cinfo = (SEC_PKCS7ContentInfo*)src_or_dest;
  1166. kind = SEC_PKCS7ContentType (cinfo);
  1167. switch (kind) {
  1168. default:
  1169. theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
  1170. break;
  1171. case SEC_OID_PKCS7_DATA:
  1172. theTemplate = SEC_ASN1_GET(SEC_PointerToOctetStringTemplate);
  1173. break;
  1174. case SEC_OID_PKCS7_SIGNED_DATA:
  1175. theTemplate = SEC_PointerToPKCS7SignedDataTemplate;
  1176. break;
  1177. case SEC_OID_PKCS7_ENVELOPED_DATA:
  1178. theTemplate = SEC_PointerToPKCS7EnvelopedDataTemplate;
  1179. break;
  1180. case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
  1181. theTemplate = SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate;
  1182. break;
  1183. case SEC_OID_PKCS7_DIGESTED_DATA:
  1184. theTemplate = SEC_PointerToPKCS7DigestedDataTemplate;
  1185. break;
  1186. case SEC_OID_PKCS7_ENCRYPTED_DATA:
  1187. theTemplate = SEC_PointerToPKCS7EncryptedDataTemplate;
  1188. break;
  1189. }
  1190. return theTemplate;
  1191. }
  1192. /*
  1193. * End of templates. Do not add stuff after this; put new code
  1194. * up above the start of the template definitions.
  1195. */