tor-browser

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

aeskeywrap.c (20135B)


      1 /*
      2 * aeskeywrap.c - implement AES Key Wrap algorithm from RFC 3394
      3 *
      4 * This Source Code Form is subject to the terms of the Mozilla Public
      5 * License, v. 2.0. If a copy of the MPL was not distributed with this
      6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      7 
      8 #ifdef FREEBL_NO_DEPEND
      9 #include "stubs.h"
     10 #endif
     11 
     12 #include <stddef.h>
     13 
     14 #include "prcpucfg.h"
     15 #if defined(IS_LITTLE_ENDIAN) || defined(SHA_NO_LONG_LONG)
     16 #define BIG_ENDIAN_WITH_64_BIT_REGISTERS 0
     17 #else
     18 #define BIG_ENDIAN_WITH_64_BIT_REGISTERS 1
     19 #endif
     20 #include "prtypes.h" /* for PRUintXX */
     21 #include "secport.h" /* for PORT_XXX */
     22 #include "secerr.h"
     23 #include "blapi.h" /* for AES_ functions */
     24 #include "rijndael.h"
     25 
     26 struct AESKeyWrapContextStr {
     27    AESContext aescx;
     28    unsigned char iv[AES_KEY_WRAP_IV_BYTES];
     29    void *mem; /* Pointer to beginning of allocated memory. */
     30 };
     31 
     32 /******************************************/
     33 /*
     34 ** AES key wrap algorithm, RFC 3394
     35 */
     36 
     37 AESKeyWrapContext *
     38 AESKeyWrap_AllocateContext(void)
     39 {
     40    /* aligned_alloc is C11 so we have to do it the old way. */
     41    AESKeyWrapContext *ctx = PORT_ZAlloc(sizeof(AESKeyWrapContext) + 15);
     42    if (ctx == NULL) {
     43        PORT_SetError(SEC_ERROR_NO_MEMORY);
     44        return NULL;
     45    }
     46    ctx->mem = ctx;
     47    return (AESKeyWrapContext *)(((uintptr_t)ctx + 15) & ~(uintptr_t)0x0F);
     48 }
     49 
     50 SECStatus
     51 AESKeyWrap_InitContext(AESKeyWrapContext *cx,
     52                       const unsigned char *key,
     53                       unsigned int keylen,
     54                       const unsigned char *iv,
     55                       int x1,
     56                       unsigned int encrypt,
     57                       unsigned int x2)
     58 {
     59    SECStatus rv = SECFailure;
     60    if (!cx) {
     61        PORT_SetError(SEC_ERROR_INVALID_ARGS);
     62        return SECFailure;
     63    }
     64    if (iv) {
     65        memcpy(cx->iv, iv, sizeof cx->iv);
     66    } else {
     67        memset(cx->iv, 0xA6, sizeof cx->iv);
     68    }
     69    rv = AES_InitContext(&cx->aescx, key, keylen, NULL, NSS_AES, encrypt,
     70                         AES_BLOCK_SIZE);
     71    return rv;
     72 }
     73 
     74 /*
     75 ** Create a new AES context suitable for AES encryption/decryption.
     76 **  "key" raw key data
     77 **  "keylen" the number of bytes of key data (16, 24, or 32)
     78 */
     79 extern AESKeyWrapContext *
     80 AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv,
     81                         int encrypt, unsigned int keylen)
     82 {
     83    SECStatus rv;
     84    AESKeyWrapContext *cx = AESKeyWrap_AllocateContext();
     85    if (!cx)
     86        return NULL; /* error is already set */
     87    rv = AESKeyWrap_InitContext(cx, key, keylen, iv, 0, encrypt, 0);
     88    if (rv != SECSuccess) {
     89        PORT_Free(cx->mem);
     90        cx = NULL; /* error should already be set */
     91    }
     92    return cx;
     93 }
     94 
     95 /*
     96 ** Destroy a AES KeyWrap context.
     97 **  "cx" the context
     98 **  "freeit" if PR_TRUE then free the object as well as its sub-objects
     99 */
    100 extern void
    101 AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
    102 {
    103    if (cx) {
    104        AES_DestroyContext(&cx->aescx, PR_FALSE);
    105        /*  memset(cx, 0, sizeof *cx); */
    106        if (freeit) {
    107            PORT_Free(cx->mem);
    108        }
    109    }
    110 }
    111 
    112 #if !BIG_ENDIAN_WITH_64_BIT_REGISTERS
    113 
    114 /* The AES Key Wrap algorithm has 64-bit values that are ALWAYS big-endian
    115 ** (Most significant byte first) in memory.  The only ALU operations done
    116 ** on them are increment, decrement, and XOR.  So, on little-endian CPUs,
    117 ** and on CPUs that lack 64-bit registers, these big-endian 64-bit operations
    118 ** are simulated in the following code.  This is thought to be faster and
    119 ** simpler than trying to convert the data to little-endian and back.
    120 */
    121 
    122 /* A and T point to two 64-bit values stored most signficant byte first
    123 ** (big endian).  This function increments the 64-bit value T, and then
    124 ** XORs it with A, changing A.
    125 */
    126 static void
    127 increment_and_xor(unsigned char *A, unsigned char *T)
    128 {
    129    if (!++T[7])
    130        if (!++T[6])
    131            if (!++T[5])
    132                if (!++T[4])
    133                    if (!++T[3])
    134                        if (!++T[2])
    135                            if (!++T[1])
    136                                ++T[0];
    137 
    138    A[0] ^= T[0];
    139    A[1] ^= T[1];
    140    A[2] ^= T[2];
    141    A[3] ^= T[3];
    142    A[4] ^= T[4];
    143    A[5] ^= T[5];
    144    A[6] ^= T[6];
    145    A[7] ^= T[7];
    146 }
    147 
    148 /* A and T point to two 64-bit values stored most signficant byte first
    149 ** (big endian).  This function XORs T with A, giving a new A, then
    150 ** decrements the 64-bit value T.
    151 */
    152 static void
    153 xor_and_decrement(PRUint64 *A, PRUint64 *T)
    154 {
    155    unsigned char *TP = (unsigned char *)T;
    156    const PRUint64 mask = 0xFF;
    157    *A = ((*A & mask << 56) ^ (*T & mask << 56)) |
    158         ((*A & mask << 48) ^ (*T & mask << 48)) |
    159         ((*A & mask << 40) ^ (*T & mask << 40)) |
    160         ((*A & mask << 32) ^ (*T & mask << 32)) |
    161         ((*A & mask << 24) ^ (*T & mask << 23)) |
    162         ((*A & mask << 16) ^ (*T & mask << 16)) |
    163         ((*A & mask << 8) ^ (*T & mask << 8)) |
    164         ((*A & mask) ^ (*T & mask));
    165 
    166    if (!TP[7]--)
    167        if (!TP[6]--)
    168            if (!TP[5]--)
    169                if (!TP[4]--)
    170                    if (!TP[3]--)
    171                        if (!TP[2]--)
    172                            if (!TP[1]--)
    173                                TP[0]--;
    174 }
    175 
    176 /* Given an unsigned long t (in host byte order), store this value as a
    177 ** 64-bit big-endian value (MSB first) in *pt.
    178 */
    179 static void
    180 set_t(unsigned char *pt, unsigned long t)
    181 {
    182    pt[7] = (unsigned char)t;
    183    t >>= 8;
    184    pt[6] = (unsigned char)t;
    185    t >>= 8;
    186    pt[5] = (unsigned char)t;
    187    t >>= 8;
    188    pt[4] = (unsigned char)t;
    189    t >>= 8;
    190    pt[3] = (unsigned char)t;
    191    t >>= 8;
    192    pt[2] = (unsigned char)t;
    193    t >>= 8;
    194    pt[1] = (unsigned char)t;
    195    t >>= 8;
    196    pt[0] = (unsigned char)t;
    197 }
    198 
    199 #endif
    200 
    201 static void
    202 encode_PRUint32_BE(unsigned char *data, PRUint32 val)
    203 {
    204    size_t i;
    205    for (i = 0; i < sizeof(PRUint32); i++) {
    206        data[i] = PORT_GET_BYTE_BE(val, i, sizeof(PRUint32));
    207    }
    208 }
    209 
    210 static PRUint32
    211 decode_PRUint32_BE(unsigned char *data)
    212 {
    213    PRUint32 val = 0;
    214    size_t i;
    215 
    216    for (i = 0; i < sizeof(PRUint32); i++) {
    217        val = (val << PR_BITS_PER_BYTE) | data[i];
    218    }
    219    return val;
    220 }
    221 
    222 /*
    223 ** Perform AES key wrap W function.
    224 **  "cx" the context
    225 **  "iv" the iv is concatenated to the plain text for for executing the function
    226 **  "output" the output buffer to store the encrypted data.
    227 **  "pOutputLen" how much data is stored in "output". Set by the routine
    228 **     after some data is stored in output.
    229 **  "maxOutputLen" the maximum amount of data that can ever be
    230 **     stored in "output"
    231 **  "input" the input data
    232 **  "inputLen" the amount of input data
    233 */
    234 extern SECStatus
    235 AESKeyWrap_W(AESKeyWrapContext *cx, unsigned char *iv, unsigned char *output,
    236             unsigned int *pOutputLen, unsigned int maxOutputLen,
    237             const unsigned char *input, unsigned int inputLen)
    238 {
    239    PRUint64 *R = NULL;
    240    unsigned int nBlocks;
    241    unsigned int i, j;
    242    unsigned int aesLen = AES_BLOCK_SIZE;
    243    unsigned int outLen = inputLen + AES_KEY_WRAP_BLOCK_SIZE;
    244    SECStatus s = SECFailure;
    245    /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
    246    PRUint64 t;
    247    PRUint64 B[2];
    248 
    249 #define A B[0]
    250 
    251    /* Check args */
    252    if (inputLen < 2 * AES_KEY_WRAP_BLOCK_SIZE ||
    253        0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
    254        PORT_SetError(SEC_ERROR_INPUT_LEN);
    255        return s;
    256    }
    257 #ifdef maybe
    258    if (!output && pOutputLen) { /* caller is asking for output size */
    259        *pOutputLen = outLen;
    260        return SECSuccess;
    261    }
    262 #endif
    263    if (maxOutputLen < outLen) {
    264        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    265        return s;
    266    }
    267    if (cx == NULL || output == NULL || input == NULL) {
    268        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    269        return s;
    270    }
    271    nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
    272    R = PORT_NewArray(PRUint64, nBlocks + 1);
    273    if (!R)
    274        return s; /* error is already set. */
    275    /*
    276    ** 1) Initialize variables.
    277    */
    278    memcpy(&A, iv, AES_KEY_WRAP_IV_BYTES);
    279    memcpy(&R[1], input, inputLen);
    280 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
    281    t = 0;
    282 #else
    283    memset(&t, 0, sizeof t);
    284 #endif
    285    /*
    286    ** 2) Calculate intermediate values.
    287    */
    288    for (j = 0; j < 6; ++j) {
    289        for (i = 1; i <= nBlocks; ++i) {
    290            B[1] = R[i];
    291            s = AES_Encrypt(&cx->aescx, (unsigned char *)B, &aesLen,
    292                            sizeof B, (unsigned char *)B, sizeof B);
    293            if (s != SECSuccess)
    294                break;
    295            R[i] = B[1];
    296 /* here, increment t and XOR A with t (in big endian order); */
    297 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
    298            A ^= ++t;
    299 #else
    300            increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
    301 #endif
    302        }
    303    }
    304    /*
    305    ** 3) Output the results.
    306    */
    307    if (s == SECSuccess) {
    308        R[0] = A;
    309        memcpy(output, &R[0], outLen);
    310        if (pOutputLen)
    311            *pOutputLen = outLen;
    312    } else if (pOutputLen) {
    313        *pOutputLen = 0;
    314    }
    315    PORT_ZFree(R, outLen);
    316    return s;
    317 }
    318 #undef A
    319 
    320 /*
    321 ** Perform AES key wrap W^-1 function.
    322 **  "cx" the context
    323 **  "iv" the input IV to verify against. If NULL, then skip verification.
    324 **  "ivOut" the output buffer to store the IV (optional).
    325 **  "output" the output buffer to store the decrypted data.
    326 **  "pOutputLen" how much data is stored in "output". Set by the routine
    327 **     after some data is stored in output.
    328 **  "maxOutputLen" the maximum amount of data that can ever be
    329 **     stored in "output"
    330 **  "input" the input data
    331 **  "inputLen" the amount of input data
    332 */
    333 extern SECStatus
    334 AESKeyWrap_Winv(AESKeyWrapContext *cx, unsigned char *iv,
    335                unsigned char *ivOut, unsigned char *output,
    336                unsigned int *pOutputLen, unsigned int maxOutputLen,
    337                const unsigned char *input, unsigned int inputLen)
    338 {
    339    PRUint64 *R = NULL;
    340    unsigned int nBlocks;
    341    unsigned int i, j;
    342    unsigned int aesLen = AES_BLOCK_SIZE;
    343    unsigned int outLen;
    344    SECStatus s = SECFailure;
    345    /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
    346    PRUint64 t;
    347    PRUint64 B[2];
    348 
    349    /* Check args */
    350    if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
    351        0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
    352        PORT_SetError(SEC_ERROR_INPUT_LEN);
    353        return s;
    354    }
    355    outLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
    356 #ifdef maybe
    357    if (!output && pOutputLen) { /* caller is asking for output size */
    358        *pOutputLen = outLen;
    359        return SECSuccess;
    360    }
    361 #endif
    362    if (maxOutputLen < outLen) {
    363        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    364        return s;
    365    }
    366    if (cx == NULL || output == NULL || input == NULL) {
    367        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    368        return s;
    369    }
    370    nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
    371    R = PORT_NewArray(PRUint64, nBlocks);
    372    if (!R)
    373        return s; /* error is already set. */
    374    nBlocks--;
    375    /*
    376    ** 1) Initialize variables.
    377    */
    378    memcpy(&R[0], input, inputLen);
    379    B[0] = R[0];
    380 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
    381    t = 6UL * nBlocks;
    382 #else
    383    set_t((unsigned char *)&t, 6UL * nBlocks);
    384 #endif
    385    /*
    386    ** 2) Calculate intermediate values.
    387    */
    388    for (j = 0; j < 6; ++j) {
    389        for (i = nBlocks; i; --i) {
    390 /* here, XOR A with t (in big endian order) and decrement t; */
    391 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
    392            B[0] ^= t--;
    393 #else
    394            xor_and_decrement(&B[0], &t);
    395 #endif
    396            B[1] = R[i];
    397            s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen,
    398                            sizeof B, (unsigned char *)B, sizeof B);
    399            if (s != SECSuccess)
    400                break;
    401            R[i] = B[1];
    402        }
    403    }
    404    /*
    405    ** 3) Output the results.
    406    */
    407    if (s == SECSuccess) {
    408        int bad = (iv) && memcmp(&B[0], iv, AES_KEY_WRAP_IV_BYTES);
    409        if (!bad) {
    410            memcpy(output, &R[1], outLen);
    411            if (pOutputLen)
    412                *pOutputLen = outLen;
    413            if (ivOut) {
    414                memcpy(ivOut, &B[0], AES_KEY_WRAP_IV_BYTES);
    415            }
    416        } else {
    417            s = SECFailure;
    418            PORT_SetError(SEC_ERROR_BAD_DATA);
    419            if (pOutputLen)
    420                *pOutputLen = 0;
    421        }
    422    } else if (pOutputLen) {
    423        *pOutputLen = 0;
    424    }
    425    PORT_ZFree(R, inputLen);
    426    return s;
    427 }
    428 #undef A
    429 
    430 /*
    431 ** Perform AES key wrap.
    432 **  "cx" the context
    433 **  "output" the output buffer to store the encrypted data.
    434 **  "pOutputLen" how much data is stored in "output". Set by the routine
    435 **     after some data is stored in output.
    436 **  "maxOutputLen" the maximum amount of data that can ever be
    437 **     stored in "output"
    438 **  "input" the input data
    439 **  "inputLen" the amount of input data
    440 */
    441 extern SECStatus
    442 AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
    443                   unsigned int *pOutputLen, unsigned int maxOutputLen,
    444                   const unsigned char *input, unsigned int inputLen)
    445 {
    446    return AESKeyWrap_W(cx, cx->iv, output, pOutputLen, maxOutputLen,
    447                        input, inputLen);
    448 }
    449 
    450 /*
    451 ** Perform AES key unwrap.
    452 **  "cx" the context
    453 **  "output" the output buffer to store the decrypted data.
    454 **  "pOutputLen" how much data is stored in "output". Set by the routine
    455 **     after some data is stored in output.
    456 **  "maxOutputLen" the maximum amount of data that can ever be
    457 **     stored in "output"
    458 **  "input" the input data
    459 **  "inputLen" the amount of input data
    460 */
    461 extern SECStatus
    462 AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
    463                   unsigned int *pOutputLen, unsigned int maxOutputLen,
    464                   const unsigned char *input, unsigned int inputLen)
    465 {
    466    return AESKeyWrap_Winv(cx, cx->iv, NULL, output, pOutputLen, maxOutputLen,
    467                           input, inputLen);
    468 }
    469 
    470 #define BLOCK_PAD_POWER2(x, bs) (((bs) - ((x) & ((bs)-1))) & ((bs)-1))
    471 #define AES_KEY_WRAP_ICV2 0xa6, 0x59, 0x59, 0xa6
    472 #define AES_KEY_WRAP_ICV2_INT32 0xa65959a6
    473 #define AES_KEY_WRAP_ICV2_LEN 4
    474 
    475 /*
    476 ** Perform AES key wrap with padding.
    477 **  "cx" the context
    478 **  "output" the output buffer to store the encrypted data.
    479 **  "pOutputLen" how much data is stored in "output". Set by the routine
    480 **     after some data is stored in output.
    481 **  "maxOutputLen" the maximum amount of data that can ever be
    482 **     stored in "output"
    483 **  "input" the input data
    484 **  "inputLen" the amount of input data
    485 */
    486 extern SECStatus
    487 AESKeyWrap_EncryptKWP(AESKeyWrapContext *cx, unsigned char *output,
    488                      unsigned int *pOutputLen, unsigned int maxOutputLen,
    489                      const unsigned char *input, unsigned int inputLen)
    490 {
    491    unsigned int padLen = BLOCK_PAD_POWER2(inputLen, AES_KEY_WRAP_BLOCK_SIZE);
    492    unsigned int paddedInputLen = inputLen + padLen;
    493    unsigned int outLen = paddedInputLen + AES_KEY_WRAP_BLOCK_SIZE;
    494    unsigned char iv[AES_BLOCK_SIZE] = { AES_KEY_WRAP_ICV2 };
    495    unsigned char *newBuf;
    496    SECStatus rv;
    497 
    498    *pOutputLen = outLen;
    499    if (maxOutputLen < outLen) {
    500        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    501        return SECFailure;
    502    }
    503    PORT_Assert((AES_KEY_WRAP_ICV2_LEN + sizeof(PRUint32)) == AES_KEY_WRAP_BLOCK_SIZE);
    504    encode_PRUint32_BE(iv + AES_KEY_WRAP_ICV2_LEN, inputLen);
    505 
    506    /* If we can fit in an AES Block, just do and AES Encrypt,
    507     * iv is big enough to handle this on the stack, so no need to allocate
    508     */
    509    if (outLen == AES_BLOCK_SIZE) {
    510        PORT_Assert(inputLen <= AES_KEY_WRAP_BLOCK_SIZE);
    511        PORT_Memset(iv + AES_KEY_WRAP_BLOCK_SIZE, 0, AES_KEY_WRAP_BLOCK_SIZE);
    512        PORT_Memcpy(iv + AES_KEY_WRAP_BLOCK_SIZE, input, inputLen);
    513        rv = AES_Encrypt(&cx->aescx, output, pOutputLen, maxOutputLen, iv,
    514                         outLen);
    515        PORT_SafeZero(iv, sizeof(iv));
    516        return rv;
    517    }
    518 
    519    /* add padding to our input block */
    520    newBuf = PORT_ZAlloc(paddedInputLen);
    521    if (newBuf == NULL) {
    522        return SECFailure;
    523    }
    524    PORT_Memcpy(newBuf, input, inputLen);
    525 
    526    rv = AESKeyWrap_W(cx, iv, output, pOutputLen, maxOutputLen,
    527                      newBuf, paddedInputLen);
    528    PORT_ZFree(newBuf, paddedInputLen);
    529    /* a little overkill, we only need to clear out the length, but this
    530     * is easier to verify we got it all */
    531    PORT_SafeZero(iv, sizeof(iv));
    532    return rv;
    533 }
    534 
    535 /*
    536 ** Perform AES key unwrap with padding.
    537 **  "cx" the context
    538 **  "output" the output buffer to store the decrypted data.
    539 **  "pOutputLen" how much data is stored in "output". Set by the routine
    540 **     after some data is stored in output.
    541 **  "maxOutputLen" the maximum amount of data that can ever be
    542 **     stored in "output"
    543 **  "input" the input data
    544 **  "inputLen" the amount of input data
    545 */
    546 extern SECStatus
    547 AESKeyWrap_DecryptKWP(AESKeyWrapContext *cx, unsigned char *output,
    548                      unsigned int *pOutputLen, unsigned int maxOutputLen,
    549                      const unsigned char *input, unsigned int inputLen)
    550 {
    551    unsigned int padLen;
    552    unsigned int padLen2;
    553    unsigned int outLen;
    554    unsigned int paddedLen;
    555    unsigned int good;
    556    unsigned char *newBuf = NULL;
    557    unsigned char *allocBuf = NULL;
    558    int i;
    559    unsigned char iv[AES_BLOCK_SIZE];
    560    PRUint32 magic;
    561    SECStatus rv = SECFailure;
    562 
    563    paddedLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
    564    /* unwrap the padded result */
    565    if (inputLen == AES_BLOCK_SIZE) {
    566        rv = AES_Decrypt(&cx->aescx, iv, &outLen, inputLen, input, inputLen);
    567        newBuf = &iv[AES_KEY_WRAP_BLOCK_SIZE];
    568        outLen -= AES_KEY_WRAP_BLOCK_SIZE;
    569    } else {
    570        /* if the caller supplied enough space to hold the unpadded buffer,
    571         * we can unwrap directly into that unpadded buffer. Otherwise
    572         * we allocate a buffer that can hold the padding, and we'll copy
    573         * the result in a later step */
    574        newBuf = output;
    575        if (maxOutputLen < paddedLen) {
    576            allocBuf = newBuf = PORT_Alloc(paddedLen);
    577            if (!allocBuf) {
    578                return SECFailure;
    579            }
    580        }
    581        /* We pass NULL for the first IV argument because we don't know
    582         * what the IV has since in includes the length, so we don't have
    583         * Winv verify it. We pass iv in the second argument to get the
    584         * iv, which we verify below before we return anything */
    585        rv = AESKeyWrap_Winv(cx, NULL, iv, newBuf, &outLen,
    586                             paddedLen, input, inputLen);
    587    }
    588    if (rv != SECSuccess) {
    589        goto loser;
    590    }
    591    rv = SECFailure;
    592    if (outLen != paddedLen) {
    593        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    594        goto loser;
    595    }
    596 
    597    /* we verify the result in a constant time manner */
    598    /* verify ICV magic */
    599    magic = decode_PRUint32_BE(iv);
    600    good = PORT_CT_EQ(magic, AES_KEY_WRAP_ICV2_INT32);
    601    /* fetch and verify plain text length */
    602    outLen = decode_PRUint32_BE(iv + AES_KEY_WRAP_ICV2_LEN);
    603    good &= PORT_CT_LE(outLen, paddedLen);
    604    /* now verify the padding */
    605    padLen = paddedLen - outLen;
    606    padLen2 = BLOCK_PAD_POWER2(outLen, AES_KEY_WRAP_BLOCK_SIZE);
    607    good &= PORT_CT_EQ(padLen, padLen2);
    608    for (i = 0; i < AES_KEY_WRAP_BLOCK_SIZE; i++) {
    609        unsigned int doTest = PORT_CT_GT(padLen, i);
    610        unsigned int result = PORT_CT_ZERO(newBuf[paddedLen - i - 1]);
    611        good &= PORT_CT_SEL(doTest, result, PORT_CT_TRUE);
    612    }
    613 
    614    /* now if anything was wrong, fail. At this point we will leak timing
    615     * information, but we also 'leak' the error code as well. */
    616    if (!good) {
    617        PORT_SetError(SEC_ERROR_BAD_DATA);
    618        goto loser;
    619    }
    620 
    621    /* now copy out the result */
    622    *pOutputLen = outLen;
    623    if (maxOutputLen < outLen) {
    624        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    625        goto loser;
    626    }
    627    if (output != newBuf) {
    628        PORT_Memcpy(output, newBuf, outLen);
    629    }
    630    rv = SECSuccess;
    631 loser:
    632    /* if we failed, make sure we don't return any data to the user */
    633    if ((rv != SECSuccess) && (output == newBuf)) {
    634        PORT_SafeZero(newBuf, paddedLen);
    635    }
    636    /* clear out CSP sensitive data from the heap and stack */
    637    if (allocBuf) {
    638        PORT_ZFree(allocBuf, paddedLen);
    639    }
    640    PORT_SafeZero(iv, sizeof(iv));
    641    return rv;
    642 }