security/nss/lib/smime/cmscipher.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial