Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/freebl/aeskeywrap.c
Line
Count
Source (jump to first uncovered line)
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
0
{
40
    /* aligned_alloc is C11 so we have to do it the old way. */
41
0
    AESKeyWrapContext *ctx = PORT_ZAlloc(sizeof(AESKeyWrapContext) + 15);
42
0
    if (ctx == NULL) {
43
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
44
0
        return NULL;
45
0
    }
46
0
    ctx->mem = ctx;
47
0
    return (AESKeyWrapContext *)(((uintptr_t)ctx + 15) & ~(uintptr_t)0x0F);
48
0
}
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
0
{
59
0
    SECStatus rv = SECFailure;
60
0
    if (!cx) {
61
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
62
0
        return SECFailure;
63
0
    }
64
0
    if (iv) {
65
0
        memcpy(cx->iv, iv, sizeof cx->iv);
66
0
    } else {
67
0
        memset(cx->iv, 0xA6, sizeof cx->iv);
68
0
    }
69
0
    rv = AES_InitContext(&cx->aescx, key, keylen, NULL, NSS_AES, encrypt,
70
0
                         AES_BLOCK_SIZE);
71
0
    return rv;
72
0
}
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
0
{
83
0
    SECStatus rv;
84
0
    AESKeyWrapContext *cx = AESKeyWrap_AllocateContext();
85
0
    if (!cx)
86
0
        return NULL; /* error is already set */
87
0
    rv = AESKeyWrap_InitContext(cx, key, keylen, iv, 0, encrypt, 0);
88
0
    if (rv != SECSuccess) {
89
0
        PORT_Free(cx->mem);
90
0
        cx = NULL; /* error should already be set */
91
0
    }
92
0
    return cx;
93
0
}
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
0
{
103
0
    if (cx) {
104
0
        AES_DestroyContext(&cx->aescx, PR_FALSE);
105
        /*  memset(cx, 0, sizeof *cx); */
106
0
        if (freeit) {
107
0
            PORT_Free(cx->mem);
108
0
        }
109
0
    }
110
0
}
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
0
{
129
0
    if (!++T[7])
130
0
        if (!++T[6])
131
0
            if (!++T[5])
132
0
                if (!++T[4])
133
0
                    if (!++T[3])
134
0
                        if (!++T[2])
135
0
                            if (!++T[1])
136
0
                                ++T[0];
137
138
0
    A[0] ^= T[0];
139
0
    A[1] ^= T[1];
140
0
    A[2] ^= T[2];
141
0
    A[3] ^= T[3];
142
0
    A[4] ^= T[4];
143
0
    A[5] ^= T[5];
144
0
    A[6] ^= T[6];
145
0
    A[7] ^= T[7];
146
0
}
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
0
{
155
0
    unsigned char *TP = (unsigned char *)T;
156
0
    const PRUint64 mask = 0xFF;
157
0
    *A = ((*A & mask << 56) ^ (*T & mask << 56)) |
158
0
         ((*A & mask << 48) ^ (*T & mask << 48)) |
159
0
         ((*A & mask << 40) ^ (*T & mask << 40)) |
160
0
         ((*A & mask << 32) ^ (*T & mask << 32)) |
161
0
         ((*A & mask << 24) ^ (*T & mask << 23)) |
162
0
         ((*A & mask << 16) ^ (*T & mask << 16)) |
163
0
         ((*A & mask << 8) ^ (*T & mask << 8)) |
164
0
         ((*A & mask) ^ (*T & mask));
165
166
0
    if (!TP[7]--)
167
0
        if (!TP[6]--)
168
0
            if (!TP[5]--)
169
0
                if (!TP[4]--)
170
0
                    if (!TP[3]--)
171
0
                        if (!TP[2]--)
172
0
                            if (!TP[1]--)
173
0
                                TP[0]--;
174
0
}
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
0
{
182
0
    pt[7] = (unsigned char)t;
183
0
    t >>= 8;
184
0
    pt[6] = (unsigned char)t;
185
0
    t >>= 8;
186
0
    pt[5] = (unsigned char)t;
187
0
    t >>= 8;
188
0
    pt[4] = (unsigned char)t;
189
0
    t >>= 8;
190
0
    pt[3] = (unsigned char)t;
191
0
    t >>= 8;
192
0
    pt[2] = (unsigned char)t;
193
0
    t >>= 8;
194
0
    pt[1] = (unsigned char)t;
195
0
    t >>= 8;
196
0
    pt[0] = (unsigned char)t;
197
0
}
198
199
#endif
200
201
static void
202
encode_PRUint32_BE(unsigned char *data, PRUint32 val)
203
0
{
204
0
    size_t i;
205
0
    for (i = 0; i < sizeof(PRUint32); i++) {
206
0
        data[i] = PORT_GET_BYTE_BE(val, i, sizeof(PRUint32));
207
0
    }
208
0
}
209
210
static PRUint32
211
decode_PRUint32_BE(unsigned char *data)
212
0
{
213
0
    PRUint32 val = 0;
214
0
    size_t i;
215
216
0
    for (i = 0; i < sizeof(PRUint32); i++) {
217
0
        val = (val << PR_BITS_PER_BYTE) | data[i];
218
0
    }
219
0
    return val;
220
0
}
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
0
{
239
0
    PRUint64 *R = NULL;
240
0
    unsigned int nBlocks;
241
0
    unsigned int i, j;
242
0
    unsigned int aesLen = AES_BLOCK_SIZE;
243
0
    unsigned int outLen = inputLen + AES_KEY_WRAP_BLOCK_SIZE;
244
0
    SECStatus s = SECFailure;
245
    /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
246
0
    PRUint64 t;
247
0
    PRUint64 B[2];
248
249
0
#define A B[0]
250
251
    /* Check args */
252
0
    if (inputLen < 2 * AES_KEY_WRAP_BLOCK_SIZE ||
253
0
        0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
254
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
255
0
        return s;
256
0
    }
257
#ifdef maybe
258
    if (!output && pOutputLen) { /* caller is asking for output size */
259
        *pOutputLen = outLen;
260
        return SECSuccess;
261
    }
262
#endif
263
0
    if (maxOutputLen < outLen) {
264
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
265
0
        return s;
266
0
    }
267
0
    if (cx == NULL || output == NULL || input == NULL) {
268
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
269
0
        return s;
270
0
    }
271
0
    nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
272
0
    R = PORT_NewArray(PRUint64, nBlocks + 1);
273
0
    if (!R)
274
0
        return s; /* error is already set. */
275
    /*
276
    ** 1) Initialize variables.
277
    */
278
0
    memcpy(&A, iv, AES_KEY_WRAP_IV_BYTES);
279
0
    memcpy(&R[1], input, inputLen);
280
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
281
    t = 0;
282
#else
283
0
    memset(&t, 0, sizeof t);
284
0
#endif
285
    /*
286
    ** 2) Calculate intermediate values.
287
    */
288
0
    for (j = 0; j < 6; ++j) {
289
0
        for (i = 1; i <= nBlocks; ++i) {
290
0
            B[1] = R[i];
291
0
            s = AES_Encrypt(&cx->aescx, (unsigned char *)B, &aesLen,
292
0
                            sizeof B, (unsigned char *)B, sizeof B);
293
0
            if (s != SECSuccess)
294
0
                break;
295
0
            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
0
            increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
301
0
#endif
302
0
        }
303
0
    }
304
    /*
305
    ** 3) Output the results.
306
    */
307
0
    if (s == SECSuccess) {
308
0
        R[0] = A;
309
0
        memcpy(output, &R[0], outLen);
310
0
        if (pOutputLen)
311
0
            *pOutputLen = outLen;
312
0
    } else if (pOutputLen) {
313
0
        *pOutputLen = 0;
314
0
    }
315
0
    PORT_ZFree(R, outLen);
316
0
    return s;
317
0
}
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
0
{
339
0
    PRUint64 *R = NULL;
340
0
    unsigned int nBlocks;
341
0
    unsigned int i, j;
342
0
    unsigned int aesLen = AES_BLOCK_SIZE;
343
0
    unsigned int outLen;
344
0
    SECStatus s = SECFailure;
345
    /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
346
0
    PRUint64 t;
347
0
    PRUint64 B[2];
348
349
    /* Check args */
350
0
    if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
351
0
        0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
352
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
353
0
        return s;
354
0
    }
355
0
    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
0
    if (maxOutputLen < outLen) {
363
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
364
0
        return s;
365
0
    }
366
0
    if (cx == NULL || output == NULL || input == NULL) {
367
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
368
0
        return s;
369
0
    }
370
0
    nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
371
0
    R = PORT_NewArray(PRUint64, nBlocks);
372
0
    if (!R)
373
0
        return s; /* error is already set. */
374
0
    nBlocks--;
375
    /*
376
    ** 1) Initialize variables.
377
    */
378
0
    memcpy(&R[0], input, inputLen);
379
0
    B[0] = R[0];
380
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
381
    t = 6UL * nBlocks;
382
#else
383
0
    set_t((unsigned char *)&t, 6UL * nBlocks);
384
0
#endif
385
    /*
386
    ** 2) Calculate intermediate values.
387
    */
388
0
    for (j = 0; j < 6; ++j) {
389
0
        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
0
            xor_and_decrement(&B[0], &t);
395
0
#endif
396
0
            B[1] = R[i];
397
0
            s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen,
398
0
                            sizeof B, (unsigned char *)B, sizeof B);
399
0
            if (s != SECSuccess)
400
0
                break;
401
0
            R[i] = B[1];
402
0
        }
403
0
    }
404
    /*
405
    ** 3) Output the results.
406
    */
407
0
    if (s == SECSuccess) {
408
0
        int bad = (iv) && memcmp(&B[0], iv, AES_KEY_WRAP_IV_BYTES);
409
0
        if (!bad) {
410
0
            memcpy(output, &R[1], outLen);
411
0
            if (pOutputLen)
412
0
                *pOutputLen = outLen;
413
0
            if (ivOut) {
414
0
                memcpy(ivOut, &B[0], AES_KEY_WRAP_IV_BYTES);
415
0
            }
416
0
        } else {
417
0
            s = SECFailure;
418
0
            PORT_SetError(SEC_ERROR_BAD_DATA);
419
0
            if (pOutputLen)
420
0
                *pOutputLen = 0;
421
0
        }
422
0
    } else if (pOutputLen) {
423
0
        *pOutputLen = 0;
424
0
    }
425
0
    PORT_ZFree(R, inputLen);
426
0
    return s;
427
0
}
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
0
{
446
0
    return AESKeyWrap_W(cx, cx->iv, output, pOutputLen, maxOutputLen,
447
0
                        input, inputLen);
448
0
}
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
0
{
466
0
    return AESKeyWrap_Winv(cx, cx->iv, NULL, output, pOutputLen, maxOutputLen,
467
0
                           input, inputLen);
468
0
}
469
470
0
#define BLOCK_PAD_POWER2(x, bs) (((bs) - ((x) & ((bs)-1))) & ((bs)-1))
471
0
#define AES_KEY_WRAP_ICV2 0xa6, 0x59, 0x59, 0xa6
472
#define AES_KEY_WRAP_ICV2_INT32 0xa65959a6
473
0
#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
0
{
491
0
    unsigned int padLen = BLOCK_PAD_POWER2(inputLen, AES_KEY_WRAP_BLOCK_SIZE);
492
0
    unsigned int paddedInputLen = inputLen + padLen;
493
0
    unsigned int outLen = paddedInputLen + AES_KEY_WRAP_BLOCK_SIZE;
494
0
    unsigned char iv[AES_BLOCK_SIZE] = { AES_KEY_WRAP_ICV2 };
495
0
    unsigned char *newBuf;
496
0
    SECStatus rv;
497
498
0
    *pOutputLen = outLen;
499
0
    if (maxOutputLen < outLen) {
500
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
501
0
        return SECFailure;
502
0
    }
503
0
    PORT_Assert((AES_KEY_WRAP_ICV2_LEN + sizeof(PRUint32)) == AES_KEY_WRAP_BLOCK_SIZE);
504
0
    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
0
    if (outLen == AES_BLOCK_SIZE) {
510
0
        PORT_Assert(inputLen <= AES_KEY_WRAP_BLOCK_SIZE);
511
0
        PORT_Memset(iv + AES_KEY_WRAP_BLOCK_SIZE, 0, AES_KEY_WRAP_BLOCK_SIZE);
512
0
        PORT_Memcpy(iv + AES_KEY_WRAP_BLOCK_SIZE, input, inputLen);
513
0
        rv = AES_Encrypt(&cx->aescx, output, pOutputLen, maxOutputLen, iv,
514
0
                         outLen);
515
0
        PORT_Memset(iv, 0, sizeof(iv));
516
0
        return rv;
517
0
    }
518
519
    /* add padding to our input block */
520
0
    newBuf = PORT_ZAlloc(paddedInputLen);
521
0
    if (newBuf == NULL) {
522
0
        return SECFailure;
523
0
    }
524
0
    PORT_Memcpy(newBuf, input, inputLen);
525
526
0
    rv = AESKeyWrap_W(cx, iv, output, pOutputLen, maxOutputLen,
527
0
                      newBuf, paddedInputLen);
528
0
    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
0
    PORT_Memset(iv, 0, sizeof(iv));
532
0
    return rv;
533
0
}
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
0
{
551
0
    unsigned int padLen;
552
0
    unsigned int padLen2;
553
0
    unsigned int outLen;
554
0
    unsigned int paddedLen;
555
0
    unsigned int good;
556
0
    unsigned char *newBuf = NULL;
557
0
    unsigned char *allocBuf = NULL;
558
0
    int i;
559
0
    unsigned char iv[AES_BLOCK_SIZE];
560
0
    PRUint32 magic;
561
0
    SECStatus rv = SECFailure;
562
563
0
    paddedLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
564
    /* unwrap the padded result */
565
0
    if (inputLen == AES_BLOCK_SIZE) {
566
0
        rv = AES_Decrypt(&cx->aescx, iv, &outLen, inputLen, input, inputLen);
567
0
        newBuf = &iv[AES_KEY_WRAP_BLOCK_SIZE];
568
0
        outLen -= AES_KEY_WRAP_BLOCK_SIZE;
569
0
    } 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
0
        newBuf = output;
575
0
        if (maxOutputLen < paddedLen) {
576
0
            allocBuf = newBuf = PORT_Alloc(paddedLen);
577
0
            if (!allocBuf) {
578
0
                return SECFailure;
579
0
            }
580
0
        }
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
0
        rv = AESKeyWrap_Winv(cx, NULL, iv, newBuf, &outLen,
586
0
                             paddedLen, input, inputLen);
587
0
    }
588
0
    if (rv != SECSuccess) {
589
0
        goto loser;
590
0
    }
591
0
    rv = SECFailure;
592
0
    if (outLen != paddedLen) {
593
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
594
0
        goto loser;
595
0
    }
596
597
    /* we verify the result in a constant time manner */
598
    /* verify ICV magic */
599
0
    magic = decode_PRUint32_BE(iv);
600
0
    good = PORT_CT_EQ(magic, AES_KEY_WRAP_ICV2_INT32);
601
    /* fetch and verify plain text length */
602
0
    outLen = decode_PRUint32_BE(iv + AES_KEY_WRAP_ICV2_LEN);
603
0
    good &= PORT_CT_LE(outLen, paddedLen);
604
    /* now verify the padding */
605
0
    padLen = paddedLen - outLen;
606
0
    padLen2 = BLOCK_PAD_POWER2(outLen, AES_KEY_WRAP_BLOCK_SIZE);
607
0
    good &= PORT_CT_EQ(padLen, padLen2);
608
0
    for (i = 0; i < AES_KEY_WRAP_BLOCK_SIZE; i++) {
609
0
        unsigned int doTest = PORT_CT_GT(padLen, i);
610
0
        unsigned int result = PORT_CT_ZERO(newBuf[paddedLen - i - 1]);
611
0
        good &= PORT_CT_SEL(doTest, result, PORT_CT_TRUE);
612
0
    }
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
0
    if (!good) {
617
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
618
0
        goto loser;
619
0
    }
620
621
    /* now copy out the result */
622
0
    *pOutputLen = outLen;
623
0
    if (maxOutputLen < outLen) {
624
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
625
0
        goto loser;
626
0
    }
627
0
    if (output != newBuf) {
628
0
        PORT_Memcpy(output, newBuf, outLen);
629
0
    }
630
0
    rv = SECSuccess;
631
0
loser:
632
    /* if we failed, make sure we don't return any data to the user */
633
0
    if ((rv != SECSuccess) && (output == newBuf)) {
634
0
        PORT_Memset(newBuf, 0, paddedLen);
635
0
    }
636
    /* clear out CSP sensitive data from the heap and stack */
637
0
    if (allocBuf) {
638
0
        PORT_ZFree(allocBuf, paddedLen);
639
0
    }
640
0
    PORT_Memset(iv, 0, sizeof(iv));
641
0
    return rv;
642
0
}