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 *
AESKeyWrap_AllocateContext(void)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
AESKeyWrap_InitContext(AESKeyWrapContext * cx,const unsigned char * key,unsigned int keylen,const unsigned char * iv,int x1,unsigned int encrypt,unsigned int x2)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 *
AESKeyWrap_CreateContext(const unsigned char * key,const unsigned char * iv,int encrypt,unsigned int keylen)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
AESKeyWrap_DestroyContext(AESKeyWrapContext * cx,PRBool freeit)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
increment_and_xor(unsigned char * A,unsigned char * T)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
xor_and_decrement(PRUint64 * A,PRUint64 * T)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
set_t(unsigned char * pt,unsigned long t)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
encode_PRUint32_BE(unsigned char * data,PRUint32 val)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
decode_PRUint32_BE(unsigned char * data)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
AESKeyWrap_W(AESKeyWrapContext * cx,unsigned char * iv,unsigned char * output,unsigned int * pOutputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)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
AESKeyWrap_Winv(AESKeyWrapContext * cx,unsigned char * iv,unsigned char * ivOut,unsigned char * output,unsigned int * pOutputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)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
AESKeyWrap_Encrypt(AESKeyWrapContext * cx,unsigned char * output,unsigned int * pOutputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)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
AESKeyWrap_Decrypt(AESKeyWrapContext * cx,unsigned char * output,unsigned int * pOutputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)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
AESKeyWrap_EncryptKWP(AESKeyWrapContext * cx,unsigned char * output,unsigned int * pOutputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)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
AESKeyWrap_DecryptKWP(AESKeyWrapContext * cx,unsigned char * output,unsigned int * pOutputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)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 }
643