p7local.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:43k
源码类别:

CA认证

开发平台:

WINDOWS

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