tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cmscipher.c (24444B)


      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/. */
      4 
      5 /*
      6 * Encryption/decryption routines for CMS implementation, none of which are exported.
      7 */
      8 
      9 #include "cmslocal.h"
     10 
     11 #include "secoid.h"
     12 #include "secitem.h"
     13 #include "pk11func.h"
     14 #include "secerr.h"
     15 #include "secpkcs5.h"
     16 
     17 /*
     18 * -------------------------------------------------------------------
     19 * Cipher stuff.
     20 */
     21 
     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);
     25 
     26 #define BLOCK_SIZE 4096
     27 
     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 };
     38 
     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;
     57 
     58    algtag = SECOID_GetAlgorithmTag(algid);
     59 
     60    /* set param and mechanism */
     61    if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
     62        SECItem *pwitem;
     63 
     64        pwitem = PK11_GetSymKeyUserData(key);
     65        if (!pwitem)
     66            return NULL;
     67 
     68        cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
     69        if (cryptoMechType == CKM_INVALID_MECHANISM) {
     70            SECITEM_FreeItem(param, PR_TRUE);
     71            return NULL;
     72        }
     73 
     74    } else {
     75        cryptoMechType = PK11_AlgtagToMechanism(algtag);
     76        if ((param = PK11_ParamFromAlgid(algid)) == NULL)
     77            return NULL;
     78    }
     79 
     80    cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext));
     81    if (cc == NULL) {
     82        SECITEM_FreeItem(param, PR_TRUE);
     83        return NULL;
     84    }
     85 
     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);
     91 
     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    }
    100 
    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;
    106 
    107    return cc;
    108 }
    109 
    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 = NULL;
    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);
    130 
    131    /* set param and mechanism */
    132    if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
    133        SECItem *pwitem;
    134 
    135        pwitem = PK11_GetSymKeyUserData(key);
    136        if (!pwitem)
    137            return NULL;
    138 
    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    }
    150 
    151    cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext));
    152    if (cc == NULL) {
    153        goto loser;
    154    }
    155 
    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);
    161 
    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    }
    170 
    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    }
    187 
    188    cc->cx = ciphercx;
    189    ciphercx = NULL;
    190    cc->doit = (nss_cms_cipher_function)PK11_CipherOp;
    191    cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext;
    192    cc->encrypt = PR_TRUE;
    193    cc->pending_count = 0;
    194 
    195 loser:
    196    SECITEM_FreeItem(param, PR_TRUE);
    197    if (ciphercx) {
    198        PK11_DestroyContext(ciphercx, PR_TRUE);
    199    }
    200 
    201    return cc;
    202 }
    203 
    204 void
    205 NSS_CMSCipherContext_Destroy(NSSCMSCipherContext *cc)
    206 {
    207    PORT_Assert(cc != NULL);
    208    if (cc == NULL)
    209        return;
    210    (*cc->destroy)(cc->cx, PR_TRUE);
    211    PORT_Free(cc);
    212 }
    213 
    214 /*
    215 * NSS_CMSCipherContext_DecryptLength - find the output length of the next call to decrypt.
    216 *
    217 * cc - the cipher context
    218 * input_len - number of bytes used as input
    219 * final - true if this is the final chunk of data
    220 *
    221 * Result can be used to perform memory allocations.  Note that the amount
    222 * is exactly accurate only when not doing a block cipher or when final
    223 * is false, otherwise it is an upper bound on the amount because until
    224 * we see the data we do not know how many padding bytes there are
    225 * (always between 1 and bsize).
    226 *
    227 * Note that this can return zero, which does not mean that the decrypt
    228 * operation can be skipped!  (It simply means that there are not enough
    229 * bytes to make up an entire block; the bytes will be reserved until
    230 * there are enough to encrypt/decrypt at least one block.)  However,
    231 * if zero is returned it *does* mean that no output buffer need be
    232 * passed in to the subsequent decrypt operation, as no output bytes
    233 * will be stored.
    234 */
    235 unsigned int
    236 NSS_CMSCipherContext_DecryptLength(NSSCMSCipherContext *cc, unsigned int input_len, PRBool final)
    237 {
    238    int blocks, block_size;
    239 
    240    PORT_Assert(!cc->encrypt);
    241 
    242    block_size = cc->block_size;
    243 
    244    /*
    245     * If this is not a block cipher, then we always have the same
    246     * number of output bytes as we had input bytes.
    247     */
    248    if (block_size == 0)
    249        return input_len;
    250 
    251    /*
    252     * On the final call, we will always use up all of the pending
    253     * bytes plus all of the input bytes, *but*, there will be padding
    254     * at the end and we cannot predict how many bytes of padding we
    255     * will end up removing.  The amount given here is actually known
    256     * to be at least 1 byte too long (because we know we will have
    257     * at least 1 byte of padding), but seemed clearer/better to me.
    258     */
    259    if (final)
    260        return cc->pending_count + input_len;
    261 
    262    /*
    263     * Okay, this amount is exactly what we will output on the
    264     * next cipher operation.  We will always hang onto the last
    265     * 1 - block_size bytes for non-final operations.  That is,
    266     * we will do as many complete blocks as we can *except* the
    267     * last block (complete or partial).  (This is because until
    268     * we know we are at the end, we cannot know when to interpret
    269     * and removing the padding byte(s), which are guaranteed to
    270     * be there.)
    271     */
    272    blocks = (cc->pending_count + input_len - 1) / block_size;
    273    return blocks * block_size;
    274 }
    275 
    276 /*
    277 * NSS_CMSCipherContext_EncryptLength - find the output length of the next call to encrypt.
    278 *
    279 * cc - the cipher context
    280 * input_len - number of bytes used as input
    281 * final - true if this is the final chunk of data
    282 *
    283 * Result can be used to perform memory allocations.
    284 *
    285 * Note that this can return zero, which does not mean that the encrypt
    286 * operation can be skipped!  (It simply means that there are not enough
    287 * bytes to make up an entire block; the bytes will be reserved until
    288 * there are enough to encrypt/decrypt at least one block.)  However,
    289 * if zero is returned it *does* mean that no output buffer need be
    290 * passed in to the subsequent encrypt operation, as no output bytes
    291 * will be stored.
    292 */
    293 unsigned int
    294 NSS_CMSCipherContext_EncryptLength(NSSCMSCipherContext *cc, unsigned int input_len, PRBool final)
    295 {
    296    int blocks, block_size;
    297    int pad_size;
    298 
    299    PORT_Assert(cc->encrypt);
    300 
    301    block_size = cc->block_size;
    302    pad_size = cc->pad_size;
    303 
    304    /*
    305     * If this is not a block cipher, then we always have the same
    306     * number of output bytes as we had input bytes.
    307     */
    308    if (block_size == 0)
    309        return input_len;
    310 
    311    /*
    312     * On the final call, we only send out what we need for
    313     * remaining bytes plus the padding.  (There is always padding,
    314     * so even if we have an exact number of blocks as input, we
    315     * will add another full block that is just padding.)
    316     */
    317    if (final) {
    318        if (pad_size == 0) {
    319            return cc->pending_count + input_len;
    320        } else {
    321            blocks = (cc->pending_count + input_len) / pad_size;
    322            blocks++;
    323            return blocks * pad_size;
    324        }
    325    }
    326 
    327    /*
    328     * Now, count the number of complete blocks of data we have.
    329     */
    330    blocks = (cc->pending_count + input_len) / block_size;
    331 
    332    return blocks * block_size;
    333 }
    334 
    335 /*
    336 * NSS_CMSCipherContext_Decrypt - do the decryption
    337 *
    338 * cc - the cipher context
    339 * output - buffer for decrypted result bytes
    340 * output_len_p - number of bytes in output
    341 * max_output_len - upper bound on bytes to put into output
    342 * input - pointer to input bytes
    343 * input_len - number of input bytes
    344 * final - true if this is the final chunk of data
    345 *
    346 * Decrypts a given length of input buffer (starting at "input" and
    347 * containing "input_len" bytes), placing the decrypted bytes in
    348 * "output" and storing the output length in "*output_len_p".
    349 * "cc" is the return value from NSS_CMSCipher_StartDecrypt.
    350 * When "final" is true, this is the last of the data to be decrypted.
    351 *
    352 * This is much more complicated than it sounds when the cipher is
    353 * a block-type, meaning that the decryption function will only
    354 * operate on whole blocks.  But our caller is operating stream-wise,
    355 * and can pass in any number of bytes.  So we need to keep track
    356 * of block boundaries.  We save excess bytes between calls in "cc".
    357 * We also need to determine which bytes are padding, and remove
    358 * them from the output.  We can only do this step when we know we
    359 * have the final block of data.  PKCS #7 specifies that the padding
    360 * used for a block cipher is a string of bytes, each of whose value is
    361 * the same as the length of the padding, and that all data is padded.
    362 * (Even data that starts out with an exact multiple of blocks gets
    363 * added to it another block, all of which is padding.)
    364 */
    365 SECStatus
    366 NSS_CMSCipherContext_Decrypt(NSSCMSCipherContext *cc, unsigned char *output,
    367                             unsigned int *output_len_p, unsigned int max_output_len,
    368                             const unsigned char *input, unsigned int input_len,
    369                             PRBool final)
    370 {
    371    unsigned int blocks, bsize, pcount, padsize;
    372    unsigned int max_needed, ifraglen, ofraglen, output_len;
    373    unsigned char *pbuf;
    374    SECStatus rv;
    375 
    376    PORT_Assert(!cc->encrypt);
    377 
    378    /*
    379     * Check that we have enough room for the output.  Our caller should
    380     * already handle this; failure is really an internal error (i.e. bug).
    381     */
    382    max_needed = NSS_CMSCipherContext_DecryptLength(cc, input_len, final);
    383    PORT_Assert(max_output_len >= max_needed);
    384    if (max_output_len < max_needed) {
    385        /* PORT_SetError (XXX); */
    386        return SECFailure;
    387    }
    388 
    389    /*
    390     * hardware encryption does not like small decryption sizes here, so we
    391     * allow both blocking and padding.
    392     */
    393    bsize = cc->block_size;
    394    padsize = cc->pad_size;
    395 
    396    /*
    397     * When no blocking or padding work to do, we can simply call the
    398     * cipher function and we are done.
    399     */
    400    if (bsize == 0) {
    401        return (*cc->doit)(cc->cx, output, output_len_p, max_output_len,
    402                           input, input_len);
    403    }
    404 
    405    pcount = cc->pending_count;
    406    pbuf = cc->pending_buf;
    407 
    408    output_len = 0;
    409 
    410    if (pcount) {
    411        /*
    412         * Try to fill in an entire block, starting with the bytes
    413         * we already have saved away.
    414         */
    415        while (input_len && pcount < bsize) {
    416            pbuf[pcount++] = *input++;
    417            input_len--;
    418        }
    419        /*
    420         * If we have at most a whole block and this is not our last call,
    421         * then we are done for now.  (We do not try to decrypt a lone
    422         * single block because we cannot interpret the padding bytes
    423         * until we know we are handling the very last block of all input.)
    424         */
    425        if (input_len == 0 && !final) {
    426            cc->pending_count = pcount;
    427            if (output_len_p)
    428                *output_len_p = 0;
    429            return SECSuccess;
    430        }
    431        /*
    432         * Given the logic above, we expect to have a full block by now.
    433         * If we do not, there is something wrong, either with our own
    434         * logic or with (length of) the data given to us.
    435         */
    436        if ((padsize != 0) && (pcount % padsize) != 0) {
    437            PORT_Assert(final);
    438            PORT_SetError(SEC_ERROR_BAD_DATA);
    439            return SECFailure;
    440        }
    441        /*
    442         * Decrypt the block.
    443         */
    444        rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
    445                         pbuf, pcount);
    446        if (rv != SECSuccess)
    447            return rv;
    448 
    449        /*
    450         * For now anyway, all of our ciphers have the same number of
    451         * bytes of output as they do input.  If this ever becomes untrue,
    452         * then NSS_CMSCipherContext_DecryptLength needs to be made smarter!
    453         */
    454        PORT_Assert(ofraglen == pcount);
    455 
    456        /*
    457         * Account for the bytes now in output.
    458         */
    459        max_output_len -= ofraglen;
    460        output_len += ofraglen;
    461        output += ofraglen;
    462    }
    463 
    464    /*
    465     * If this is our last call, we expect to have an exact number of
    466     * blocks left to be decrypted; we will decrypt them all.
    467     *
    468     * If not our last call, we always save between 1 and bsize bytes
    469     * until next time.  (We must do this because we cannot be sure
    470     * that none of the decrypted bytes are padding bytes until we
    471     * have at least another whole block of data.  You cannot tell by
    472     * looking -- the data could be anything -- you can only tell by
    473     * context, knowing you are looking at the last block.)  We could
    474     * decrypt a whole block now but it is easier if we just treat it
    475     * the same way we treat partial block bytes.
    476     */
    477    if (final) {
    478        if (padsize) {
    479            blocks = input_len / padsize;
    480            ifraglen = blocks * padsize;
    481        } else
    482            ifraglen = input_len;
    483        PORT_Assert(ifraglen == input_len);
    484 
    485        if (ifraglen != input_len) {
    486            PORT_SetError(SEC_ERROR_BAD_DATA);
    487            return SECFailure;
    488        }
    489    } else {
    490        blocks = (input_len - 1) / bsize;
    491        ifraglen = blocks * bsize;
    492        PORT_Assert(ifraglen < input_len);
    493 
    494        pcount = input_len - ifraglen;
    495        PORT_Memcpy(pbuf, input + ifraglen, pcount);
    496        cc->pending_count = pcount;
    497    }
    498 
    499    if (ifraglen) {
    500        rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
    501                         input, ifraglen);
    502        if (rv != SECSuccess)
    503            return rv;
    504 
    505        /*
    506         * For now anyway, all of our ciphers have the same number of
    507         * bytes of output as they do input.  If this ever becomes untrue,
    508         * then sec_PKCS7DecryptLength needs to be made smarter!
    509         */
    510        PORT_Assert(ifraglen == ofraglen);
    511        if (ifraglen != ofraglen) {
    512            PORT_SetError(SEC_ERROR_BAD_DATA);
    513            return SECFailure;
    514        }
    515 
    516        output_len += ofraglen;
    517    } else {
    518        ofraglen = 0;
    519    }
    520 
    521    /*
    522     * If we just did our very last block, "remove" the padding by
    523     * adjusting the output length.
    524     */
    525    if (final && (padsize != 0)) {
    526        unsigned int padlen = *(output + ofraglen - 1);
    527 
    528        if (padlen == 0 || padlen > padsize) {
    529            PORT_SetError(SEC_ERROR_BAD_DATA);
    530            return SECFailure;
    531        }
    532        output_len -= padlen;
    533    }
    534 
    535    PORT_Assert(output_len_p != NULL || output_len == 0);
    536    if (output_len_p != NULL)
    537        *output_len_p = output_len;
    538 
    539    return SECSuccess;
    540 }
    541 
    542 /*
    543 * NSS_CMSCipherContext_Encrypt - do the encryption
    544 *
    545 * cc - the cipher context
    546 * output - buffer for decrypted result bytes
    547 * output_len_p - number of bytes in output
    548 * max_output_len - upper bound on bytes to put into output
    549 * input - pointer to input bytes
    550 * input_len - number of input bytes
    551 * final - true if this is the final chunk of data
    552 *
    553 * Encrypts a given length of input buffer (starting at "input" and
    554 * containing "input_len" bytes), placing the encrypted bytes in
    555 * "output" and storing the output length in "*output_len_p".
    556 * "cc" is the return value from NSS_CMSCipher_StartEncrypt.
    557 * When "final" is true, this is the last of the data to be encrypted.
    558 *
    559 * This is much more complicated than it sounds when the cipher is
    560 * a block-type, meaning that the encryption function will only
    561 * operate on whole blocks.  But our caller is operating stream-wise,
    562 * and can pass in any number of bytes.  So we need to keep track
    563 * of block boundaries.  We save excess bytes between calls in "cc".
    564 * We also need to add padding bytes at the end.  PKCS #7 specifies
    565 * that the padding used for a block cipher is a string of bytes,
    566 * each of whose value is the same as the length of the padding,
    567 * and that all data is padded.  (Even data that starts out with
    568 * an exact multiple of blocks gets added to it another block,
    569 * all of which is padding.)
    570 *
    571 * XXX I would kind of like to combine this with the function above
    572 * which does decryption, since they have a lot in common.  But the
    573 * tricky parts about padding and filling blocks would be much
    574 * harder to read that way, so I left them separate.  At least for
    575 * now until it is clear that they are right.
    576 */
    577 SECStatus
    578 NSS_CMSCipherContext_Encrypt(NSSCMSCipherContext *cc, unsigned char *output,
    579                             unsigned int *output_len_p, unsigned int max_output_len,
    580                             const unsigned char *input, unsigned int input_len,
    581                             PRBool final)
    582 {
    583    int blocks, bsize, padlen, pcount, padsize;
    584    unsigned int max_needed, ifraglen, ofraglen, output_len;
    585    unsigned char *pbuf;
    586    SECStatus rv;
    587 
    588    PORT_Assert(cc->encrypt);
    589 
    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 
    601    bsize = cc->block_size;
    602    padsize = cc->pad_size;
    603 
    604    /*
    605     * When no blocking and padding work to do, we can simply call the
    606     * cipher function and we are done.
    607     */
    608    if (bsize == 0) {
    609        return (*cc->doit)(cc->cx, output, output_len_p, max_output_len,
    610                           input, input_len);
    611    }
    612 
    613    pcount = cc->pending_count;
    614    pbuf = cc->pending_buf;
    615 
    616    output_len = 0;
    617 
    618    if (pcount) {
    619        /*
    620         * Try to fill in an entire block, starting with the bytes
    621         * we already have saved away.
    622         */
    623        while (input_len && pcount < bsize) {
    624            pbuf[pcount++] = *input++;
    625            input_len--;
    626        }
    627        /*
    628         * If we do not have a full block and we know we will be
    629         * called again, then we are done for now.
    630         */
    631        if (pcount < bsize && !final) {
    632            cc->pending_count = pcount;
    633            if (output_len_p != NULL)
    634                *output_len_p = 0;
    635            return SECSuccess;
    636        }
    637        /*
    638         * If we have a whole block available, encrypt it.
    639         */
    640        if ((padsize == 0) || (pcount % padsize) == 0) {
    641            rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
    642                             pbuf, pcount);
    643            if (rv != SECSuccess)
    644                return rv;
    645 
    646            /*
    647             * For now anyway, all of our ciphers have the same number of
    648             * bytes of output as they do input.  If this ever becomes untrue,
    649             * then sec_PKCS7EncryptLength needs to be made smarter!
    650             */
    651            PORT_Assert(ofraglen == pcount);
    652 
    653            /*
    654             * Account for the bytes now in output.
    655             */
    656            max_output_len -= ofraglen;
    657            output_len += ofraglen;
    658            output += ofraglen;
    659 
    660            pcount = 0;
    661        }
    662    }
    663 
    664    if (input_len) {
    665        PORT_Assert(pcount == 0);
    666 
    667        blocks = input_len / bsize;
    668        ifraglen = blocks * bsize;
    669 
    670        if (ifraglen) {
    671            rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
    672                             input, ifraglen);
    673            if (rv != SECSuccess)
    674                return rv;
    675 
    676            /*
    677             * For now anyway, all of our ciphers have the same number of
    678             * bytes of output as they do input.  If this ever becomes untrue,
    679             * then sec_PKCS7EncryptLength needs to be made smarter!
    680             */
    681            PORT_Assert(ifraglen == ofraglen);
    682 
    683            max_output_len -= ofraglen;
    684            output_len += ofraglen;
    685            output += ofraglen;
    686        }
    687 
    688        pcount = input_len - ifraglen;
    689        PORT_Assert(pcount < bsize);
    690        if (pcount)
    691            PORT_Memcpy(pbuf, input + ifraglen, pcount);
    692    }
    693 
    694    if (final) {
    695        if (padsize <= 0) {
    696            padlen = 0;
    697        } else {
    698            padlen = padsize - (pcount % padsize);
    699            PORT_Memset(pbuf + pcount, padlen, padlen);
    700        }
    701        rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
    702                         pbuf, pcount + padlen);
    703        if (rv != SECSuccess)
    704            return rv;
    705 
    706        /*
    707         * For now anyway, all of our ciphers have the same number of
    708         * bytes of output as they do input.  If this ever becomes untrue,
    709         * then sec_PKCS7EncryptLength needs to be made smarter!
    710         */
    711        PORT_Assert(ofraglen == (pcount + padlen));
    712        output_len += ofraglen;
    713    } else {
    714        cc->pending_count = pcount;
    715    }
    716 
    717    PORT_Assert(output_len_p != NULL || output_len == 0);
    718    if (output_len_p != NULL)
    719        *output_len_p = output_len;
    720 
    721    return SECSuccess;
    722 }