"Fossies" - the Fresh Open Source Software Archive

Member "nss-3.55/nss/lib/freebl/aeskeywrap.c" (24 Jul 2020, 20139 Bytes) of package /linux/misc/nss-3.55.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "aeskeywrap.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.52.1_vs_3.53.

    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_Memset(iv, 0, 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_Memset(iv, 0, 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_Memset(newBuf, 0, paddedLen);
  635     }
  636     /* clear out CSP sensitive data from the heap and stack */
  637     if (allocBuf) {
  638         PORT_ZFree(allocBuf, paddedLen);
  639     }
  640     PORT_Memset(iv, 0, sizeof(iv));
  641     return rv;
  642 }