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

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.  * Encryption/decryption routines for CMS implementation, none of which are exported.
  35.  *
  36.  * $Id: cmscipher.c,v 1.2 2000/06/13 21:56:27 chrisk%netscape.com Exp $
  37.  */
  38. #include "cmslocal.h"
  39. #include "secoid.h"
  40. #include "secitem.h"
  41. #include "pk11func.h"
  42. #include "secerr.h"
  43. #include "secpkcs5.h"
  44. /*
  45.  * -------------------------------------------------------------------
  46.  * Cipher stuff.
  47.  */
  48. typedef SECStatus (*nss_cms_cipher_function) (void *, unsigned char *, unsigned int *,
  49. unsigned int, const unsigned char *, unsigned int);
  50. typedef SECStatus (*nss_cms_cipher_destroy) (void *, PRBool);
  51. #define BLOCK_SIZE 4096
  52. struct NSSCMSCipherContextStr {
  53.     void * cx; /* PK11 cipher context */
  54.     nss_cms_cipher_function doit;
  55.     nss_cms_cipher_destroy destroy;
  56.     PRBool encrypt; /* encrypt / decrypt switch */
  57.     int block_size; /* block & pad sizes for cipher */
  58.     int pad_size;
  59.     int pending_count; /* pending data (not yet en/decrypted */
  60.     unsigned char pending_buf[BLOCK_SIZE];/* because of blocking */
  61. };
  62. /*
  63.  * NSS_CMSCipherContext_StartDecrypt - create a cipher context to do decryption
  64.  * based on the given bulk * encryption key and algorithm identifier (which may include an iv).
  65.  *
  66.  * XXX Once both are working, it might be nice to combine this and the
  67.  * function below (for starting up encryption) into one routine, and just
  68.  * have two simple cover functions which call it. 
  69.  */
  70. NSSCMSCipherContext *
  71. NSS_CMSCipherContext_StartDecrypt(PK11SymKey *key, SECAlgorithmID *algid)
  72. {
  73.     NSSCMSCipherContext *cc;
  74.     void *ciphercx;
  75.     CK_MECHANISM_TYPE mechanism;
  76.     SECItem *param;
  77.     PK11SlotInfo *slot;
  78.     SECOidTag algtag;
  79.     algtag = SECOID_GetAlgorithmTag(algid);
  80.     /* set param and mechanism */
  81.     if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
  82. CK_MECHANISM pbeMech, cryptoMech;
  83. SECItem *pbeParams;
  84. SEC_PKCS5KeyAndPassword *keyPwd;
  85. PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM));
  86. PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM));
  87. /* HACK ALERT!
  88.  * in this case, key is not actually a PK11SymKey *, but a SEC_PKCS5KeyAndPassword *
  89.  */
  90. keyPwd = (SEC_PKCS5KeyAndPassword *)key;
  91. key = keyPwd->key;
  92. /* find correct PK11 mechanism and parameters to initialize pbeMech */
  93. pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
  94. pbeParams = PK11_ParamFromAlgid(algid);
  95. if (!pbeParams)
  96.     return NULL;
  97. pbeMech.pParameter = pbeParams->data;
  98. pbeMech.ulParameterLen = pbeParams->len;
  99. /* now map pbeMech to cryptoMech */
  100. if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem,
  101.   PR_FALSE) != CKR_OK) { 
  102.     SECITEM_ZfreeItem(pbeParams, PR_TRUE);
  103.     return NULL;
  104. }
  105. SECITEM_ZfreeItem(pbeParams, PR_TRUE);
  106. /* and use it to initialize param & mechanism */
  107. if ((param = (SECItem *)PORT_ZAlloc(sizeof(SECItem))) == NULL)
  108.      return NULL;
  109. param->data = (unsigned char *)cryptoMech.pParameter;
  110. param->len = cryptoMech.ulParameterLen;
  111. mechanism = cryptoMech.mechanism;
  112.     } else {
  113. mechanism = PK11_AlgtagToMechanism(algtag);
  114. if ((param = PK11_ParamFromAlgid(algid)) == NULL)
  115.     return NULL;
  116.     }
  117.     cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext));
  118.     if (cc == NULL) {
  119. SECITEM_FreeItem(param,PR_TRUE);
  120. return NULL;
  121.     }
  122.     /* figure out pad and block sizes */
  123.     cc->pad_size = PK11_GetBlockSize(mechanism, param);
  124.     slot = PK11_GetSlotFromKey(key);
  125.     cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
  126.     PK11_FreeSlot(slot);
  127.     /* create PK11 cipher context */
  128.     ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_DECRYPT, key, param);
  129.     SECITEM_FreeItem(param, PR_TRUE);
  130.     if (ciphercx == NULL) {
  131. PORT_Free (cc);
  132. return NULL;
  133.     }
  134.     cc->cx = ciphercx;
  135.     cc->doit =  (nss_cms_cipher_function) PK11_CipherOp;
  136.     cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext;
  137.     cc->encrypt = PR_FALSE;
  138.     cc->pending_count = 0;
  139.     return cc;
  140. }
  141. /*
  142.  * NSS_CMSCipherContext_StartEncrypt - create a cipher object to do encryption,
  143.  * based on the given bulk encryption key and algorithm tag.  Fill in the algorithm
  144.  * identifier (which may include an iv) appropriately.
  145.  *
  146.  * XXX Once both are working, it might be nice to combine this and the
  147.  * function above (for starting up decryption) into one routine, and just
  148.  * have two simple cover functions which call it. 
  149.  */
  150. NSSCMSCipherContext *
  151. NSS_CMSCipherContext_StartEncrypt(PRArenaPool *poolp, PK11SymKey *key, SECAlgorithmID *algid)
  152. {
  153.     NSSCMSCipherContext *cc;
  154.     void *ciphercx;
  155.     SECItem *param;
  156.     SECStatus rv;
  157.     CK_MECHANISM_TYPE mechanism;
  158.     PK11SlotInfo *slot;
  159.     PRBool needToEncodeAlgid = PR_FALSE;
  160.     SECOidTag algtag = SECOID_GetAlgorithmTag(algid);
  161.     /* set param and mechanism */
  162.     if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
  163. CK_MECHANISM pbeMech, cryptoMech;
  164. SECItem *pbeParams;
  165. SEC_PKCS5KeyAndPassword *keyPwd;
  166. PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM));
  167. PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM));
  168. /* HACK ALERT!
  169.  * in this case, key is not actually a PK11SymKey *, but a SEC_PKCS5KeyAndPassword *
  170.  */
  171. keyPwd = (SEC_PKCS5KeyAndPassword *)key;
  172. key = keyPwd->key;
  173. /* find correct PK11 mechanism and parameters to initialize pbeMech */
  174. pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
  175. pbeParams = PK11_ParamFromAlgid(algid);
  176. if (!pbeParams)
  177.     return NULL;
  178. pbeMech.pParameter = pbeParams->data;
  179. pbeMech.ulParameterLen = pbeParams->len;
  180. /* now map pbeMech to cryptoMech */
  181. if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem,
  182.   PR_FALSE) != CKR_OK) { 
  183.     SECITEM_ZfreeItem(pbeParams, PR_TRUE);
  184.     return NULL;
  185. }
  186. SECITEM_ZfreeItem(pbeParams, PR_TRUE);
  187. /* and use it to initialize param & mechanism */
  188. if ((param = (SECItem *)PORT_ZAlloc(sizeof(SECItem))) == NULL)
  189.     return NULL;
  190. param->data = (unsigned char *)cryptoMech.pParameter;
  191. param->len = cryptoMech.ulParameterLen;
  192. mechanism = cryptoMech.mechanism;
  193.     } else {
  194. mechanism = PK11_AlgtagToMechanism(algtag);
  195. if ((param = PK11_GenerateNewParam(mechanism, key)) == NULL)
  196.     return NULL;
  197. needToEncodeAlgid = PR_TRUE;
  198.     }
  199.     cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext));
  200.     if (cc == NULL)
  201. return NULL;
  202.     /* now find pad and block sizes for our mechanism */
  203.     cc->pad_size = PK11_GetBlockSize(mechanism,param);
  204.     slot = PK11_GetSlotFromKey(key);
  205.     cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
  206.     PK11_FreeSlot(slot);
  207.     /* and here we go, creating a PK11 cipher context */
  208.     ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT, key, param);
  209.     if (ciphercx == NULL) {
  210. PORT_Free(cc);
  211. cc = NULL;
  212. goto loser;
  213.     }
  214.     /*
  215.      * These are placed after the CreateContextBySymKey() because some
  216.      * mechanisms have to generate their IVs from their card (i.e. FORTEZZA).
  217.      * Don't move it from here.
  218.      * XXX is that right? the purpose of this is to get the correct algid
  219.      *     containing the IVs etc. for encoding. this means we need to set this up
  220.      *     BEFORE encoding the algid in the contentInfo, right?
  221.      */
  222.     if (needToEncodeAlgid) {
  223. rv = PK11_ParamToAlgid(algtag, param, poolp, algid);
  224. if(rv != SECSuccess) {
  225.     PORT_Free(cc);
  226.     cc = NULL;
  227.     goto loser;
  228. }
  229.     }
  230.     cc->cx = ciphercx;
  231.     cc->doit = (nss_cms_cipher_function)PK11_CipherOp;
  232.     cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext;
  233.     cc->encrypt = PR_TRUE;
  234.     cc->pending_count = 0;
  235. loser:
  236.     SECITEM_FreeItem(param, PR_TRUE);
  237.     return cc;
  238. }
  239. void
  240. NSS_CMSCipherContext_Destroy(NSSCMSCipherContext *cc)
  241. {
  242.     PORT_Assert(cc != NULL);
  243.     if (cc == NULL)
  244. return;
  245.     (*cc->destroy)(cc->cx, PR_TRUE);
  246.     PORT_Free(cc);
  247. }
  248. /*
  249.  * NSS_CMSCipherContext_DecryptLength - find the output length of the next call to decrypt.
  250.  *
  251.  * cc - the cipher context
  252.  * input_len - number of bytes used as input
  253.  * final - true if this is the final chunk of data
  254.  *
  255.  * Result can be used to perform memory allocations.  Note that the amount
  256.  * is exactly accurate only when not doing a block cipher or when final
  257.  * is false, otherwise it is an upper bound on the amount because until
  258.  * we see the data we do not know how many padding bytes there are
  259.  * (always between 1 and bsize).
  260.  *
  261.  * Note that this can return zero, which does not mean that the decrypt
  262.  * operation can be skipped!  (It simply means that there are not enough
  263.  * bytes to make up an entire block; the bytes will be reserved until
  264.  * there are enough to encrypt/decrypt at least one block.)  However,
  265.  * if zero is returned it *does* mean that no output buffer need be
  266.  * passed in to the subsequent decrypt operation, as no output bytes
  267.  * will be stored.
  268.  */
  269. unsigned int
  270. NSS_CMSCipherContext_DecryptLength(NSSCMSCipherContext *cc, unsigned int input_len, PRBool final)
  271. {
  272.     int blocks, block_size;
  273.     PORT_Assert (! cc->encrypt);
  274.     block_size = cc->block_size;
  275.     /*
  276.      * If this is not a block cipher, then we always have the same
  277.      * number of output bytes as we had input bytes.
  278.      */
  279.     if (block_size == 0)
  280. return input_len;
  281.     /*
  282.      * On the final call, we will always use up all of the pending
  283.      * bytes plus all of the input bytes, *but*, there will be padding
  284.      * at the end and we cannot predict how many bytes of padding we
  285.      * will end up removing.  The amount given here is actually known
  286.      * to be at least 1 byte too long (because we know we will have
  287.      * at least 1 byte of padding), but seemed clearer/better to me.
  288.      */
  289.     if (final)
  290. return cc->pending_count + input_len;
  291.     /*
  292.      * Okay, this amount is exactly what we will output on the
  293.      * next cipher operation.  We will always hang onto the last
  294.      * 1 - block_size bytes for non-final operations.  That is,
  295.      * we will do as many complete blocks as we can *except* the
  296.      * last block (complete or partial).  (This is because until
  297.      * we know we are at the end, we cannot know when to interpret
  298.      * and removing the padding byte(s), which are guaranteed to
  299.      * be there.)
  300.      */
  301.     blocks = (cc->pending_count + input_len - 1) / block_size;
  302.     return blocks * block_size;
  303. }
  304. /*
  305.  * NSS_CMSCipherContext_EncryptLength - find the output length of the next call to encrypt.
  306.  *
  307.  * cc - the cipher context
  308.  * input_len - number of bytes used as input
  309.  * final - true if this is the final chunk of data
  310.  *
  311.  * Result can be used to perform memory allocations.
  312.  *
  313.  * Note that this can return zero, which does not mean that the encrypt
  314.  * operation can be skipped!  (It simply means that there are not enough
  315.  * bytes to make up an entire block; the bytes will be reserved until
  316.  * there are enough to encrypt/decrypt at least one block.)  However,
  317.  * if zero is returned it *does* mean that no output buffer need be
  318.  * passed in to the subsequent encrypt operation, as no output bytes
  319.  * will be stored.
  320.  */
  321. unsigned int
  322. NSS_CMSCipherContext_EncryptLength(NSSCMSCipherContext *cc, unsigned int input_len, PRBool final)
  323. {
  324.     int blocks, block_size;
  325.     int pad_size;
  326.     PORT_Assert (cc->encrypt);
  327.     block_size = cc->block_size;
  328.     pad_size = cc->pad_size;
  329.     /*
  330.      * If this is not a block cipher, then we always have the same
  331.      * number of output bytes as we had input bytes.
  332.      */
  333.     if (block_size == 0)
  334. return input_len;
  335.     /*
  336.      * On the final call, we only send out what we need for
  337.      * remaining bytes plus the padding.  (There is always padding,
  338.      * so even if we have an exact number of blocks as input, we
  339.      * will add another full block that is just padding.)
  340.      */
  341.     if (final) {
  342. if (pad_size == 0) {
  343.          return cc->pending_count + input_len;
  344. } else {
  345.          blocks = (cc->pending_count + input_len) / pad_size;
  346.     blocks++;
  347.     return blocks*pad_size;
  348. }
  349.     }
  350.     /*
  351.      * Now, count the number of complete blocks of data we have.
  352.      */
  353.     blocks = (cc->pending_count + input_len) / block_size;
  354.     return blocks * block_size;
  355. }
  356. /*
  357.  * NSS_CMSCipherContext_Decrypt - do the decryption
  358.  *
  359.  * cc - the cipher context
  360.  * output - buffer for decrypted result bytes
  361.  * output_len_p - number of bytes in output
  362.  * max_output_len - upper bound on bytes to put into output
  363.  * input - pointer to input bytes
  364.  * input_len - number of input bytes
  365.  * final - true if this is the final chunk of data
  366.  *
  367.  * Decrypts a given length of input buffer (starting at "input" and
  368.  * containing "input_len" bytes), placing the decrypted bytes in
  369.  * "output" and storing the output length in "*output_len_p".
  370.  * "cc" is the return value from NSS_CMSCipher_StartDecrypt.
  371.  * When "final" is true, this is the last of the data to be decrypted.
  372.  *
  373.  * This is much more complicated than it sounds when the cipher is
  374.  * a block-type, meaning that the decryption function will only
  375.  * operate on whole blocks.  But our caller is operating stream-wise,
  376.  * and can pass in any number of bytes.  So we need to keep track
  377.  * of block boundaries.  We save excess bytes between calls in "cc".
  378.  * We also need to determine which bytes are padding, and remove
  379.  * them from the output.  We can only do this step when we know we
  380.  * have the final block of data.  PKCS #7 specifies that the padding
  381.  * used for a block cipher is a string of bytes, each of whose value is
  382.  * the same as the length of the padding, and that all data is padded.
  383.  * (Even data that starts out with an exact multiple of blocks gets
  384.  * added to it another block, all of which is padding.)
  385.  */ 
  386. SECStatus
  387. NSS_CMSCipherContext_Decrypt(NSSCMSCipherContext *cc, unsigned char *output,
  388.   unsigned int *output_len_p, unsigned int max_output_len,
  389.   const unsigned char *input, unsigned int input_len,
  390.   PRBool final)
  391. {
  392.     int blocks, bsize, pcount, padsize;
  393.     unsigned int max_needed, ifraglen, ofraglen, output_len;
  394.     unsigned char *pbuf;
  395.     SECStatus rv;
  396.     PORT_Assert (! cc->encrypt);
  397.     /*
  398.      * Check that we have enough room for the output.  Our caller should
  399.      * already handle this; failure is really an internal error (i.e. bug).
  400.      */
  401.     max_needed = NSS_CMSCipherContext_DecryptLength(cc, input_len, final);
  402.     PORT_Assert (max_output_len >= max_needed);
  403.     if (max_output_len < max_needed) {
  404. /* PORT_SetError (XXX); */
  405. return SECFailure;
  406.     }
  407.     /*
  408.      * hardware encryption does not like small decryption sizes here, so we
  409.      * allow both blocking and padding.
  410.      */
  411.     bsize = cc->block_size;
  412.     padsize = cc->pad_size;
  413.     /*
  414.      * When no blocking or padding work to do, we can simply call the
  415.      * cipher function and we are done.
  416.      */
  417.     if (bsize == 0) {
  418. return (* cc->doit) (cc->cx, output, output_len_p, max_output_len,
  419.       input, input_len);
  420.     }
  421.     pcount = cc->pending_count;
  422.     pbuf = cc->pending_buf;
  423.     output_len = 0;
  424.     if (pcount) {
  425. /*
  426.  * Try to fill in an entire block, starting with the bytes
  427.  * we already have saved away.
  428.  */
  429. while (input_len && pcount < bsize) {
  430.     pbuf[pcount++] = *input++;
  431.     input_len--;
  432. }
  433. /*
  434.  * If we have at most a whole block and this is not our last call,
  435.  * then we are done for now.  (We do not try to decrypt a lone
  436.  * single block because we cannot interpret the padding bytes
  437.  * until we know we are handling the very last block of all input.)
  438.  */
  439. if (input_len == 0 && !final) {
  440.     cc->pending_count = pcount;
  441.     if (output_len_p)
  442. *output_len_p = 0;
  443.     return SECSuccess;
  444. }
  445. /*
  446.  * Given the logic above, we expect to have a full block by now.
  447.  * If we do not, there is something wrong, either with our own
  448.  * logic or with (length of) the data given to us.
  449.  */
  450. PORT_Assert ((padsize == 0) || (pcount % padsize) == 0);
  451. if ((padsize != 0) && (pcount % padsize) != 0) {
  452.     PORT_Assert (final);
  453.     PORT_SetError (SEC_ERROR_BAD_DATA);
  454.     return SECFailure;
  455. }
  456. /*
  457.  * Decrypt the block.
  458.  */
  459. rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
  460.     pbuf, pcount);
  461. if (rv != SECSuccess)
  462.     return rv;
  463. /*
  464.  * For now anyway, all of our ciphers have the same number of
  465.  * bytes of output as they do input.  If this ever becomes untrue,
  466.  * then NSS_CMSCipherContext_DecryptLength needs to be made smarter!
  467.  */
  468. PORT_Assert(ofraglen == pcount);
  469. /*
  470.  * Account for the bytes now in output.
  471.  */
  472. max_output_len -= ofraglen;
  473. output_len += ofraglen;
  474. output += ofraglen;
  475.     }
  476.     /*
  477.      * If this is our last call, we expect to have an exact number of
  478.      * blocks left to be decrypted; we will decrypt them all.
  479.      * 
  480.      * If not our last call, we always save between 1 and bsize bytes
  481.      * until next time.  (We must do this because we cannot be sure
  482.      * that none of the decrypted bytes are padding bytes until we
  483.      * have at least another whole block of data.  You cannot tell by
  484.      * looking -- the data could be anything -- you can only tell by
  485.      * context, knowing you are looking at the last block.)  We could
  486.      * decrypt a whole block now but it is easier if we just treat it
  487.      * the same way we treat partial block bytes.
  488.      */
  489.     if (final) {
  490. if (padsize) {
  491.     blocks = input_len / padsize;
  492.     ifraglen = blocks * padsize;
  493. } else ifraglen = input_len;
  494. PORT_Assert (ifraglen == input_len);
  495. if (ifraglen != input_len) {
  496.     PORT_SetError(SEC_ERROR_BAD_DATA);
  497.     return SECFailure;
  498. }
  499.     } else {
  500. blocks = (input_len - 1) / bsize;
  501. ifraglen = blocks * bsize;
  502. PORT_Assert (ifraglen < input_len);
  503. pcount = input_len - ifraglen;
  504. PORT_Memcpy (pbuf, input + ifraglen, pcount);
  505. cc->pending_count = pcount;
  506.     }
  507.     if (ifraglen) {
  508. rv = (* cc->doit)(cc->cx, output, &ofraglen, max_output_len,
  509.     input, ifraglen);
  510. if (rv != SECSuccess)
  511.     return rv;
  512. /*
  513.  * For now anyway, all of our ciphers have the same number of
  514.  * bytes of output as they do input.  If this ever becomes untrue,
  515.  * then sec_PKCS7DecryptLength needs to be made smarter!
  516.  */
  517. PORT_Assert (ifraglen == ofraglen);
  518. if (ifraglen != ofraglen) {
  519.     PORT_SetError(SEC_ERROR_BAD_DATA);
  520.     return SECFailure;
  521. }
  522. output_len += ofraglen;
  523.     } else {
  524. ofraglen = 0;
  525.     }
  526.     /*
  527.      * If we just did our very last block, "remove" the padding by
  528.      * adjusting the output length.
  529.      */
  530.     if (final && (padsize != 0)) {
  531. unsigned int padlen = *(output + ofraglen - 1);
  532. PORT_Assert (padlen > 0 && padlen <= padsize);
  533. if (padlen == 0 || padlen > padsize) {
  534.     PORT_SetError(SEC_ERROR_BAD_DATA);
  535.     return SECFailure;
  536. }
  537. output_len -= padlen;
  538.     }
  539.     PORT_Assert (output_len_p != NULL || output_len == 0);
  540.     if (output_len_p != NULL)
  541. *output_len_p = output_len;
  542.     return SECSuccess;
  543. }
  544. /*
  545.  * NSS_CMSCipherContext_Encrypt - do the encryption
  546.  *
  547.  * cc - the cipher context
  548.  * output - buffer for decrypted result bytes
  549.  * output_len_p - number of bytes in output
  550.  * max_output_len - upper bound on bytes to put into output
  551.  * input - pointer to input bytes
  552.  * input_len - number of input bytes
  553.  * final - true if this is the final chunk of data
  554.  *
  555.  * Encrypts a given length of input buffer (starting at "input" and
  556.  * containing "input_len" bytes), placing the encrypted bytes in
  557.  * "output" and storing the output length in "*output_len_p".
  558.  * "cc" is the return value from NSS_CMSCipher_StartEncrypt.
  559.  * When "final" is true, this is the last of the data to be encrypted.
  560.  *
  561.  * This is much more complicated than it sounds when the cipher is
  562.  * a block-type, meaning that the encryption function will only
  563.  * operate on whole blocks.  But our caller is operating stream-wise,
  564.  * and can pass in any number of bytes.  So we need to keep track
  565.  * of block boundaries.  We save excess bytes between calls in "cc".
  566.  * We also need to add padding bytes at the end.  PKCS #7 specifies
  567.  * that the padding used for a block cipher is a string of bytes,
  568.  * each of whose value is the same as the length of the padding,
  569.  * and that all data is padded.  (Even data that starts out with
  570.  * an exact multiple of blocks gets added to it another block,
  571.  * all of which is padding.)
  572.  *
  573.  * XXX I would kind of like to combine this with the function above
  574.  * which does decryption, since they have a lot in common.  But the
  575.  * tricky parts about padding and filling blocks would be much
  576.  * harder to read that way, so I left them separate.  At least for
  577.  * now until it is clear that they are right.
  578.  */ 
  579. SECStatus
  580. NSS_CMSCipherContext_Encrypt(NSSCMSCipherContext *cc, unsigned char *output,
  581.   unsigned int *output_len_p, unsigned int max_output_len,
  582.   const unsigned char *input, unsigned int input_len,
  583.   PRBool final)
  584. {
  585.     int blocks, bsize, padlen, pcount, padsize;
  586.     unsigned int max_needed, ifraglen, ofraglen, output_len;
  587.     unsigned char *pbuf;
  588.     SECStatus rv;
  589.     PORT_Assert (cc->encrypt);
  590.     /*
  591.      * Check that we have enough room for the output.  Our caller should
  592.      * already handle this; failure is really an internal error (i.e. bug).
  593.      */
  594.     max_needed = NSS_CMSCipherContext_EncryptLength (cc, input_len, final);
  595.     PORT_Assert (max_output_len >= max_needed);
  596.     if (max_output_len < max_needed) {
  597. /* PORT_SetError (XXX); */
  598. return SECFailure;
  599.     }
  600.     bsize = cc->block_size;
  601.     padsize = cc->pad_size;
  602.     /*
  603.      * When no blocking and padding work to do, we can simply call the
  604.      * cipher function and we are done.
  605.      */
  606.     if (bsize == 0) {
  607. return (*cc->doit)(cc->cx, output, output_len_p, max_output_len,
  608.       input, input_len);
  609.     }
  610.     pcount = cc->pending_count;
  611.     pbuf = cc->pending_buf;
  612.     output_len = 0;
  613.     if (pcount) {
  614. /*
  615.  * Try to fill in an entire block, starting with the bytes
  616.  * we already have saved away.
  617.  */
  618. while (input_len && pcount < bsize) {
  619.     pbuf[pcount++] = *input++;
  620.     input_len--;
  621. }
  622. /*
  623.  * If we do not have a full block and we know we will be
  624.  * called again, then we are done for now.
  625.  */
  626. if (pcount < bsize && !final) {
  627.     cc->pending_count = pcount;
  628.     if (output_len_p != NULL)
  629. *output_len_p = 0;
  630.     return SECSuccess;
  631. }
  632. /*
  633.  * If we have a whole block available, encrypt it.
  634.  */
  635. if ((padsize == 0) || (pcount % padsize) == 0) {
  636.     rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
  637. pbuf, pcount);
  638.     if (rv != SECSuccess)
  639. return rv;
  640.     /*
  641.      * For now anyway, all of our ciphers have the same number of
  642.      * bytes of output as they do input.  If this ever becomes untrue,
  643.      * then sec_PKCS7EncryptLength needs to be made smarter!
  644.      */
  645.     PORT_Assert (ofraglen == pcount);
  646.     /*
  647.      * Account for the bytes now in output.
  648.      */
  649.     max_output_len -= ofraglen;
  650.     output_len += ofraglen;
  651.     output += ofraglen;
  652.     pcount = 0;
  653. }
  654.     }
  655.     if (input_len) {
  656. PORT_Assert (pcount == 0);
  657. blocks = input_len / bsize;
  658. ifraglen = blocks * bsize;
  659. if (ifraglen) {
  660.     rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
  661. input, ifraglen);
  662.     if (rv != SECSuccess)
  663. return rv;
  664.     /*
  665.      * For now anyway, all of our ciphers have the same number of
  666.      * bytes of output as they do input.  If this ever becomes untrue,
  667.      * then sec_PKCS7EncryptLength needs to be made smarter!
  668.      */
  669.     PORT_Assert (ifraglen == ofraglen);
  670.     max_output_len -= ofraglen;
  671.     output_len += ofraglen;
  672.     output += ofraglen;
  673. }
  674. pcount = input_len - ifraglen;
  675. PORT_Assert (pcount < bsize);
  676. if (pcount)
  677.     PORT_Memcpy (pbuf, input + ifraglen, pcount);
  678.     }
  679.     if (final) {
  680. padlen = padsize - (pcount % padsize);
  681. PORT_Memset (pbuf + pcount, padlen, padlen);
  682. rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
  683.     pbuf, pcount+padlen);
  684. if (rv != SECSuccess)
  685.     return rv;
  686. /*
  687.  * For now anyway, all of our ciphers have the same number of
  688.  * bytes of output as they do input.  If this ever becomes untrue,
  689.  * then sec_PKCS7EncryptLength needs to be made smarter!
  690.  */
  691. PORT_Assert (ofraglen == (pcount+padlen));
  692. output_len += ofraglen;
  693.     } else {
  694. cc->pending_count = pcount;
  695.     }
  696.     PORT_Assert (output_len_p != NULL || output_len == 0);
  697.     if (output_len_p != NULL)
  698. *output_len_p = output_len;
  699.     return SECSuccess;
  700. }