Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/freebl/rijndael.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#ifdef FREEBL_NO_DEPEND
6
#include "stubs.h"
7
#endif
8
9
#include "blapit.h"
10
#include "prenv.h"
11
#include "prerr.h"
12
#include "prinit.h"
13
#include "secerr.h"
14
15
#include "prtypes.h"
16
#include "blapi.h"
17
#include "rijndael.h"
18
19
#include "cts.h"
20
#include "ctr.h"
21
#include "gcm.h"
22
#include "mpi.h"
23
24
#if !defined(IS_LITTLE_ENDIAN) && !defined(NSS_X86_OR_X64)
25
// not test yet on big endian platform of arm
26
#undef USE_HW_AES
27
#endif
28
29
#ifdef __powerpc64__
30
#include "ppc-crypto.h"
31
#endif
32
33
#ifdef USE_HW_AES
34
#ifdef NSS_X86_OR_X64
35
#include "intel-aes.h"
36
#else
37
#include "aes-armv8.h"
38
#endif
39
#endif /* USE_HW_AES */
40
#ifdef INTEL_GCM
41
#include "intel-gcm.h"
42
#endif /* INTEL_GCM */
43
#if defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
44
#include "ppc-gcm.h"
45
#endif
46
47
/* Forward declarations */
48
void rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
49
                                   unsigned int Nk);
50
void rijndael_native_encryptBlock(AESContext *cx,
51
                                  unsigned char *output,
52
                                  const unsigned char *input);
53
void rijndael_native_decryptBlock(AESContext *cx,
54
                                  unsigned char *output,
55
                                  const unsigned char *input);
56
void native_xorBlock(unsigned char *out,
57
                     const unsigned char *a,
58
                     const unsigned char *b);
59
60
/* Stub definitions for the above rijndael_native_* functions, which
61
 * shouldn't be used unless NSS_X86_OR_X64 is defined */
62
#ifndef NSS_X86_OR_X64
63
void
64
rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
65
                              unsigned int Nk)
66
{
67
    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
68
    PORT_Assert(0);
69
}
70
71
void
72
rijndael_native_encryptBlock(AESContext *cx,
73
                             unsigned char *output,
74
                             const unsigned char *input)
75
{
76
    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
77
    PORT_Assert(0);
78
}
79
80
void
81
rijndael_native_decryptBlock(AESContext *cx,
82
                             unsigned char *output,
83
                             const unsigned char *input)
84
{
85
    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
86
    PORT_Assert(0);
87
}
88
89
void
90
native_xorBlock(unsigned char *out, const unsigned char *a,
91
                const unsigned char *b)
92
{
93
    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
94
    PORT_Assert(0);
95
}
96
#endif /* NSS_X86_OR_X64 */
97
98
/*
99
 * There are currently three ways to build this code, varying in performance
100
 * and code size.
101
 *
102
 * RIJNDAEL_INCLUDE_TABLES         Include all tables from rijndael32.tab
103
 * RIJNDAEL_GENERATE_VALUES        Do not store tables, generate the table
104
 *                                 values "on-the-fly", using gfm
105
 * RIJNDAEL_GENERATE_VALUES_MACRO  Same as above, but use macros
106
 *
107
 * The default is RIJNDAEL_INCLUDE_TABLES.
108
 */
109
110
/*
111
 * When building RIJNDAEL_INCLUDE_TABLES, includes S**-1, Rcon, T[0..4],
112
 *                                                 T**-1[0..4], IMXC[0..4]
113
 * When building anything else, includes S, S**-1, Rcon
114
 */
115
#include "rijndael32.tab"
116
117
#if defined(RIJNDAEL_INCLUDE_TABLES)
118
/*
119
 * RIJNDAEL_INCLUDE_TABLES
120
 */
121
0
#define T0(i) _T0[i]
122
0
#define T1(i) _T1[i]
123
0
#define T2(i) _T2[i]
124
0
#define T3(i) _T3[i]
125
0
#define TInv0(i) _TInv0[i]
126
0
#define TInv1(i) _TInv1[i]
127
0
#define TInv2(i) _TInv2[i]
128
0
#define TInv3(i) _TInv3[i]
129
168
#define IMXC0(b) _IMXC0[b]
130
168
#define IMXC1(b) _IMXC1[b]
131
168
#define IMXC2(b) _IMXC2[b]
132
168
#define IMXC3(b) _IMXC3[b]
133
/* The S-box can be recovered from the T-tables */
134
#ifdef IS_LITTLE_ENDIAN
135
204
#define SBOX(b) ((PRUint8)_T3[b])
136
#else
137
#define SBOX(b) ((PRUint8)_T1[b])
138
#endif
139
0
#define SINV(b) (_SInv[b])
140
141
#else /* not RIJNDAEL_INCLUDE_TABLES */
142
143
/*
144
 * Code for generating T-table values.
145
 */
146
147
#ifdef IS_LITTLE_ENDIAN
148
#define WORD4(b0, b1, b2, b3) \
149
    ((((PRUint32)b3) << 24) | \
150
     (((PRUint32)b2) << 16) | \
151
     (((PRUint32)b1) << 8) |  \
152
     ((PRUint32)b0))
153
#else
154
#define WORD4(b0, b1, b2, b3) \
155
    ((((PRUint32)b0) << 24) | \
156
     (((PRUint32)b1) << 16) | \
157
     (((PRUint32)b2) << 8) |  \
158
     ((PRUint32)b3))
159
#endif
160
161
/*
162
 * Define the S and S**-1 tables (both have been stored)
163
 */
164
#define SBOX(b) (_S[b])
165
#define SINV(b) (_SInv[b])
166
167
/*
168
 * The function xtime, used for Galois field multiplication
169
 */
170
#define XTIME(a) \
171
    ((a & 0x80) ? ((a << 1) ^ 0x1b) : (a << 1))
172
173
/* Choose GFM method (macros or function) */
174
#if defined(RIJNDAEL_GENERATE_VALUES_MACRO)
175
176
/*
177
 * Galois field GF(2**8) multipliers, in macro form
178
 */
179
#define GFM01(a) \
180
    (a) /* a * 01 = a, the identity */
181
#define GFM02(a) \
182
    (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
183
#define GFM04(a) \
184
    (GFM02(GFM02(a))) /* a * 04 = xtime**2(a) */
185
#define GFM08(a) \
186
    (GFM02(GFM04(a))) /* a * 08 = xtime**3(a) */
187
#define GFM03(a) \
188
    (GFM01(a) ^ GFM02(a)) /* a * 03 = a * (01 + 02) */
189
#define GFM09(a) \
190
    (GFM01(a) ^ GFM08(a)) /* a * 09 = a * (01 + 08) */
191
#define GFM0B(a) \
192
    (GFM01(a) ^ GFM02(a) ^ GFM08(a)) /* a * 0B = a * (01 + 02 + 08) */
193
#define GFM0D(a) \
194
    (GFM01(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0D = a * (01 + 04 + 08) */
195
#define GFM0E(a) \
196
    (GFM02(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0E = a * (02 + 04 + 08) */
197
198
#else /* RIJNDAEL_GENERATE_VALUES */
199
200
/* GF_MULTIPLY
201
 *
202
 * multiply two bytes represented in GF(2**8), mod (x**4 + 1)
203
 */
204
PRUint8
205
gfm(PRUint8 a, PRUint8 b)
206
{
207
    PRUint8 res = 0;
208
    while (b > 0) {
209
        res = (b & 0x01) ? res ^ a : res;
210
        a = XTIME(a);
211
        b >>= 1;
212
    }
213
    return res;
214
}
215
216
#define GFM01(a) \
217
    (a) /* a * 01 = a, the identity */
218
#define GFM02(a) \
219
    (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
220
#define GFM03(a) \
221
    (gfm(a, 0x03)) /* a * 03 */
222
#define GFM09(a) \
223
    (gfm(a, 0x09)) /* a * 09 */
224
#define GFM0B(a) \
225
    (gfm(a, 0x0B)) /* a * 0B */
226
#define GFM0D(a) \
227
    (gfm(a, 0x0D)) /* a * 0D */
228
#define GFM0E(a) \
229
    (gfm(a, 0x0E)) /* a * 0E */
230
231
#endif /* choosing GFM function */
232
233
/*
234
 * The T-tables
235
 */
236
#define G_T0(i) \
237
    (WORD4(GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i))))
238
#define G_T1(i) \
239
    (WORD4(GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i))))
240
#define G_T2(i) \
241
    (WORD4(GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i))))
242
#define G_T3(i) \
243
    (WORD4(GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i))))
244
245
/*
246
 * The inverse T-tables
247
 */
248
#define G_TInv0(i) \
249
    (WORD4(GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i))))
250
#define G_TInv1(i) \
251
    (WORD4(GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i))))
252
#define G_TInv2(i) \
253
    (WORD4(GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i))))
254
#define G_TInv3(i) \
255
    (WORD4(GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i))))
256
257
/*
258
 * The inverse mix column tables
259
 */
260
#define G_IMXC0(i) \
261
    (WORD4(GFM0E(i), GFM09(i), GFM0D(i), GFM0B(i)))
262
#define G_IMXC1(i) \
263
    (WORD4(GFM0B(i), GFM0E(i), GFM09(i), GFM0D(i)))
264
#define G_IMXC2(i) \
265
    (WORD4(GFM0D(i), GFM0B(i), GFM0E(i), GFM09(i)))
266
#define G_IMXC3(i) \
267
    (WORD4(GFM09(i), GFM0D(i), GFM0B(i), GFM0E(i)))
268
269
/* Now choose the T-table indexing method */
270
#if defined(RIJNDAEL_GENERATE_VALUES)
271
/* generate values for the tables with a function*/
272
static PRUint32
273
gen_TInvXi(PRUint8 tx, PRUint8 i)
274
{
275
    PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E;
276
    si01 = SINV(i);
277
    si02 = XTIME(si01);
278
    si04 = XTIME(si02);
279
    si08 = XTIME(si04);
280
    si03 = si02 ^ si01;
281
    si09 = si08 ^ si01;
282
    si0B = si08 ^ si03;
283
    si0D = si09 ^ si04;
284
    si0E = si08 ^ si04 ^ si02;
285
    switch (tx) {
286
        case 0:
287
            return WORD4(si0E, si09, si0D, si0B);
288
        case 1:
289
            return WORD4(si0B, si0E, si09, si0D);
290
        case 2:
291
            return WORD4(si0D, si0B, si0E, si09);
292
        case 3:
293
            return WORD4(si09, si0D, si0B, si0E);
294
    }
295
    return -1;
296
}
297
#define T0(i) G_T0(i)
298
#define T1(i) G_T1(i)
299
#define T2(i) G_T2(i)
300
#define T3(i) G_T3(i)
301
#define TInv0(i) gen_TInvXi(0, i)
302
#define TInv1(i) gen_TInvXi(1, i)
303
#define TInv2(i) gen_TInvXi(2, i)
304
#define TInv3(i) gen_TInvXi(3, i)
305
#define IMXC0(b) G_IMXC0(b)
306
#define IMXC1(b) G_IMXC1(b)
307
#define IMXC2(b) G_IMXC2(b)
308
#define IMXC3(b) G_IMXC3(b)
309
#else /* RIJNDAEL_GENERATE_VALUES_MACRO */
310
/* generate values for the tables with macros */
311
#define T0(i) G_T0(i)
312
#define T1(i) G_T1(i)
313
#define T2(i) G_T2(i)
314
#define T3(i) G_T3(i)
315
#define TInv0(i) G_TInv0(i)
316
#define TInv1(i) G_TInv1(i)
317
#define TInv2(i) G_TInv2(i)
318
#define TInv3(i) G_TInv3(i)
319
#define IMXC0(b) G_IMXC0(b)
320
#define IMXC1(b) G_IMXC1(b)
321
#define IMXC2(b) G_IMXC2(b)
322
#define IMXC3(b) G_IMXC3(b)
323
#endif /* choose T-table indexing method */
324
325
#endif /* not RIJNDAEL_INCLUDE_TABLES */
326
327
/**************************************************************************
328
 *
329
 * Stuff related to the Rijndael key schedule
330
 *
331
 *************************************************************************/
332
333
#define SUBBYTE(w)                                \
334
51
    ((((PRUint32)SBOX((w >> 24) & 0xff)) << 24) | \
335
51
     (((PRUint32)SBOX((w >> 16) & 0xff)) << 16) | \
336
51
     (((PRUint32)SBOX((w >> 8) & 0xff)) << 8) |   \
337
51
     (((PRUint32)SBOX((w)&0xff))))
338
339
#ifdef IS_LITTLE_ENDIAN
340
#define ROTBYTE(b) \
341
    ((b >> 8) | (b << 24))
342
#else
343
#define ROTBYTE(b) \
344
    ((b << 8) | (b >> 24))
345
#endif
346
347
/* rijndael_key_expansion7
348
 *
349
 * Generate the expanded key from the key input by the user.
350
 * XXX
351
 * Nk == 7 (224 key bits) is a weird case.  Since Nk > 6, an added SubByte
352
 * transformation is done periodically.  The period is every 4 bytes, and
353
 * since 7%4 != 0 this happens at different times for each key word (unlike
354
 * Nk == 8 where it happens twice in every key word, in the same positions).
355
 * For now, I'm implementing this case "dumbly", w/o any unrolling.
356
 */
357
static void
358
rijndael_key_expansion7(AESContext *cx, const unsigned char *key, unsigned int Nk)
359
0
{
360
0
    unsigned int i;
361
0
    PRUint32 *W;
362
0
    PRUint32 *pW;
363
0
    PRUint32 tmp;
364
0
    W = cx->k.expandedKey;
365
    /* 1.  the first Nk words contain the cipher key */
366
0
    memcpy(W, key, Nk * 4);
367
0
    i = Nk;
368
    /* 2.  loop until full expanded key is obtained */
369
0
    pW = W + i - 1;
370
0
    for (; i < cx->Nb * (cx->Nr + 1); ++i) {
371
0
        tmp = *pW++;
372
0
        if (i % Nk == 0)
373
0
            tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
374
0
        else if (i % Nk == 4)
375
0
            tmp = SUBBYTE(tmp);
376
0
        *pW = W[i - Nk] ^ tmp;
377
0
    }
378
0
}
379
380
/* rijndael_key_expansion
381
 *
382
 * Generate the expanded key from the key input by the user.
383
 */
384
static void
385
rijndael_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
386
5
{
387
5
    unsigned int i;
388
5
    PRUint32 *W;
389
5
    PRUint32 *pW;
390
5
    PRUint32 tmp;
391
5
    unsigned int round_key_words = cx->Nb * (cx->Nr + 1);
392
5
    if (Nk == 7) {
393
0
        rijndael_key_expansion7(cx, key, Nk);
394
0
        return;
395
0
    }
396
5
    W = cx->k.expandedKey;
397
    /* The first Nk words contain the input cipher key */
398
5
    memcpy(W, key, Nk * 4);
399
5
    i = Nk;
400
5
    pW = W + i - 1;
401
    /* Loop over all sets of Nk words, except the last */
402
45
    while (i < round_key_words - Nk) {
403
40
        tmp = *pW++;
404
40
        tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
405
40
        *pW = W[i++ - Nk] ^ tmp;
406
40
        tmp = *pW++;
407
40
        *pW = W[i++ - Nk] ^ tmp;
408
40
        tmp = *pW++;
409
40
        *pW = W[i++ - Nk] ^ tmp;
410
40
        tmp = *pW++;
411
40
        *pW = W[i++ - Nk] ^ tmp;
412
40
        if (Nk == 4)
413
27
            continue;
414
13
        switch (Nk) {
415
6
            case 8:
416
6
                tmp = *pW++;
417
6
                tmp = SUBBYTE(tmp);
418
6
                *pW = W[i++ - Nk] ^ tmp;
419
6
            case 7:
420
6
                tmp = *pW++;
421
6
                *pW = W[i++ - Nk] ^ tmp;
422
13
            case 6:
423
13
                tmp = *pW++;
424
13
                *pW = W[i++ - Nk] ^ tmp;
425
13
            case 5:
426
13
                tmp = *pW++;
427
13
                *pW = W[i++ - Nk] ^ tmp;
428
13
        }
429
13
    }
430
    /* Generate the last word */
431
5
    tmp = *pW++;
432
5
    tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
433
5
    *pW = W[i++ - Nk] ^ tmp;
434
    /* There may be overflow here, if Nk % (Nb * (Nr + 1)) > 0.  However,
435
     * since the above loop generated all but the last Nk key words, there
436
     * is no more need for the SubByte transformation.
437
     */
438
5
    if (Nk < 8) {
439
16
        for (; i < round_key_words; ++i) {
440
12
            tmp = *pW++;
441
12
            *pW = W[i - Nk] ^ tmp;
442
12
        }
443
4
    } else {
444
        /* except in the case when Nk == 8.  Then one more SubByte may have
445
         * to be performed, at i % Nk == 4.
446
         */
447
4
        for (; i < round_key_words; ++i) {
448
3
            tmp = *pW++;
449
3
            if (i % Nk == 4)
450
0
                tmp = SUBBYTE(tmp);
451
3
            *pW = W[i - Nk] ^ tmp;
452
3
        }
453
1
    }
454
5
}
455
456
/* rijndael_invkey_expansion
457
 *
458
 * Generate the expanded key for the inverse cipher from the key input by
459
 * the user.
460
 */
461
static void
462
rijndael_invkey_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
463
4
{
464
4
    unsigned int r;
465
4
    PRUint32 *roundkeyw;
466
4
    PRUint8 *b;
467
4
    int Nb = cx->Nb;
468
    /* begins like usual key expansion ... */
469
4
    rijndael_key_expansion(cx, key, Nk);
470
    /* ... but has the additional step of InvMixColumn,
471
     * excepting the first and last round keys.
472
     */
473
4
    roundkeyw = cx->k.expandedKey + cx->Nb;
474
46
    for (r = 1; r < cx->Nr; ++r) {
475
        /* each key word, roundkeyw, represents a column in the key
476
         * matrix.  Each column is multiplied by the InvMixColumn matrix.
477
         *   [ 0E 0B 0D 09 ]   [ b0 ]
478
         *   [ 09 0E 0B 0D ] * [ b1 ]
479
         *   [ 0D 09 0E 0B ]   [ b2 ]
480
         *   [ 0B 0D 09 0E ]   [ b3 ]
481
         */
482
42
        b = (PRUint8 *)roundkeyw;
483
42
        *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
484
42
        b = (PRUint8 *)roundkeyw;
485
42
        *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
486
42
        b = (PRUint8 *)roundkeyw;
487
42
        *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
488
42
        b = (PRUint8 *)roundkeyw;
489
42
        *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
490
42
        if (Nb <= 4)
491
42
            continue;
492
0
        switch (Nb) {
493
0
            case 8:
494
0
                b = (PRUint8 *)roundkeyw;
495
0
                *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
496
0
                               IMXC2(b[2]) ^ IMXC3(b[3]);
497
0
            case 7:
498
0
                b = (PRUint8 *)roundkeyw;
499
0
                *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
500
0
                               IMXC2(b[2]) ^ IMXC3(b[3]);
501
0
            case 6:
502
0
                b = (PRUint8 *)roundkeyw;
503
0
                *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
504
0
                               IMXC2(b[2]) ^ IMXC3(b[3]);
505
0
            case 5:
506
0
                b = (PRUint8 *)roundkeyw;
507
0
                *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
508
0
                               IMXC2(b[2]) ^ IMXC3(b[3]);
509
0
        }
510
0
    }
511
4
}
512
513
/**************************************************************************
514
 *
515
 * Stuff related to Rijndael encryption/decryption.
516
 *
517
 *************************************************************************/
518
519
#ifdef IS_LITTLE_ENDIAN
520
0
#define BYTE0WORD(w) ((w)&0x000000ff)
521
0
#define BYTE1WORD(w) ((w)&0x0000ff00)
522
0
#define BYTE2WORD(w) ((w)&0x00ff0000)
523
0
#define BYTE3WORD(w) ((w)&0xff000000)
524
#else
525
#define BYTE0WORD(w) ((w)&0xff000000)
526
#define BYTE1WORD(w) ((w)&0x00ff0000)
527
#define BYTE2WORD(w) ((w)&0x0000ff00)
528
#define BYTE3WORD(w) ((w)&0x000000ff)
529
#endif
530
531
typedef union {
532
    PRUint32 w[4];
533
    PRUint8 b[16];
534
} rijndael_state;
535
536
0
#define COLUMN_0(state) state.w[0]
537
0
#define COLUMN_1(state) state.w[1]
538
0
#define COLUMN_2(state) state.w[2]
539
0
#define COLUMN_3(state) state.w[3]
540
541
#define STATE_BYTE(i) state.b[i]
542
543
// out = a ^ b
544
inline static void
545
xorBlock(unsigned char *out, const unsigned char *a, const unsigned char *b)
546
0
{
547
0
    for (unsigned int j = 0; j < AES_BLOCK_SIZE; ++j) {
548
0
        (out)[j] = (a)[j] ^ (b)[j];
549
0
    }
550
0
}
551
552
static void NO_SANITIZE_ALIGNMENT
553
rijndael_encryptBlock128(AESContext *cx,
554
                         unsigned char *output,
555
                         const unsigned char *input)
556
0
{
557
0
    unsigned int r;
558
0
    PRUint32 *roundkeyw;
559
0
    rijndael_state state;
560
0
    PRUint32 C0, C1, C2, C3;
561
0
#if defined(NSS_X86_OR_X64)
562
0
#define pIn input
563
0
#define pOut output
564
#else
565
    unsigned char *pIn, *pOut;
566
    PRUint32 inBuf[4], outBuf[4];
567
568
    if ((ptrdiff_t)input & 0x3) {
569
        memcpy(inBuf, input, sizeof inBuf);
570
        pIn = (unsigned char *)inBuf;
571
    } else {
572
        pIn = (unsigned char *)input;
573
    }
574
    if ((ptrdiff_t)output & 0x3) {
575
        pOut = (unsigned char *)outBuf;
576
    } else {
577
        pOut = (unsigned char *)output;
578
    }
579
#endif
580
0
    roundkeyw = cx->k.expandedKey;
581
    /* Step 1: Add Round Key 0 to initial state */
582
0
    COLUMN_0(state) = *((PRUint32 *)(pIn)) ^ *roundkeyw++;
583
0
    COLUMN_1(state) = *((PRUint32 *)(pIn + 4)) ^ *roundkeyw++;
584
0
    COLUMN_2(state) = *((PRUint32 *)(pIn + 8)) ^ *roundkeyw++;
585
0
    COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw++;
586
    /* Step 2: Loop over rounds [1..NR-1] */
587
0
    for (r = 1; r < cx->Nr; ++r) {
588
        /* Do ShiftRow, ByteSub, and MixColumn all at once */
589
0
        C0 = T0(STATE_BYTE(0)) ^
590
0
             T1(STATE_BYTE(5)) ^
591
0
             T2(STATE_BYTE(10)) ^
592
0
             T3(STATE_BYTE(15));
593
0
        C1 = T0(STATE_BYTE(4)) ^
594
0
             T1(STATE_BYTE(9)) ^
595
0
             T2(STATE_BYTE(14)) ^
596
0
             T3(STATE_BYTE(3));
597
0
        C2 = T0(STATE_BYTE(8)) ^
598
0
             T1(STATE_BYTE(13)) ^
599
0
             T2(STATE_BYTE(2)) ^
600
0
             T3(STATE_BYTE(7));
601
0
        C3 = T0(STATE_BYTE(12)) ^
602
0
             T1(STATE_BYTE(1)) ^
603
0
             T2(STATE_BYTE(6)) ^
604
0
             T3(STATE_BYTE(11));
605
        /* Round key addition */
606
0
        COLUMN_0(state) = C0 ^ *roundkeyw++;
607
0
        COLUMN_1(state) = C1 ^ *roundkeyw++;
608
0
        COLUMN_2(state) = C2 ^ *roundkeyw++;
609
0
        COLUMN_3(state) = C3 ^ *roundkeyw++;
610
0
    }
611
    /* Step 3: Do the last round */
612
    /* Final round does not employ MixColumn */
613
0
    C0 = ((BYTE0WORD(T2(STATE_BYTE(0)))) |
614
0
          (BYTE1WORD(T3(STATE_BYTE(5)))) |
615
0
          (BYTE2WORD(T0(STATE_BYTE(10)))) |
616
0
          (BYTE3WORD(T1(STATE_BYTE(15))))) ^
617
0
         *roundkeyw++;
618
0
    C1 = ((BYTE0WORD(T2(STATE_BYTE(4)))) |
619
0
          (BYTE1WORD(T3(STATE_BYTE(9)))) |
620
0
          (BYTE2WORD(T0(STATE_BYTE(14)))) |
621
0
          (BYTE3WORD(T1(STATE_BYTE(3))))) ^
622
0
         *roundkeyw++;
623
0
    C2 = ((BYTE0WORD(T2(STATE_BYTE(8)))) |
624
0
          (BYTE1WORD(T3(STATE_BYTE(13)))) |
625
0
          (BYTE2WORD(T0(STATE_BYTE(2)))) |
626
0
          (BYTE3WORD(T1(STATE_BYTE(7))))) ^
627
0
         *roundkeyw++;
628
0
    C3 = ((BYTE0WORD(T2(STATE_BYTE(12)))) |
629
0
          (BYTE1WORD(T3(STATE_BYTE(1)))) |
630
0
          (BYTE2WORD(T0(STATE_BYTE(6)))) |
631
0
          (BYTE3WORD(T1(STATE_BYTE(11))))) ^
632
0
         *roundkeyw++;
633
0
    *((PRUint32 *)pOut) = C0;
634
0
    *((PRUint32 *)(pOut + 4)) = C1;
635
0
    *((PRUint32 *)(pOut + 8)) = C2;
636
0
    *((PRUint32 *)(pOut + 12)) = C3;
637
0
#if defined(NSS_X86_OR_X64)
638
0
#undef pIn
639
0
#undef pOut
640
#else
641
    if ((ptrdiff_t)output & 0x3) {
642
        memcpy(output, outBuf, sizeof outBuf);
643
    }
644
#endif
645
0
}
646
647
static void NO_SANITIZE_ALIGNMENT
648
rijndael_decryptBlock128(AESContext *cx,
649
                         unsigned char *output,
650
                         const unsigned char *input)
651
0
{
652
0
    int r;
653
0
    PRUint32 *roundkeyw;
654
0
    rijndael_state state;
655
0
    PRUint32 C0, C1, C2, C3;
656
0
#if defined(NSS_X86_OR_X64)
657
0
#define pIn input
658
0
#define pOut output
659
#else
660
    unsigned char *pIn, *pOut;
661
    PRUint32 inBuf[4], outBuf[4];
662
663
    if ((ptrdiff_t)input & 0x3) {
664
        memcpy(inBuf, input, sizeof inBuf);
665
        pIn = (unsigned char *)inBuf;
666
    } else {
667
        pIn = (unsigned char *)input;
668
    }
669
    if ((ptrdiff_t)output & 0x3) {
670
        pOut = (unsigned char *)outBuf;
671
    } else {
672
        pOut = (unsigned char *)output;
673
    }
674
#endif
675
0
    roundkeyw = cx->k.expandedKey + cx->Nb * cx->Nr + 3;
676
    /* reverse the final key addition */
677
0
    COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw--;
678
0
    COLUMN_2(state) = *((PRUint32 *)(pIn + 8)) ^ *roundkeyw--;
679
0
    COLUMN_1(state) = *((PRUint32 *)(pIn + 4)) ^ *roundkeyw--;
680
0
    COLUMN_0(state) = *((PRUint32 *)(pIn)) ^ *roundkeyw--;
681
    /* Loop over rounds in reverse [NR..1] */
682
0
    for (r = cx->Nr; r > 1; --r) {
683
        /* Invert the (InvByteSub*InvMixColumn)(InvShiftRow(state)) */
684
0
        C0 = TInv0(STATE_BYTE(0)) ^
685
0
             TInv1(STATE_BYTE(13)) ^
686
0
             TInv2(STATE_BYTE(10)) ^
687
0
             TInv3(STATE_BYTE(7));
688
0
        C1 = TInv0(STATE_BYTE(4)) ^
689
0
             TInv1(STATE_BYTE(1)) ^
690
0
             TInv2(STATE_BYTE(14)) ^
691
0
             TInv3(STATE_BYTE(11));
692
0
        C2 = TInv0(STATE_BYTE(8)) ^
693
0
             TInv1(STATE_BYTE(5)) ^
694
0
             TInv2(STATE_BYTE(2)) ^
695
0
             TInv3(STATE_BYTE(15));
696
0
        C3 = TInv0(STATE_BYTE(12)) ^
697
0
             TInv1(STATE_BYTE(9)) ^
698
0
             TInv2(STATE_BYTE(6)) ^
699
0
             TInv3(STATE_BYTE(3));
700
        /* Invert the key addition step */
701
0
        COLUMN_3(state) = C3 ^ *roundkeyw--;
702
0
        COLUMN_2(state) = C2 ^ *roundkeyw--;
703
0
        COLUMN_1(state) = C1 ^ *roundkeyw--;
704
0
        COLUMN_0(state) = C0 ^ *roundkeyw--;
705
0
    }
706
    /* inverse sub */
707
0
    pOut[0] = SINV(STATE_BYTE(0));
708
0
    pOut[1] = SINV(STATE_BYTE(13));
709
0
    pOut[2] = SINV(STATE_BYTE(10));
710
0
    pOut[3] = SINV(STATE_BYTE(7));
711
0
    pOut[4] = SINV(STATE_BYTE(4));
712
0
    pOut[5] = SINV(STATE_BYTE(1));
713
0
    pOut[6] = SINV(STATE_BYTE(14));
714
0
    pOut[7] = SINV(STATE_BYTE(11));
715
0
    pOut[8] = SINV(STATE_BYTE(8));
716
0
    pOut[9] = SINV(STATE_BYTE(5));
717
0
    pOut[10] = SINV(STATE_BYTE(2));
718
0
    pOut[11] = SINV(STATE_BYTE(15));
719
0
    pOut[12] = SINV(STATE_BYTE(12));
720
0
    pOut[13] = SINV(STATE_BYTE(9));
721
0
    pOut[14] = SINV(STATE_BYTE(6));
722
0
    pOut[15] = SINV(STATE_BYTE(3));
723
    /* final key addition */
724
0
    *((PRUint32 *)(pOut + 12)) ^= *roundkeyw--;
725
0
    *((PRUint32 *)(pOut + 8)) ^= *roundkeyw--;
726
0
    *((PRUint32 *)(pOut + 4)) ^= *roundkeyw--;
727
0
    *((PRUint32 *)pOut) ^= *roundkeyw--;
728
0
#if defined(NSS_X86_OR_X64)
729
0
#undef pIn
730
0
#undef pOut
731
#else
732
    if ((ptrdiff_t)output & 0x3) {
733
        memcpy(output, outBuf, sizeof outBuf);
734
    }
735
#endif
736
0
}
737
738
/**************************************************************************
739
 *
740
 *  Rijndael modes of operation (ECB and CBC)
741
 *
742
 *************************************************************************/
743
744
static SECStatus
745
rijndael_encryptECB(AESContext *cx, unsigned char *output,
746
                    unsigned int *outputLen, unsigned int maxOutputLen,
747
                    const unsigned char *input, unsigned int inputLen, unsigned int blocksize)
748
770
{
749
770
    PORT_Assert(blocksize == AES_BLOCK_SIZE);
750
770
    PRBool aesni = aesni_support();
751
1.54k
    while (inputLen > 0) {
752
770
        if (aesni) {
753
770
            rijndael_native_encryptBlock(cx, output, input);
754
770
        } else {
755
0
            rijndael_encryptBlock128(cx, output, input);
756
0
        }
757
770
        output += AES_BLOCK_SIZE;
758
770
        input += AES_BLOCK_SIZE;
759
770
        inputLen -= AES_BLOCK_SIZE;
760
770
    }
761
770
    return SECSuccess;
762
770
}
763
764
static SECStatus
765
rijndael_encryptCBC(AESContext *cx, unsigned char *output,
766
                    unsigned int *outputLen, unsigned int maxOutputLen,
767
                    const unsigned char *input, unsigned int inputLen, unsigned int blocksize)
768
0
{
769
0
    PORT_Assert(blocksize == AES_BLOCK_SIZE);
770
0
    unsigned char *lastblock = cx->iv;
771
0
    unsigned char inblock[AES_BLOCK_SIZE * 8];
772
0
    PRBool aesni = aesni_support();
773
774
0
    if (!inputLen)
775
0
        return SECSuccess;
776
0
    while (inputLen > 0) {
777
0
        if (aesni) {
778
            /* XOR with the last block (IV if first block) */
779
0
            native_xorBlock(inblock, input, lastblock);
780
            /* encrypt */
781
0
            rijndael_native_encryptBlock(cx, output, inblock);
782
0
        } else {
783
0
            xorBlock(inblock, input, lastblock);
784
0
            rijndael_encryptBlock128(cx, output, inblock);
785
0
        }
786
787
        /* move to the next block */
788
0
        lastblock = output;
789
0
        output += AES_BLOCK_SIZE;
790
0
        input += AES_BLOCK_SIZE;
791
0
        inputLen -= AES_BLOCK_SIZE;
792
0
    }
793
0
    memcpy(cx->iv, lastblock, AES_BLOCK_SIZE);
794
0
    return SECSuccess;
795
0
}
796
797
static SECStatus
798
rijndael_decryptECB(AESContext *cx, unsigned char *output,
799
                    unsigned int *outputLen, unsigned int maxOutputLen,
800
                    const unsigned char *input, unsigned int inputLen, unsigned int blocksize)
801
0
{
802
0
    PORT_Assert(blocksize == AES_BLOCK_SIZE);
803
0
    PRBool aesni = aesni_support();
804
0
    while (inputLen > 0) {
805
0
        if (aesni) {
806
0
            rijndael_native_decryptBlock(cx, output, input);
807
0
        } else {
808
0
            rijndael_decryptBlock128(cx, output, input);
809
0
        }
810
0
        output += AES_BLOCK_SIZE;
811
0
        input += AES_BLOCK_SIZE;
812
0
        inputLen -= AES_BLOCK_SIZE;
813
0
    }
814
0
    return SECSuccess;
815
0
}
816
817
static SECStatus
818
rijndael_decryptCBC(AESContext *cx, unsigned char *output,
819
                    unsigned int *outputLen, unsigned int maxOutputLen,
820
                    const unsigned char *input, unsigned int inputLen, unsigned int blocksize)
821
0
{
822
0
    PORT_Assert(blocksize == AES_BLOCK_SIZE);
823
0
    const unsigned char *in;
824
0
    unsigned char *out;
825
0
    unsigned char newIV[AES_BLOCK_SIZE];
826
0
    PRBool aesni = aesni_support();
827
828
0
    if (!inputLen)
829
0
        return SECSuccess;
830
0
    PORT_Assert(output - input >= 0 || input - output >= (int)inputLen);
831
0
    in = input + (inputLen - AES_BLOCK_SIZE);
832
0
    memcpy(newIV, in, AES_BLOCK_SIZE);
833
0
    out = output + (inputLen - AES_BLOCK_SIZE);
834
0
    while (inputLen > AES_BLOCK_SIZE) {
835
0
        if (aesni) {
836
            // Use hardware acceleration for normal AES parameters.
837
0
            rijndael_native_decryptBlock(cx, out, in);
838
0
            native_xorBlock(out, out, &in[-AES_BLOCK_SIZE]);
839
0
        } else {
840
0
            rijndael_decryptBlock128(cx, out, in);
841
0
            xorBlock(out, out, &in[-AES_BLOCK_SIZE]);
842
0
        }
843
0
        out -= AES_BLOCK_SIZE;
844
0
        in -= AES_BLOCK_SIZE;
845
0
        inputLen -= AES_BLOCK_SIZE;
846
0
    }
847
0
    if (in == input) {
848
0
        if (aesni) {
849
0
            rijndael_native_decryptBlock(cx, out, in);
850
0
            native_xorBlock(out, out, cx->iv);
851
0
        } else {
852
0
            rijndael_decryptBlock128(cx, out, in);
853
0
            xorBlock(out, out, cx->iv);
854
0
        }
855
0
    }
856
0
    memcpy(cx->iv, newIV, AES_BLOCK_SIZE);
857
0
    return SECSuccess;
858
0
}
859
860
#define FREEBL_CIPHER_WRAP(ctxtype, mmm)                                                    \
861
    static SECStatus freeblCipher_##mmm(void *vctx, unsigned char *output,                  \
862
                                        unsigned int *outputLen, unsigned int maxOutputLen, \
863
                                        const unsigned char *input, unsigned int inputLen,  \
864
                                        unsigned int blocksize)                             \
865
771
    {                                                                                       \
866
771
        ctxtype *ctx = vctx;                                                                \
867
771
        return mmm(ctx, output, outputLen, maxOutputLen, input, inputLen, blocksize);       \
868
771
    }
Unexecuted instantiation: rijndael.c:freeblCipher_rijndael_encryptCBC
Unexecuted instantiation: rijndael.c:freeblCipher_rijndael_decryptCBC
rijndael.c:freeblCipher_rijndael_encryptECB
Line
Count
Source
865
770
    {                                                                                       \
866
770
        ctxtype *ctx = vctx;                                                                \
867
770
        return mmm(ctx, output, outputLen, maxOutputLen, input, inputLen, blocksize);       \
868
770
    }
Unexecuted instantiation: rijndael.c:freeblCipher_rijndael_decryptECB
Unexecuted instantiation: rijndael.c:freeblCipher_CTS_EncryptUpdate
Unexecuted instantiation: rijndael.c:freeblCipher_CTS_DecryptUpdate
Unexecuted instantiation: rijndael.c:freeblCipher_GCM_EncryptUpdate
rijndael.c:freeblCipher_GCM_DecryptUpdate
Line
Count
Source
865
1
    {                                                                                       \
866
1
        ctxtype *ctx = vctx;                                                                \
867
1
        return mmm(ctx, output, outputLen, maxOutputLen, input, inputLen, blocksize);       \
868
1
    }
Unexecuted instantiation: rijndael.c:freeblCipher_CTR_Update
869
870
FREEBL_CIPHER_WRAP(CTRContext, CTR_Update);
871
FREEBL_CIPHER_WRAP(CTSContext, CTS_DecryptUpdate);
872
FREEBL_CIPHER_WRAP(CTSContext, CTS_EncryptUpdate);
873
FREEBL_CIPHER_WRAP(GCMContext, GCM_DecryptUpdate);
874
FREEBL_CIPHER_WRAP(GCMContext, GCM_EncryptUpdate);
875
FREEBL_CIPHER_WRAP(AESContext, rijndael_decryptCBC);
876
FREEBL_CIPHER_WRAP(AESContext, rijndael_decryptECB);
877
FREEBL_CIPHER_WRAP(AESContext, rijndael_encryptCBC);
878
FREEBL_CIPHER_WRAP(AESContext, rijndael_encryptECB);
879
880
#if defined(INTEL_GCM) && defined(USE_HW_AES)
881
FREEBL_CIPHER_WRAP(intel_AES_GCMContext, intel_AES_GCM_DecryptUpdate);
882
FREEBL_CIPHER_WRAP(intel_AES_GCMContext, intel_AES_GCM_EncryptUpdate);
883
#elif defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
884
FREEBL_CIPHER_WRAP(ppc_AES_GCMContext, ppc_AES_GCM_DecryptUpdate);
885
FREEBL_CIPHER_WRAP(ppc_AES_GCMContext, ppc_AES_GCM_EncryptUpdate);
886
#endif
887
888
#if defined(USE_HW_AES)
889
#if defined(NSS_X86_OR_X64)
890
FREEBL_CIPHER_WRAP(AESContext, intel_aes_encrypt_ecb_128);
891
FREEBL_CIPHER_WRAP(AESContext, intel_aes_decrypt_ecb_128);
892
FREEBL_CIPHER_WRAP(AESContext, intel_aes_encrypt_cbc_128);
893
FREEBL_CIPHER_WRAP(AESContext, intel_aes_decrypt_cbc_128);
894
FREEBL_CIPHER_WRAP(AESContext, intel_aes_encrypt_ecb_192);
895
FREEBL_CIPHER_WRAP(AESContext, intel_aes_decrypt_ecb_192);
896
FREEBL_CIPHER_WRAP(AESContext, intel_aes_encrypt_cbc_192);
897
FREEBL_CIPHER_WRAP(AESContext, intel_aes_decrypt_cbc_192);
898
FREEBL_CIPHER_WRAP(AESContext, intel_aes_encrypt_ecb_256);
899
FREEBL_CIPHER_WRAP(AESContext, intel_aes_decrypt_ecb_256);
900
FREEBL_CIPHER_WRAP(AESContext, intel_aes_encrypt_cbc_256);
901
FREEBL_CIPHER_WRAP(AESContext, intel_aes_decrypt_cbc_256);
902
903
#define freeblCipher_native_aes_ecb_worker(encrypt, keysize)            \
904
    ((encrypt)                                                          \
905
         ? ((keysize) == 16   ? freeblCipher_intel_aes_encrypt_ecb_128  \
906
            : (keysize) == 24 ? freeblCipher_intel_aes_encrypt_ecb_192  \
907
                              : freeblCipher_intel_aes_encrypt_ecb_256) \
908
         : ((keysize) == 16   ? freeblCipher_intel_aes_decrypt_ecb_128  \
909
            : (keysize) == 24 ? freeblCipher_intel_aes_decrypt_ecb_192  \
910
                              : freeblCipher_intel_aes_decrypt_ecb_256))
911
912
#define freeblCipher_native_aes_cbc_worker(encrypt, keysize)            \
913
    ((encrypt)                                                          \
914
         ? ((keysize) == 16   ? freeblCipher_intel_aes_encrypt_cbc_128  \
915
            : (keysize) == 24 ? freeblCipher_intel_aes_encrypt_cbc_192  \
916
                              : freeblCipher_intel_aes_encrypt_cbc_256) \
917
         : ((keysize) == 16   ? freeblCipher_intel_aes_decrypt_cbc_128  \
918
            : (keysize) == 24 ? freeblCipher_intel_aes_decrypt_cbc_192  \
919
                              : freeblCipher_intel_aes_decrypt_cbc_256))
920
#else
921
FREEBL_CIPHER_WRAP(AESContext, arm_aes_encrypt_ecb_128);
922
FREEBL_CIPHER_WRAP(AESContext, arm_aes_decrypt_ecb_128);
923
FREEBL_CIPHER_WRAP(AESContext, arm_aes_encrypt_cbc_128);
924
FREEBL_CIPHER_WRAP(AESContext, arm_aes_decrypt_cbc_128);
925
FREEBL_CIPHER_WRAP(AESContext, arm_aes_encrypt_ecb_192);
926
FREEBL_CIPHER_WRAP(AESContext, arm_aes_decrypt_ecb_192);
927
FREEBL_CIPHER_WRAP(AESContext, arm_aes_encrypt_cbc_192);
928
FREEBL_CIPHER_WRAP(AESContext, arm_aes_decrypt_cbc_192);
929
FREEBL_CIPHER_WRAP(AESContext, arm_aes_encrypt_ecb_256);
930
FREEBL_CIPHER_WRAP(AESContext, arm_aes_decrypt_ecb_256);
931
FREEBL_CIPHER_WRAP(AESContext, arm_aes_encrypt_cbc_256);
932
FREEBL_CIPHER_WRAP(AESContext, arm_aes_decrypt_cbc_256);
933
934
#define freeblCipher_native_aes_ecb_worker(encrypt, keysize)          \
935
    ((encrypt)                                                        \
936
         ? ((keysize) == 16   ? freeblCipher_arm_aes_encrypt_ecb_128  \
937
            : (keysize) == 24 ? freeblCipher_arm_aes_encrypt_ecb_192  \
938
                              : freeblCipher_arm_aes_encrypt_ecb_256) \
939
         : ((keysize) == 16   ? freeblCipher_arm_aes_decrypt_ecb_128  \
940
            : (keysize) == 24 ? freeblCipher_arm_aes_decrypt_ecb_192  \
941
                              : freeblCipher_arm_aes_decrypt_ecb_256))
942
943
#define freeblCipher_native_aes_cbc_worker(encrypt, keysize)          \
944
    ((encrypt)                                                        \
945
         ? ((keysize) == 16   ? freeblCipher_arm_aes_encrypt_cbc_128  \
946
            : (keysize) == 24 ? freeblCipher_arm_aes_encrypt_cbc_192  \
947
                              : freeblCipher_arm_aes_encrypt_cbc_256) \
948
         : ((keysize) == 16   ? freeblCipher_arm_aes_decrypt_cbc_128  \
949
            : (keysize) == 24 ? freeblCipher_arm_aes_decrypt_cbc_192  \
950
                              : freeblCipher_arm_aes_decrypt_cbc_256))
951
#endif
952
#endif
953
954
#if defined(USE_HW_AES) && defined(_MSC_VER) && defined(NSS_X86_OR_X64)
955
FREEBL_CIPHER_WRAP(CTRContext, CTR_Update_HW_AES);
956
#endif
957
958
#define FREEBL_AEAD_WRAP(ctxtype, mmm)                                                                                \
959
    static SECStatus freeblAead_##mmm(void *vctx, unsigned char *output,                                              \
960
                                      unsigned int *outputLen, unsigned int maxOutputLen,                             \
961
                                      const unsigned char *input, unsigned int inputLen,                              \
962
                                      void *params, unsigned int paramsLen,                                           \
963
                                      const unsigned char *aad, unsigned int aadLen,                                  \
964
                                      unsigned int blocksize)                                                         \
965
0
    {                                                                                                                 \
966
0
        ctxtype *ctx = vctx;                                                                                          \
967
0
        return mmm(ctx, output, outputLen, maxOutputLen, input, inputLen, params, paramsLen, aad, aadLen, blocksize); \
968
0
    }
Unexecuted instantiation: rijndael.c:freeblAead_GCM_EncryptAEAD
Unexecuted instantiation: rijndael.c:freeblAead_GCM_DecryptAEAD
969
970
FREEBL_AEAD_WRAP(GCMContext, GCM_EncryptAEAD);
971
FREEBL_AEAD_WRAP(GCMContext, GCM_DecryptAEAD);
972
973
#if defined(INTEL_GCM) && defined(USE_HW_AES)
974
FREEBL_AEAD_WRAP(intel_AES_GCMContext, intel_AES_GCM_EncryptAEAD);
975
FREEBL_AEAD_WRAP(intel_AES_GCMContext, intel_AES_GCM_DecryptAEAD);
976
#elif defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
977
FREEBL_AEAD_WRAP(ppc_AES_GCMContext, ppc_AES_GCM_EncryptAEAD);
978
FREEBL_AEAD_WRAP(ppc_AES_GCMContext, ppc_AES_GCM_DecryptAEAD);
979
#endif
980
981
#define FREEBL_DESTROY_WRAP(ctxtype, mmm)                      \
982
    static void freeblDestroy_##mmm(void *vctx, PRBool freeit) \
983
1
    {                                                          \
984
1
        ctxtype *ctx = vctx;                                   \
985
1
        mmm(ctx, freeit);                                      \
986
1
    }
Unexecuted instantiation: rijndael.c:freeblDestroy_CTS_DestroyContext
rijndael.c:freeblDestroy_GCM_DestroyContext
Line
Count
Source
983
1
    {                                                          \
984
1
        ctxtype *ctx = vctx;                                   \
985
1
        mmm(ctx, freeit);                                      \
986
1
    }
Unexecuted instantiation: rijndael.c:freeblDestroy_CTR_DestroyContext
987
988
FREEBL_DESTROY_WRAP(CTRContext, CTR_DestroyContext);
989
FREEBL_DESTROY_WRAP(CTSContext, CTS_DestroyContext);
990
FREEBL_DESTROY_WRAP(GCMContext, GCM_DestroyContext);
991
992
#if defined(INTEL_GCM) && defined(USE_HW_AES)
993
FREEBL_DESTROY_WRAP(intel_AES_GCMContext, intel_AES_GCM_DestroyContext);
994
#elif defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
995
FREEBL_DESTROY_WRAP(ppc_AES_GCMContext, ppc_AES_GCM_DestroyContext);
996
#endif
997
998
/************************************************************************
999
 *
1000
 * BLAPI Interface functions
1001
 *
1002
 * The following functions implement the encryption routines defined in
1003
 * BLAPI for the AES cipher, Rijndael.
1004
 *
1005
 ***********************************************************************/
1006
1007
AESContext *
1008
AES_AllocateContext(void)
1009
19
{
1010
19
    return PORT_ZNewAligned(AESContext, 16, mem);
1011
19
}
1012
1013
/*
1014
** Initialize a new AES context suitable for AES encryption/decryption in
1015
** the ECB or CBC mode.
1016
**  "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC
1017
*/
1018
static SECStatus
1019
aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
1020
                const unsigned char *iv, int mode, unsigned int encrypt)
1021
19
{
1022
19
    unsigned int Nk;
1023
19
    PRBool use_hw_aes;
1024
    /* According to AES, block lengths are 128 and key lengths are 128, 192, or
1025
     * 256 bits. We support other key sizes as well [128, 256] as long as the
1026
     * length in bytes is divisible by 4.
1027
     */
1028
1029
19
    if (key == NULL ||
1030
19
        keysize < AES_BLOCK_SIZE ||
1031
19
        keysize > 32 ||
1032
19
        keysize % 4 != 0) {
1033
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1034
0
        return SECFailure;
1035
0
    }
1036
19
    if (mode != NSS_AES && mode != NSS_AES_CBC) {
1037
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1038
0
        return SECFailure;
1039
0
    }
1040
19
    if (mode == NSS_AES_CBC && iv == NULL) {
1041
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1042
0
        return SECFailure;
1043
0
    }
1044
19
    if (!cx) {
1045
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1046
0
        return SECFailure;
1047
0
    }
1048
19
#if defined(NSS_X86_OR_X64) || defined(USE_HW_AES)
1049
19
    use_hw_aes = (aesni_support() || arm_aes_support()) && (keysize % 8) == 0;
1050
#else
1051
    use_hw_aes = PR_FALSE;
1052
#endif
1053
    /* Nb = (block size in bits) / 32 */
1054
19
    cx->Nb = AES_BLOCK_SIZE / 4;
1055
    /* Nk = (key size in bits) / 32 */
1056
19
    Nk = keysize / 4;
1057
    /* Obtain number of rounds from "table" */
1058
19
    cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb);
1059
    /* copy in the iv, if neccessary */
1060
19
    if (mode == NSS_AES_CBC) {
1061
2
        memcpy(cx->iv, iv, AES_BLOCK_SIZE);
1062
#ifdef USE_HW_AES
1063
        if (use_hw_aes) {
1064
            cx->worker = freeblCipher_native_aes_cbc_worker(encrypt, keysize);
1065
        } else
1066
#endif
1067
2
        {
1068
2
            cx->worker = encrypt ? freeblCipher_rijndael_encryptCBC : freeblCipher_rijndael_decryptCBC;
1069
2
        }
1070
17
    } else {
1071
#ifdef USE_HW_AES
1072
        if (use_hw_aes) {
1073
            cx->worker = freeblCipher_native_aes_ecb_worker(encrypt, keysize);
1074
        } else
1075
#endif
1076
17
        {
1077
17
            cx->worker = encrypt ? freeblCipher_rijndael_encryptECB : freeblCipher_rijndael_decryptECB;
1078
17
        }
1079
17
    }
1080
19
    PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE);
1081
19
    if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) {
1082
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1083
0
        return SECFailure;
1084
0
    }
1085
#ifdef USE_HW_AES
1086
    if (use_hw_aes) {
1087
        native_aes_init(encrypt, keysize);
1088
    } else
1089
#endif
1090
19
    {
1091
        /* Generate expanded key */
1092
19
        if (encrypt) {
1093
15
            if (use_hw_aes && (cx->mode == NSS_AES_GCM || cx->mode == NSS_AES ||
1094
15
                               cx->mode == NSS_AES_CTR)) {
1095
14
                PORT_Assert(keysize == 16 || keysize == 24 || keysize == 32);
1096
                /* Prepare hardware key for normal AES parameters. */
1097
14
                rijndael_native_key_expansion(cx, key, Nk);
1098
14
            } else {
1099
1
                rijndael_key_expansion(cx, key, Nk);
1100
1
            }
1101
15
        } else {
1102
4
            rijndael_invkey_expansion(cx, key, Nk);
1103
4
        }
1104
19
        BLAPI_CLEAR_STACK(256)
1105
19
    }
1106
19
    cx->worker_cx = cx;
1107
19
    cx->destroy = NULL;
1108
19
    cx->isBlock = PR_TRUE;
1109
19
    return SECSuccess;
1110
19
}
1111
1112
SECStatus
1113
AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
1114
                const unsigned char *iv, int mode, unsigned int encrypt,
1115
                unsigned int blocksize)
1116
19
{
1117
19
    int basemode = mode;
1118
19
    PRBool baseencrypt = encrypt;
1119
19
    SECStatus rv;
1120
1121
19
    if (blocksize != AES_BLOCK_SIZE) {
1122
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1123
0
        return SECFailure;
1124
0
    }
1125
1126
19
    switch (mode) {
1127
0
        case NSS_AES_CTS:
1128
0
            basemode = NSS_AES_CBC;
1129
0
            break;
1130
12
        case NSS_AES_GCM:
1131
12
        case NSS_AES_CTR:
1132
12
            basemode = NSS_AES;
1133
12
            baseencrypt = PR_TRUE;
1134
12
            break;
1135
19
    }
1136
    /* Make sure enough is initialized so we can safely call Destroy. */
1137
19
    cx->worker_cx = NULL;
1138
19
    cx->destroy = NULL;
1139
19
    cx->mode = mode;
1140
19
    rv = aes_InitContext(cx, key, keysize, iv, basemode, baseencrypt);
1141
19
    if (rv != SECSuccess) {
1142
0
        AES_DestroyContext(cx, PR_FALSE);
1143
0
        return rv;
1144
0
    }
1145
1146
    /* finally, set up any mode specific contexts */
1147
19
    cx->worker_aead = 0;
1148
19
    switch (mode) {
1149
0
        case NSS_AES_CTS:
1150
0
            cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv);
1151
0
            cx->worker = encrypt ? freeblCipher_CTS_EncryptUpdate : freeblCipher_CTS_DecryptUpdate;
1152
0
            cx->destroy = freeblDestroy_CTS_DestroyContext;
1153
0
            cx->isBlock = PR_FALSE;
1154
0
            break;
1155
12
        case NSS_AES_GCM:
1156
#if defined(INTEL_GCM) && defined(USE_HW_AES)
1157
            if (aesni_support() && (keysize % 8) == 0 && avx_support() &&
1158
                clmul_support()) {
1159
                cx->worker_cx = intel_AES_GCM_CreateContext(cx, cx->worker, iv);
1160
                cx->worker = encrypt ? freeblCipher_intel_AES_GCM_EncryptUpdate
1161
                                     : freeblCipher_intel_AES_GCM_DecryptUpdate;
1162
                cx->worker_aead = encrypt ? freeblAead_intel_AES_GCM_EncryptAEAD
1163
                                          : freeblAead_intel_AES_GCM_DecryptAEAD;
1164
                cx->destroy = freeblDestroy_intel_AES_GCM_DestroyContext;
1165
                cx->isBlock = PR_FALSE;
1166
            } else
1167
#elif defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
1168
            if (ppc_crypto_support() && (keysize % 8) == 0) {
1169
                cx->worker_cx = ppc_AES_GCM_CreateContext(cx, cx->worker, iv);
1170
                cx->worker = encrypt ? freeblCipher_ppc_AES_GCM_EncryptUpdate
1171
                                     : freeblCipher_ppc_AES_GCM_DecryptUpdate;
1172
                cx->worker_aead = encrypt ? freeblAead_ppc_AES_GCM_EncryptAEAD
1173
                                          : freeblAead_ppc_AES_GCM_DecryptAEAD;
1174
                cx->destroy = freeblDestroy_ppc_AES_GCM_DestroyContext;
1175
                cx->isBlock = PR_FALSE;
1176
            } else
1177
#endif
1178
12
            {
1179
12
                cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv);
1180
12
                cx->worker = encrypt ? freeblCipher_GCM_EncryptUpdate
1181
12
                                     : freeblCipher_GCM_DecryptUpdate;
1182
12
                cx->worker_aead = encrypt ? freeblAead_GCM_EncryptAEAD
1183
12
                                          : freeblAead_GCM_DecryptAEAD;
1184
1185
12
                cx->destroy = freeblDestroy_GCM_DestroyContext;
1186
12
                cx->isBlock = PR_FALSE;
1187
12
            }
1188
12
            break;
1189
0
        case NSS_AES_CTR:
1190
0
            cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv);
1191
#if defined(USE_HW_AES) && defined(_MSC_VER) && defined(NSS_X86_OR_X64)
1192
            if (aesni_support() && (keysize % 8) == 0) {
1193
                cx->worker = freeblCipher_CTR_Update_HW_AES;
1194
            } else
1195
#endif
1196
0
            {
1197
0
                cx->worker = freeblCipher_CTR_Update;
1198
0
            }
1199
0
            cx->destroy = freeblDestroy_CTR_DestroyContext;
1200
0
            cx->isBlock = PR_FALSE;
1201
0
            break;
1202
7
        default:
1203
            /* everything has already been set up by aes_InitContext, just
1204
             * return */
1205
7
            return SECSuccess;
1206
19
    }
1207
    /* check to see if we succeeded in getting the worker context */
1208
12
    if (cx->worker_cx == NULL) {
1209
        /* no, just destroy the existing context */
1210
11
        cx->destroy = NULL; /* paranoia, though you can see a dozen lines */
1211
                            /* below that this isn't necessary */
1212
11
        AES_DestroyContext(cx, PR_FALSE);
1213
11
        return SECFailure;
1214
11
    }
1215
1
    return SECSuccess;
1216
12
}
1217
1218
/* AES_CreateContext
1219
 *
1220
 * create a new context for Rijndael operations
1221
 */
1222
AESContext *
1223
AES_CreateContext(const unsigned char *key, const unsigned char *iv,
1224
                  int mode, int encrypt,
1225
                  unsigned int keysize, unsigned int blocksize)
1226
19
{
1227
19
    AESContext *cx = AES_AllocateContext();
1228
19
    if (cx) {
1229
19
        SECStatus rv = AES_InitContext(cx, key, keysize, iv, mode, encrypt,
1230
19
                                       blocksize);
1231
19
        if (rv != SECSuccess) {
1232
11
            AES_DestroyContext(cx, PR_TRUE);
1233
11
            cx = NULL;
1234
11
        }
1235
19
    }
1236
19
    return cx;
1237
19
}
1238
1239
/*
1240
 * AES_DestroyContext
1241
 *
1242
 * Zero an AES cipher context.  If freeit is true, also free the pointer
1243
 * to the context.
1244
 */
1245
void
1246
AES_DestroyContext(AESContext *cx, PRBool freeit)
1247
30
{
1248
30
    void *mem = cx->mem;
1249
30
    if (cx->worker_cx && cx->destroy) {
1250
1
        (*cx->destroy)(cx->worker_cx, PR_TRUE);
1251
1
        cx->worker_cx = NULL;
1252
1
        cx->destroy = NULL;
1253
1
    }
1254
30
    PORT_Memset(cx, 0, sizeof(AESContext));
1255
30
    if (freeit) {
1256
19
        PORT_Free(mem);
1257
19
    } else {
1258
        /* if we are not freeing the context, restore mem, We may get called
1259
         * again to actually free the context */
1260
11
        cx->mem = mem;
1261
11
    }
1262
30
}
1263
1264
/*
1265
 * AES_Encrypt
1266
 *
1267
 * Encrypt an arbitrary-length buffer.  The output buffer must already be
1268
 * allocated to at least inputLen.
1269
 */
1270
SECStatus
1271
AES_Encrypt(AESContext *cx, unsigned char *output,
1272
            unsigned int *outputLen, unsigned int maxOutputLen,
1273
            const unsigned char *input, unsigned int inputLen)
1274
759
{
1275
    /* Check args */
1276
759
    SECStatus rv;
1277
759
    if (cx == NULL || output == NULL || (input == NULL && inputLen != 0)) {
1278
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1279
0
        return SECFailure;
1280
0
    }
1281
759
    if (cx->isBlock && (inputLen % AES_BLOCK_SIZE != 0)) {
1282
2
        PORT_SetError(SEC_ERROR_INPUT_LEN);
1283
2
        return SECFailure;
1284
2
    }
1285
757
    if (maxOutputLen < inputLen) {
1286
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1287
0
        return SECFailure;
1288
0
    }
1289
757
    *outputLen = inputLen;
1290
#if UINT_MAX > MP_32BIT_MAX
1291
    /*
1292
     * we can guarentee that GSM won't overlfow if we limit the input to
1293
     * 2^36 bytes. For simplicity, we are limiting it to 2^32 for now.
1294
     *
1295
     * We do it here to cover both hardware and software GCM operations.
1296
     */
1297
    {
1298
        PR_STATIC_ASSERT(sizeof(unsigned int) > 4);
1299
    }
1300
    if ((cx->mode == NSS_AES_GCM) && (inputLen > MP_32BIT_MAX)) {
1301
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1302
        return SECFailure;
1303
    }
1304
#else
1305
    /* if we can't pass in a 32_bit number, then no such check needed */
1306
757
    {
1307
757
        PR_STATIC_ASSERT(sizeof(unsigned int) <= 4);
1308
757
    }
1309
757
#endif
1310
1311
757
    rv = (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
1312
757
                       input, inputLen, AES_BLOCK_SIZE);
1313
757
    BLAPI_CLEAR_STACK(256)
1314
757
    return rv;
1315
757
}
1316
1317
/*
1318
 * AES_Decrypt
1319
 *
1320
 * Decrypt and arbitrary-length buffer.  The output buffer must already be
1321
 * allocated to at least inputLen.
1322
 */
1323
SECStatus
1324
AES_Decrypt(AESContext *cx, unsigned char *output,
1325
            unsigned int *outputLen, unsigned int maxOutputLen,
1326
            const unsigned char *input, unsigned int inputLen)
1327
5
{
1328
5
    SECStatus rv;
1329
    /* Check args */
1330
5
    if (cx == NULL || output == NULL || (input == NULL && inputLen != 0)) {
1331
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1332
0
        return SECFailure;
1333
0
    }
1334
5
    if (cx->isBlock && (inputLen % AES_BLOCK_SIZE != 0)) {
1335
2
        PORT_SetError(SEC_ERROR_INPUT_LEN);
1336
2
        return SECFailure;
1337
2
    }
1338
3
    if ((cx->mode != NSS_AES_GCM) && (maxOutputLen < inputLen)) {
1339
2
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1340
2
        return SECFailure;
1341
2
    }
1342
1
    *outputLen = inputLen;
1343
1
    rv = (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
1344
1
                       input, inputLen, AES_BLOCK_SIZE);
1345
1
    BLAPI_CLEAR_STACK(256)
1346
1
    return rv;
1347
3
}
1348
1349
/*
1350
 * AES_Encrypt_AEAD
1351
 *
1352
 * Encrypt using GCM or CCM. include the nonce, extra data, and the tag
1353
 */
1354
SECStatus
1355
AES_AEAD(AESContext *cx, unsigned char *output,
1356
         unsigned int *outputLen, unsigned int maxOutputLen,
1357
         const unsigned char *input, unsigned int inputLen,
1358
         void *params, unsigned int paramsLen,
1359
         const unsigned char *aad, unsigned int aadLen)
1360
0
{
1361
0
    SECStatus rv;
1362
    /* Check args */
1363
0
    if (cx == NULL || output == NULL || (input == NULL && inputLen != 0) || (aad == NULL && aadLen != 0) || params == NULL) {
1364
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1365
0
        return SECFailure;
1366
0
    }
1367
0
    if (cx->worker_aead == NULL) {
1368
0
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1369
0
        return SECFailure;
1370
0
    }
1371
0
    if (maxOutputLen < inputLen) {
1372
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1373
0
        return SECFailure;
1374
0
    }
1375
0
    *outputLen = inputLen;
1376
#if UINT_MAX > MP_32BIT_MAX
1377
    /*
1378
     * we can guarentee that GSM won't overlfow if we limit the input to
1379
     * 2^36 bytes. For simplicity, we are limiting it to 2^32 for now.
1380
     *
1381
     * We do it here to cover both hardware and software GCM operations.
1382
     */
1383
    {
1384
        PR_STATIC_ASSERT(sizeof(unsigned int) > 4);
1385
    }
1386
    if (inputLen > MP_32BIT_MAX) {
1387
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1388
        return SECFailure;
1389
    }
1390
#else
1391
    /* if we can't pass in a 32_bit number, then no such check needed */
1392
0
    {
1393
0
        PR_STATIC_ASSERT(sizeof(unsigned int) <= 4);
1394
0
    }
1395
0
#endif
1396
1397
0
    rv = (*cx->worker_aead)(cx->worker_cx, output, outputLen, maxOutputLen,
1398
0
                            input, inputLen, params, paramsLen, aad, aadLen,
1399
0
                            AES_BLOCK_SIZE);
1400
0
    BLAPI_CLEAR_STACK(256)
1401
0
    return rv;
1402
0
}