Coverage Report

Created: 2025-08-18 06:35

/src/nss/lib/freebl/gcm.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
/* Thanks to Thomas Pornin for the ideas how to implement the constat time
5
 * binary multiplication. */
6
7
#ifdef FREEBL_NO_DEPEND
8
#include "stubs.h"
9
#endif
10
#include "blapii.h"
11
#include "blapit.h"
12
#include "blapi.h"
13
#include "gcm.h"
14
#include "ctr.h"
15
#include "secerr.h"
16
#include "prtypes.h"
17
#include "pkcs11t.h"
18
19
#include <limits.h>
20
21
/* old gcc doesn't support some poly64x2_t intrinsic */
22
#if defined(__aarch64__) && defined(IS_LITTLE_ENDIAN) && \
23
    (defined(__clang__) || defined(__GNUC__) && __GNUC__ > 6)
24
#define USE_ARM_GCM
25
#elif defined(__arm__) && defined(IS_LITTLE_ENDIAN) && \
26
    !defined(NSS_DISABLE_ARM32_NEON)
27
/* We don't test on big endian platform, so disable this on big endian. */
28
#define USE_ARM_GCM
29
#endif
30
31
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
32
#include <arm_neon.h>
33
#endif
34
35
/* Forward declarations */
36
SECStatus gcm_HashInit_hw(gcmHashContext *ghash);
37
SECStatus gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf);
38
SECStatus gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
39
                          unsigned int count);
40
SECStatus gcm_HashZeroX_hw(gcmHashContext *ghash);
41
SECStatus gcm_HashMult_sftw(gcmHashContext *ghash, const unsigned char *buf,
42
                            unsigned int count);
43
SECStatus gcm_HashMult_sftw32(gcmHashContext *ghash, const unsigned char *buf,
44
                              unsigned int count);
45
46
/* Stub definitions for the above *_hw functions, which shouldn't be
47
 * used unless NSS_X86_OR_X64 is defined */
48
#if !defined(NSS_X86_OR_X64) && !defined(USE_ARM_GCM) && !defined(USE_PPC_CRYPTO)
49
SECStatus
50
gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
51
{
52
    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
53
    return SECFailure;
54
}
55
56
SECStatus
57
gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
58
                unsigned int count)
59
{
60
    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
61
    return SECFailure;
62
}
63
64
SECStatus
65
gcm_HashInit_hw(gcmHashContext *ghash)
66
{
67
    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
68
    return SECFailure;
69
}
70
71
SECStatus
72
gcm_HashZeroX_hw(gcmHashContext *ghash)
73
{
74
    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
75
    return SECFailure;
76
}
77
#endif /* !NSS_X86_OR_X64 && !USE_ARM_GCM && !USE_PPC_CRYPTO */
78
79
uint64_t
80
get64(const unsigned char *bytes)
81
0
{
82
0
    return ((uint64_t)bytes[0]) << 56 |
83
0
           ((uint64_t)bytes[1]) << 48 |
84
0
           ((uint64_t)bytes[2]) << 40 |
85
0
           ((uint64_t)bytes[3]) << 32 |
86
0
           ((uint64_t)bytes[4]) << 24 |
87
0
           ((uint64_t)bytes[5]) << 16 |
88
0
           ((uint64_t)bytes[6]) << 8 |
89
0
           ((uint64_t)bytes[7]);
90
0
}
91
92
/* Initialize a gcmHashContext */
93
SECStatus
94
gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
95
0
{
96
0
    SECStatus rv = SECSuccess;
97
98
0
    ghash->cLen = 0;
99
0
    ghash->bufLen = 0;
100
0
    PORT_Memset(ghash->counterBuf, 0, sizeof(ghash->counterBuf));
101
102
0
    ghash->h_low = get64(H + 8);
103
0
    ghash->h_high = get64(H);
104
#ifdef USE_ARM_GCM
105
#if defined(__aarch64__)
106
    if (arm_pmull_support() && !sw) {
107
#else
108
    if (arm_neon_support() && !sw) {
109
#endif
110
#elif defined(USE_PPC_CRYPTO)
111
    if (ppc_crypto_support() && !sw) {
112
#else
113
0
    if (clmul_support() && !sw) {
114
0
#endif
115
0
        rv = gcm_HashInit_hw(ghash);
116
0
    } else {
117
/* We fall back to the software implementation if we can't use / don't
118
 * want to use pclmul. */
119
0
#ifdef HAVE_INT128_SUPPORT
120
0
        ghash->ghash_mul = gcm_HashMult_sftw;
121
#else
122
        ghash->ghash_mul = gcm_HashMult_sftw32;
123
#endif
124
0
        ghash->x_high = ghash->x_low = 0;
125
0
        ghash->hw = PR_FALSE;
126
0
    }
127
0
    return rv;
128
0
}
129
130
#ifdef HAVE_INT128_SUPPORT
131
/* Binary multiplication x * y = r_high << 64 | r_low. */
132
void
133
bmul(uint64_t x, uint64_t y, uint64_t *r_high, uint64_t *r_low)
134
0
{
135
0
    uint128_t x1, x2, x3, x4, x5;
136
0
    uint128_t y1, y2, y3, y4, y5;
137
0
    uint128_t r, z;
138
139
0
    uint128_t m1 = (uint128_t)0x2108421084210842 << 64 | 0x1084210842108421;
140
0
    uint128_t m2 = (uint128_t)0x4210842108421084 << 64 | 0x2108421084210842;
141
0
    uint128_t m3 = (uint128_t)0x8421084210842108 << 64 | 0x4210842108421084;
142
0
    uint128_t m4 = (uint128_t)0x0842108421084210 << 64 | 0x8421084210842108;
143
0
    uint128_t m5 = (uint128_t)0x1084210842108421 << 64 | 0x0842108421084210;
144
145
0
    x1 = x & m1;
146
0
    y1 = y & m1;
147
0
    x2 = x & m2;
148
0
    y2 = y & m2;
149
0
    x3 = x & m3;
150
0
    y3 = y & m3;
151
0
    x4 = x & m4;
152
0
    y4 = y & m4;
153
0
    x5 = x & m5;
154
0
    y5 = y & m5;
155
156
0
    z = (x1 * y1) ^ (x2 * y5) ^ (x3 * y4) ^ (x4 * y3) ^ (x5 * y2);
157
0
    r = z & m1;
158
0
    z = (x1 * y2) ^ (x2 * y1) ^ (x3 * y5) ^ (x4 * y4) ^ (x5 * y3);
159
0
    r |= z & m2;
160
0
    z = (x1 * y3) ^ (x2 * y2) ^ (x3 * y1) ^ (x4 * y5) ^ (x5 * y4);
161
0
    r |= z & m3;
162
0
    z = (x1 * y4) ^ (x2 * y3) ^ (x3 * y2) ^ (x4 * y1) ^ (x5 * y5);
163
0
    r |= z & m4;
164
0
    z = (x1 * y5) ^ (x2 * y4) ^ (x3 * y3) ^ (x4 * y2) ^ (x5 * y1);
165
0
    r |= z & m5;
166
167
0
    *r_high = (uint64_t)(r >> 64);
168
0
    *r_low = (uint64_t)r;
169
0
}
170
171
SECStatus
172
gcm_HashMult_sftw(gcmHashContext *ghash, const unsigned char *buf,
173
                  unsigned int count)
174
0
{
175
0
    uint64_t ci_low, ci_high;
176
0
    size_t i;
177
0
    uint64_t z2_low, z2_high, z0_low, z0_high, z1a_low, z1a_high;
178
0
    uint128_t z_high = 0, z_low = 0;
179
180
0
    ci_low = ghash->x_low;
181
0
    ci_high = ghash->x_high;
182
0
    for (i = 0; i < count; i++, buf += 16) {
183
0
        ci_low ^= get64(buf + 8);
184
0
        ci_high ^= get64(buf);
185
186
        /* Do binary mult ghash->X = C * ghash->H (Karatsuba). */
187
0
        bmul(ci_high, ghash->h_high, &z2_high, &z2_low);
188
0
        bmul(ci_low, ghash->h_low, &z0_high, &z0_low);
189
0
        bmul(ci_high ^ ci_low, ghash->h_high ^ ghash->h_low, &z1a_high, &z1a_low);
190
0
        z1a_high ^= z2_high ^ z0_high;
191
0
        z1a_low ^= z2_low ^ z0_low;
192
0
        z_high = ((uint128_t)z2_high << 64) | (z2_low ^ z1a_high);
193
0
        z_low = (((uint128_t)z0_high << 64) | z0_low) ^ (((uint128_t)z1a_low) << 64);
194
195
        /* Shift one (multiply by x) as gcm spec is stupid. */
196
0
        z_high = (z_high << 1) | (z_low >> 127);
197
0
        z_low <<= 1;
198
199
        /* Reduce */
200
0
        z_low ^= (z_low << 127) ^ (z_low << 126) ^ (z_low << 121);
201
0
        z_high ^= z_low ^ (z_low >> 1) ^ (z_low >> 2) ^ (z_low >> 7);
202
0
        ci_low = (uint64_t)z_high;
203
0
        ci_high = (uint64_t)(z_high >> 64);
204
0
    }
205
0
    ghash->x_low = ci_low;
206
0
    ghash->x_high = ci_high;
207
0
    return SECSuccess;
208
0
}
209
#else
210
/* Binary multiplication x * y = r_high << 32 | r_low. */
211
void
212
bmul32(uint32_t x, uint32_t y, uint32_t *r_high, uint32_t *r_low)
213
{
214
    uint32_t x0, x1, x2, x3;
215
    uint32_t y0, y1, y2, y3;
216
    uint32_t m1 = (uint32_t)0x11111111;
217
    uint32_t m2 = (uint32_t)0x22222222;
218
    uint32_t m4 = (uint32_t)0x44444444;
219
    uint32_t m8 = (uint32_t)0x88888888;
220
    uint64_t z0, z1, z2, z3;
221
    uint64_t z;
222
223
    x0 = x & m1;
224
    x1 = x & m2;
225
    x2 = x & m4;
226
    x3 = x & m8;
227
    y0 = y & m1;
228
    y1 = y & m2;
229
    y2 = y & m4;
230
    y3 = y & m8;
231
    z0 = ((uint64_t)x0 * y0) ^ ((uint64_t)x1 * y3) ^
232
         ((uint64_t)x2 * y2) ^ ((uint64_t)x3 * y1);
233
    z1 = ((uint64_t)x0 * y1) ^ ((uint64_t)x1 * y0) ^
234
         ((uint64_t)x2 * y3) ^ ((uint64_t)x3 * y2);
235
    z2 = ((uint64_t)x0 * y2) ^ ((uint64_t)x1 * y1) ^
236
         ((uint64_t)x2 * y0) ^ ((uint64_t)x3 * y3);
237
    z3 = ((uint64_t)x0 * y3) ^ ((uint64_t)x1 * y2) ^
238
         ((uint64_t)x2 * y1) ^ ((uint64_t)x3 * y0);
239
    z0 &= ((uint64_t)m1 << 32) | m1;
240
    z1 &= ((uint64_t)m2 << 32) | m2;
241
    z2 &= ((uint64_t)m4 << 32) | m4;
242
    z3 &= ((uint64_t)m8 << 32) | m8;
243
    z = z0 | z1 | z2 | z3;
244
    *r_high = (uint32_t)(z >> 32);
245
    *r_low = (uint32_t)z;
246
}
247
248
SECStatus
249
gcm_HashMult_sftw32(gcmHashContext *ghash, const unsigned char *buf,
250
                    unsigned int count)
251
{
252
    size_t i;
253
    uint64_t ci_low, ci_high;
254
    uint64_t z_high_h, z_high_l, z_low_h, z_low_l;
255
    uint32_t ci_high_h, ci_high_l, ci_low_h, ci_low_l;
256
    uint32_t b_a_h, b_a_l, a_a_h, a_a_l, b_b_h, b_b_l;
257
    uint32_t a_b_h, a_b_l, b_c_h, b_c_l, a_c_h, a_c_l, c_c_h, c_c_l;
258
    uint32_t ci_highXlow_h, ci_highXlow_l, c_a_h, c_a_l, c_b_h, c_b_l;
259
260
    uint32_t h_high_h = (uint32_t)(ghash->h_high >> 32);
261
    uint32_t h_high_l = (uint32_t)ghash->h_high;
262
    uint32_t h_low_h = (uint32_t)(ghash->h_low >> 32);
263
    uint32_t h_low_l = (uint32_t)ghash->h_low;
264
    uint32_t h_highXlow_h = h_high_h ^ h_low_h;
265
    uint32_t h_highXlow_l = h_high_l ^ h_low_l;
266
    uint32_t h_highX_xored = h_highXlow_h ^ h_highXlow_l;
267
268
    for (i = 0; i < count; i++, buf += 16) {
269
        ci_low = ghash->x_low ^ get64(buf + 8);
270
        ci_high = ghash->x_high ^ get64(buf);
271
        ci_low_h = (uint32_t)(ci_low >> 32);
272
        ci_low_l = (uint32_t)ci_low;
273
        ci_high_h = (uint32_t)(ci_high >> 32);
274
        ci_high_l = (uint32_t)ci_high;
275
        ci_highXlow_h = ci_high_h ^ ci_low_h;
276
        ci_highXlow_l = ci_high_l ^ ci_low_l;
277
278
        /* Do binary mult ghash->X = C * ghash->H (recursive Karatsuba). */
279
        bmul32(ci_high_h, h_high_h, &a_a_h, &a_a_l);
280
        bmul32(ci_high_l, h_high_l, &a_b_h, &a_b_l);
281
        bmul32(ci_high_h ^ ci_high_l, h_high_h ^ h_high_l, &a_c_h, &a_c_l);
282
        a_c_h ^= a_a_h ^ a_b_h;
283
        a_c_l ^= a_a_l ^ a_b_l;
284
        a_a_l ^= a_c_h;
285
        a_b_h ^= a_c_l;
286
        /* ci_high * h_high = a_a_h:a_a_l:a_b_h:a_b_l */
287
288
        bmul32(ci_low_h, h_low_h, &b_a_h, &b_a_l);
289
        bmul32(ci_low_l, h_low_l, &b_b_h, &b_b_l);
290
        bmul32(ci_low_h ^ ci_low_l, h_low_h ^ h_low_l, &b_c_h, &b_c_l);
291
        b_c_h ^= b_a_h ^ b_b_h;
292
        b_c_l ^= b_a_l ^ b_b_l;
293
        b_a_l ^= b_c_h;
294
        b_b_h ^= b_c_l;
295
        /* ci_low * h_low = b_a_h:b_a_l:b_b_h:b_b_l */
296
297
        bmul32(ci_highXlow_h, h_highXlow_h, &c_a_h, &c_a_l);
298
        bmul32(ci_highXlow_l, h_highXlow_l, &c_b_h, &c_b_l);
299
        bmul32(ci_highXlow_h ^ ci_highXlow_l, h_highX_xored, &c_c_h, &c_c_l);
300
        c_c_h ^= c_a_h ^ c_b_h;
301
        c_c_l ^= c_a_l ^ c_b_l;
302
        c_a_l ^= c_c_h;
303
        c_b_h ^= c_c_l;
304
        /* (ci_high ^ ci_low) * (h_high ^ h_low) = c_a_h:c_a_l:c_b_h:c_b_l */
305
306
        c_a_h ^= b_a_h ^ a_a_h;
307
        c_a_l ^= b_a_l ^ a_a_l;
308
        c_b_h ^= b_b_h ^ a_b_h;
309
        c_b_l ^= b_b_l ^ a_b_l;
310
        z_high_h = ((uint64_t)a_a_h << 32) | a_a_l;
311
        z_high_l = (((uint64_t)a_b_h << 32) | a_b_l) ^
312
                   (((uint64_t)c_a_h << 32) | c_a_l);
313
        z_low_h = (((uint64_t)b_a_h << 32) | b_a_l) ^
314
                  (((uint64_t)c_b_h << 32) | c_b_l);
315
        z_low_l = ((uint64_t)b_b_h << 32) | b_b_l;
316
317
        /* Shift one (multiply by x) as gcm spec is stupid. */
318
        z_high_h = z_high_h << 1 | z_high_l >> 63;
319
        z_high_l = z_high_l << 1 | z_low_h >> 63;
320
        z_low_h = z_low_h << 1 | z_low_l >> 63;
321
        z_low_l <<= 1;
322
323
        /* Reduce */
324
        z_low_h ^= (z_low_l << 63) ^ (z_low_l << 62) ^ (z_low_l << 57);
325
        z_high_h ^= z_low_h ^ (z_low_h >> 1) ^ (z_low_h >> 2) ^ (z_low_h >> 7);
326
        z_high_l ^= z_low_l ^ (z_low_l >> 1) ^ (z_low_l >> 2) ^ (z_low_l >> 7) ^
327
                    (z_low_h << 63) ^ (z_low_h << 62) ^ (z_low_h << 57);
328
        ghash->x_high = z_high_h;
329
        ghash->x_low = z_high_l;
330
    }
331
    return SECSuccess;
332
}
333
#endif /* HAVE_INT128_SUPPORT */
334
335
static SECStatus
336
gcm_zeroX(gcmHashContext *ghash)
337
0
{
338
0
    SECStatus rv = SECSuccess;
339
340
0
    if (ghash->hw) {
341
0
        rv = gcm_HashZeroX_hw(ghash);
342
0
    }
343
344
0
    ghash->x_high = ghash->x_low = 0;
345
0
    return rv;
346
0
}
347
348
/*
349
 * implement GCM GHASH using the freebl GHASH function. The gcm_HashMult
350
 * function always takes AES_BLOCK_SIZE lengths of data. gcmHash_Update will
351
 * format the data properly.
352
 */
353
SECStatus
354
gcmHash_Update(gcmHashContext *ghash, const unsigned char *buf,
355
               unsigned int len)
356
0
{
357
0
    unsigned int blocks;
358
0
    SECStatus rv;
359
360
0
    ghash->cLen += (len * PR_BITS_PER_BYTE);
361
362
    /* first deal with the current buffer of data. Try to fill it out so
363
     * we can hash it */
364
0
    if (ghash->bufLen) {
365
0
        unsigned int needed = PR_MIN(len, AES_BLOCK_SIZE - ghash->bufLen);
366
0
        if (needed != 0) {
367
0
            PORT_Memcpy(ghash->buffer + ghash->bufLen, buf, needed);
368
0
        }
369
0
        buf += needed;
370
0
        len -= needed;
371
0
        ghash->bufLen += needed;
372
0
        if (len == 0) {
373
            /* didn't add enough to hash the data, nothing more do do */
374
0
            return SECSuccess;
375
0
        }
376
0
        PORT_Assert(ghash->bufLen == AES_BLOCK_SIZE);
377
        /* hash the buffer and clear it */
378
0
        rv = ghash->ghash_mul(ghash, ghash->buffer, 1);
379
0
        PORT_Memset(ghash->buffer, 0, AES_BLOCK_SIZE);
380
0
        ghash->bufLen = 0;
381
0
        if (rv != SECSuccess) {
382
0
            return SECFailure;
383
0
        }
384
0
    }
385
    /* now hash any full blocks remaining in the data stream */
386
0
    blocks = len / AES_BLOCK_SIZE;
387
0
    if (blocks) {
388
0
        rv = ghash->ghash_mul(ghash, buf, blocks);
389
0
        if (rv != SECSuccess) {
390
0
            return SECFailure;
391
0
        }
392
0
        buf += blocks * AES_BLOCK_SIZE;
393
0
        len -= blocks * AES_BLOCK_SIZE;
394
0
    }
395
396
    /* save any remainder in the buffer to be hashed with the next call */
397
0
    if (len != 0) {
398
0
        PORT_Memcpy(ghash->buffer, buf, len);
399
0
        ghash->bufLen = len;
400
0
    }
401
0
    return SECSuccess;
402
0
}
403
404
/*
405
 * write out any partial blocks zero padded through the GHASH engine,
406
 * save the lengths for the final completion of the hash
407
 */
408
static SECStatus
409
gcmHash_Sync(gcmHashContext *ghash)
410
0
{
411
0
    int i;
412
0
    SECStatus rv;
413
414
    /* copy the previous counter to the upper block */
415
0
    PORT_Memcpy(ghash->counterBuf, &ghash->counterBuf[GCM_HASH_LEN_LEN],
416
0
                GCM_HASH_LEN_LEN);
417
    /* copy the current counter in the lower block */
418
0
    for (i = 0; i < GCM_HASH_LEN_LEN; i++) {
419
0
        ghash->counterBuf[GCM_HASH_LEN_LEN + i] =
420
0
            (ghash->cLen >> ((GCM_HASH_LEN_LEN - 1 - i) * PR_BITS_PER_BYTE)) & 0xff;
421
0
    }
422
0
    ghash->cLen = 0;
423
424
    /* now zero fill the buffer and hash the last block */
425
0
    if (ghash->bufLen) {
426
0
        PORT_Memset(ghash->buffer + ghash->bufLen, 0, AES_BLOCK_SIZE - ghash->bufLen);
427
0
        rv = ghash->ghash_mul(ghash, ghash->buffer, 1);
428
0
        PORT_Memset(ghash->buffer, 0, AES_BLOCK_SIZE);
429
0
        ghash->bufLen = 0;
430
0
        if (rv != SECSuccess) {
431
0
            return SECFailure;
432
0
        }
433
0
    }
434
0
    return SECSuccess;
435
0
}
436
437
#define WRITE64(x, bytes)   \
438
0
    (bytes)[0] = (x) >> 56; \
439
0
    (bytes)[1] = (x) >> 48; \
440
0
    (bytes)[2] = (x) >> 40; \
441
0
    (bytes)[3] = (x) >> 32; \
442
0
    (bytes)[4] = (x) >> 24; \
443
0
    (bytes)[5] = (x) >> 16; \
444
0
    (bytes)[6] = (x) >> 8;  \
445
0
    (bytes)[7] = (x);
446
447
/*
448
 * This does the final sync, hashes the lengths, then returns
449
 * "T", the hashed output.
450
 */
451
SECStatus
452
gcmHash_Final(gcmHashContext *ghash, unsigned char *outbuf,
453
              unsigned int *outlen, unsigned int maxout)
454
0
{
455
0
    unsigned char T[MAX_BLOCK_SIZE];
456
0
    SECStatus rv;
457
458
0
    rv = gcmHash_Sync(ghash);
459
0
    if (rv != SECSuccess) {
460
0
        goto cleanup;
461
0
    }
462
463
0
    rv = ghash->ghash_mul(ghash, ghash->counterBuf,
464
0
                          (GCM_HASH_LEN_LEN * 2) / AES_BLOCK_SIZE);
465
0
    if (rv != SECSuccess) {
466
0
        goto cleanup;
467
0
    }
468
469
0
    if (ghash->hw) {
470
0
        rv = gcm_HashWrite_hw(ghash, T);
471
0
        if (rv != SECSuccess) {
472
0
            goto cleanup;
473
0
        }
474
0
    } else {
475
0
        WRITE64(ghash->x_low, T + 8);
476
0
        WRITE64(ghash->x_high, T);
477
0
    }
478
479
0
    if (maxout > AES_BLOCK_SIZE) {
480
0
        maxout = AES_BLOCK_SIZE;
481
0
    }
482
0
    PORT_Memcpy(outbuf, T, maxout);
483
0
    *outlen = maxout;
484
0
    rv = SECSuccess;
485
486
0
cleanup:
487
0
    PORT_SafeZero(T, sizeof(T));
488
0
    return rv;
489
0
}
490
491
SECStatus
492
gcmHash_Reset(gcmHashContext *ghash, const unsigned char *AAD,
493
              unsigned int AADLen)
494
0
{
495
0
    SECStatus rv;
496
497
    // Limit AADLen in accordance with SP800-38D
498
0
    if (sizeof(AADLen) >= 8) {
499
0
        unsigned long long AADLen_ull = AADLen;
500
0
        if (AADLen_ull > (1ULL << 61) - 1) {
501
0
            PORT_SetError(SEC_ERROR_INPUT_LEN);
502
0
            return SECFailure;
503
0
        }
504
0
    }
505
506
0
    ghash->cLen = 0;
507
0
    PORT_Memset(ghash->counterBuf, 0, GCM_HASH_LEN_LEN * 2);
508
0
    ghash->bufLen = 0;
509
0
    rv = gcm_zeroX(ghash);
510
0
    if (rv != SECSuccess) {
511
0
        return rv;
512
0
    }
513
514
    /* now kick things off by hashing the Additional Authenticated Data */
515
0
    if (AADLen != 0) {
516
0
        rv = gcmHash_Update(ghash, AAD, AADLen);
517
0
        if (rv != SECSuccess) {
518
0
            return SECFailure;
519
0
        }
520
0
        rv = gcmHash_Sync(ghash);
521
0
        if (rv != SECSuccess) {
522
0
            return SECFailure;
523
0
        }
524
0
    }
525
0
    return SECSuccess;
526
0
}
527
528
/**************************************************************************
529
 *           Now implement the GCM using gcmHash and CTR                  *
530
 **************************************************************************/
531
532
/* state to handle the full GCM operation (hash and counter) */
533
struct GCMContextStr {
534
    gcmHashContext *ghash_context;
535
    CTRContext ctr_context;
536
    freeblCipherFunc cipher;
537
    void *cipher_context;
538
    unsigned long tagBits;
539
    unsigned char tagKey[MAX_BLOCK_SIZE];
540
    PRBool ctr_context_init;
541
    gcmIVContext gcm_iv;
542
};
543
544
SECStatus gcm_InitCounter(GCMContext *gcm, const unsigned char *iv,
545
                          unsigned int ivLen, unsigned int tagBits,
546
                          const unsigned char *aad, unsigned int aadLen);
547
548
GCMContext *
549
GCM_CreateContext(void *context, freeblCipherFunc cipher,
550
                  const unsigned char *params)
551
0
{
552
0
    GCMContext *gcm = NULL;
553
0
    gcmHashContext *ghash = NULL;
554
0
    unsigned char H[MAX_BLOCK_SIZE];
555
0
    unsigned int tmp;
556
0
    const CK_NSS_GCM_PARAMS *gcmParams = (const CK_NSS_GCM_PARAMS *)params;
557
0
    SECStatus rv;
558
#ifdef DISABLE_HW_GCM
559
    const PRBool sw = PR_TRUE;
560
#else
561
0
    const PRBool sw = PR_FALSE;
562
0
#endif
563
564
0
    gcm = PORT_ZNew(GCMContext);
565
0
    if (gcm == NULL) {
566
0
        return NULL;
567
0
    }
568
0
    gcm->cipher = cipher;
569
0
    gcm->cipher_context = context;
570
0
    ghash = PORT_ZNewAligned(gcmHashContext, 16, mem);
571
572
    /* first plug in the ghash context */
573
0
    gcm->ghash_context = ghash;
574
0
    PORT_Memset(H, 0, AES_BLOCK_SIZE);
575
0
    rv = (*cipher)(context, H, &tmp, AES_BLOCK_SIZE, H, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
576
0
    if (rv != SECSuccess) {
577
0
        goto loser;
578
0
    }
579
0
    rv = gcmHash_InitContext(ghash, H, sw);
580
0
    if (rv != SECSuccess) {
581
0
        goto loser;
582
0
    }
583
584
0
    gcm_InitIVContext(&gcm->gcm_iv);
585
0
    gcm->ctr_context_init = PR_FALSE;
586
587
    /* if gcmPara/ms is NULL, then we are creating an PKCS #11 MESSAGE
588
     * style context, in which we initialize the key once, then do separate
589
     * iv/aad's for each message. In that case we only initialize the key
590
     * and ghash. We initialize the counter in each separate message */
591
0
    if (gcmParams == NULL) {
592
        /* OK we are finished with init, if we are doing MESSAGE interface,
593
         * return from here */
594
0
        return gcm;
595
0
    }
596
597
0
    rv = gcm_InitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
598
0
                         gcmParams->ulTagBits, gcmParams->pAAD,
599
0
                         gcmParams->ulAADLen);
600
0
    if (rv != SECSuccess) {
601
0
        goto loser;
602
0
    }
603
0
    PORT_SafeZero(H, AES_BLOCK_SIZE);
604
0
    gcm->ctr_context_init = PR_TRUE;
605
0
    return gcm;
606
607
0
loser:
608
0
    PORT_SafeZero(H, AES_BLOCK_SIZE);
609
0
    if (ghash && ghash->mem) {
610
0
        void *mem = ghash->mem;
611
0
        PORT_SafeZero(ghash, sizeof(gcmHashContext));
612
0
        PORT_Free(mem);
613
0
    }
614
0
    if (gcm) {
615
0
        PORT_ZFree(gcm, sizeof(GCMContext));
616
0
    }
617
0
    return NULL;
618
0
}
619
620
static inline unsigned int
621
load32_be(const unsigned char *p)
622
0
{
623
0
    return ((unsigned int)p[0]) << 24 | p[1] << 16 | p[2] << 8 | p[3];
624
0
}
625
626
static inline void
627
store32_be(unsigned char *p, const unsigned int c)
628
0
{
629
0
    p[0] = (unsigned char)(c >> 24);
630
0
    p[1] = (unsigned char)(c >> 16);
631
0
    p[2] = (unsigned char)(c >> 8);
632
0
    p[3] = (unsigned char)c;
633
0
}
634
635
static inline void
636
gcm_ctr_xor(unsigned char *target, const unsigned char *x,
637
            const unsigned char *y, unsigned int count)
638
0
{
639
0
    for (unsigned int i = 0; i < count; i++) {
640
0
        target[i] = x[i] ^ y[i];
641
0
    }
642
0
}
643
644
static inline void
645
gcm_ctr_xor_block(unsigned char *target, const unsigned char *x,
646
                  const unsigned char *y)
647
0
{
648
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
649
    vst1q_u8(target, veorq_u8(vld1q_u8(x), vld1q_u8(y)));
650
#else
651
0
    gcm_ctr_xor(target, x, y, AES_BLOCK_SIZE);
652
0
#endif
653
0
}
654
655
static SECStatus
656
gcm_CTR_Update(CTRContext *ctr, unsigned char *outbuf,
657
               unsigned int *outlen, unsigned int maxout,
658
               const unsigned char *inbuf, unsigned int inlen)
659
0
{
660
0
    PORT_Assert(ctr->counterBits == 32);
661
0
    PORT_Assert(0 < ctr->bufPtr && ctr->bufPtr <= AES_BLOCK_SIZE);
662
663
    // The AES-GCM message length limit is 2^32 - 2 blocks.
664
0
    const unsigned int blockLimit = 0xFFFFFFFEUL;
665
666
0
    unsigned char *const pCounter = ctr->counter + AES_BLOCK_SIZE - 4;
667
0
    unsigned int counter = load32_be(pCounter);
668
669
    // Calculate the number of times that the counter has already been incremented.
670
0
    unsigned char *const pCounterFirst = ctr->counterFirst + AES_BLOCK_SIZE - 4;
671
0
    unsigned int ticks = (counter - load32_be(pCounterFirst)) & 0xFFFFFFFFUL;
672
673
    // Get the number of bytes of keystream that are available in the internal buffer.
674
0
    const unsigned int bufBytes = AES_BLOCK_SIZE - ctr->bufPtr;
675
676
    // Calculate the number of times that we will increment the counter while
677
    // encrypting inbuf. We can encrypt bufBytes bytes of the input without
678
    // incrementing the counter.
679
0
    unsigned int newTicks;
680
0
    if (inlen < bufBytes) {
681
0
        newTicks = 0;
682
0
    } else if ((inlen - bufBytes) % AES_BLOCK_SIZE) {
683
0
        newTicks = ((inlen - bufBytes) / AES_BLOCK_SIZE) + 1;
684
0
    } else {
685
0
        newTicks = ((inlen - bufBytes) / AES_BLOCK_SIZE);
686
0
    }
687
688
    // Ensure that the counter will not exceed the limit.
689
0
    if (ticks > blockLimit - newTicks) {
690
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
691
0
        return SECFailure;
692
0
    }
693
694
0
    *outlen = inlen;
695
0
    if (maxout < inlen) {
696
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
697
0
        return SECFailure;
698
0
    }
699
700
0
    if (bufBytes) {
701
0
        unsigned int needed = PR_MIN(bufBytes, inlen);
702
0
        gcm_ctr_xor(outbuf, inbuf, ctr->buffer + ctr->bufPtr, needed);
703
0
        ctr->bufPtr += needed;
704
0
        outbuf += needed;
705
0
        inbuf += needed;
706
0
        inlen -= needed;
707
0
        PORT_Assert(inlen == 0 || ctr->bufPtr == AES_BLOCK_SIZE);
708
0
    }
709
0
    while (inlen >= AES_BLOCK_SIZE) {
710
0
        unsigned int tmp;
711
0
        SECStatus rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, AES_BLOCK_SIZE,
712
0
                                      ctr->counter, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
713
0
        PORT_Assert(rv == SECSuccess);
714
0
        (void)rv;
715
0
        store32_be(pCounter, ++counter);
716
0
        gcm_ctr_xor_block(outbuf, inbuf, ctr->buffer);
717
0
        outbuf += AES_BLOCK_SIZE;
718
0
        inbuf += AES_BLOCK_SIZE;
719
0
        inlen -= AES_BLOCK_SIZE;
720
0
    }
721
0
    if (inlen) {
722
0
        unsigned int tmp;
723
0
        SECStatus rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, AES_BLOCK_SIZE,
724
0
                                      ctr->counter, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
725
0
        PORT_Assert(rv == SECSuccess);
726
0
        (void)rv;
727
0
        store32_be(pCounter, ++counter);
728
0
        gcm_ctr_xor(outbuf, inbuf, ctr->buffer, inlen);
729
0
        ctr->bufPtr = inlen;
730
0
    }
731
0
    return SECSuccess;
732
0
}
733
734
SECStatus
735
gcm_InitCounter(GCMContext *gcm, const unsigned char *iv, unsigned int ivLen,
736
                unsigned int tagBits, const unsigned char *aad,
737
                unsigned int aadLen)
738
0
{
739
0
    gcmHashContext *ghash = gcm->ghash_context;
740
0
    unsigned int tmp;
741
0
    PRBool freeCtr = PR_FALSE;
742
0
    CK_AES_CTR_PARAMS ctrParams;
743
0
    SECStatus rv;
744
745
    /* Verify our parameters here */
746
0
    if (ivLen == 0) {
747
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
748
0
        goto loser;
749
0
    }
750
751
0
    if (tagBits != 128 && tagBits != 120 &&
752
0
        tagBits != 112 && tagBits != 104 &&
753
0
        tagBits != 96 && tagBits != 64 &&
754
0
        tagBits != 32) {
755
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
756
0
        goto loser;
757
0
    }
758
759
    /* fill in the Counter context */
760
0
    ctrParams.ulCounterBits = 32;
761
0
    PORT_Memset(ctrParams.cb, 0, sizeof(ctrParams.cb));
762
0
    if (ivLen == 12) {
763
0
        PORT_Memcpy(ctrParams.cb, iv, ivLen);
764
0
        ctrParams.cb[AES_BLOCK_SIZE - 1] = 1;
765
0
    } else {
766
0
        rv = gcmHash_Reset(ghash, NULL, 0);
767
0
        if (rv != SECSuccess) {
768
0
            goto loser;
769
0
        }
770
0
        rv = gcmHash_Update(ghash, iv, ivLen);
771
0
        if (rv != SECSuccess) {
772
0
            goto loser;
773
0
        }
774
0
        rv = gcmHash_Final(ghash, ctrParams.cb, &tmp, AES_BLOCK_SIZE);
775
0
        if (rv != SECSuccess) {
776
0
            goto loser;
777
0
        }
778
0
    }
779
0
    rv = CTR_InitContext(&gcm->ctr_context, gcm->cipher_context, gcm->cipher,
780
0
                         (unsigned char *)&ctrParams);
781
0
    if (rv != SECSuccess) {
782
0
        goto loser;
783
0
    }
784
0
    freeCtr = PR_TRUE;
785
786
    /* fill in the gcm structure */
787
0
    gcm->tagBits = tagBits; /* save for final step */
788
    /* calculate the final tag key. NOTE: gcm->tagKey is zero to start with.
789
     * if this assumption changes, we would need to explicitly clear it here */
790
0
    PORT_Memset(gcm->tagKey, 0, sizeof(gcm->tagKey));
791
0
    rv = gcm_CTR_Update(&gcm->ctr_context, gcm->tagKey, &tmp, AES_BLOCK_SIZE,
792
0
                        gcm->tagKey, AES_BLOCK_SIZE);
793
0
    if (rv != SECSuccess) {
794
0
        goto loser;
795
0
    }
796
797
    /* finally mix in the AAD data */
798
0
    rv = gcmHash_Reset(ghash, aad, aadLen);
799
0
    if (rv != SECSuccess) {
800
0
        goto loser;
801
0
    }
802
803
0
    PORT_SafeZero(&ctrParams, sizeof ctrParams);
804
0
    return SECSuccess;
805
806
0
loser:
807
0
    PORT_SafeZero(&ctrParams, sizeof ctrParams);
808
0
    if (freeCtr) {
809
0
        CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
810
0
    }
811
0
    return SECFailure;
812
0
}
813
814
void
815
GCM_DestroyContext(GCMContext *gcm, PRBool freeit)
816
0
{
817
0
    void *mem = gcm->ghash_context->mem;
818
    /* ctr_context is statically allocated and will be freed when we free
819
     * gcm. call their destroy functions to free up any locally
820
     * allocated data (like mp_int's) */
821
0
    if (gcm->ctr_context_init) {
822
0
        CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
823
0
    }
824
0
    PORT_Memset(gcm->ghash_context, 0, sizeof(gcmHashContext));
825
0
    PORT_Free(mem);
826
0
    PORT_Memset(&gcm->tagBits, 0, sizeof(gcm->tagBits));
827
0
    PORT_Memset(gcm->tagKey, 0, sizeof(gcm->tagKey));
828
0
    if (freeit) {
829
0
        PORT_Free(gcm);
830
0
    }
831
0
}
832
833
static SECStatus
834
gcm_GetTag(GCMContext *gcm, unsigned char *outbuf,
835
           unsigned int *outlen, unsigned int maxout)
836
0
{
837
0
    unsigned int tagBytes;
838
0
    unsigned int extra;
839
0
    unsigned int i;
840
0
    SECStatus rv;
841
842
0
    tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
843
0
    extra = tagBytes * PR_BITS_PER_BYTE - gcm->tagBits;
844
845
0
    if (outbuf == NULL) {
846
0
        *outlen = tagBytes;
847
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
848
0
        return SECFailure;
849
0
    }
850
851
0
    if (maxout < tagBytes) {
852
0
        *outlen = tagBytes;
853
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
854
0
        return SECFailure;
855
0
    }
856
0
    maxout = tagBytes;
857
0
    rv = gcmHash_Final(gcm->ghash_context, outbuf, outlen, maxout);
858
0
    if (rv != SECSuccess) {
859
0
        return SECFailure;
860
0
    }
861
862
0
    for (i = 0; i < *outlen; i++) {
863
0
        outbuf[i] ^= gcm->tagKey[i];
864
0
    }
865
    /* mask off any extra bits we got */
866
0
    if (extra) {
867
0
        outbuf[tagBytes - 1] &= ~((1 << extra) - 1);
868
0
    }
869
0
    return SECSuccess;
870
0
}
871
872
/*
873
 * See The Galois/Counter Mode of Operation, McGrew and Viega.
874
 *  GCM is basically counter mode with a specific initialization and
875
 *  built in macing operation.
876
 */
877
SECStatus
878
GCM_EncryptUpdate(GCMContext *gcm, unsigned char *outbuf,
879
                  unsigned int *outlen, unsigned int maxout,
880
                  const unsigned char *inbuf, unsigned int inlen,
881
                  unsigned int blocksize)
882
0
{
883
0
    SECStatus rv;
884
0
    unsigned int tagBytes;
885
0
    unsigned int len;
886
887
0
    PORT_Assert(blocksize == AES_BLOCK_SIZE);
888
0
    if (blocksize != AES_BLOCK_SIZE) {
889
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
890
0
        return SECFailure;
891
0
    }
892
893
0
    if (!gcm->ctr_context_init) {
894
0
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
895
0
        return SECFailure;
896
0
    }
897
898
0
    tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
899
0
    if (UINT_MAX - inlen < tagBytes) {
900
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
901
0
        return SECFailure;
902
0
    }
903
0
    if (maxout < inlen + tagBytes) {
904
0
        *outlen = inlen + tagBytes;
905
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
906
0
        return SECFailure;
907
0
    }
908
909
0
    rv = gcm_CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
910
0
                        inbuf, inlen);
911
0
    if (rv != SECSuccess) {
912
0
        return SECFailure;
913
0
    }
914
0
    rv = gcmHash_Update(gcm->ghash_context, outbuf, *outlen);
915
0
    if (rv != SECSuccess) {
916
0
        PORT_Memset(outbuf, 0, *outlen); /* clear the output buffer */
917
0
        *outlen = 0;
918
0
        return SECFailure;
919
0
    }
920
0
    rv = gcm_GetTag(gcm, outbuf + *outlen, &len, maxout - *outlen);
921
0
    if (rv != SECSuccess) {
922
0
        PORT_Memset(outbuf, 0, *outlen); /* clear the output buffer */
923
0
        *outlen = 0;
924
0
        return SECFailure;
925
0
    };
926
0
    *outlen += len;
927
0
    return SECSuccess;
928
0
}
929
930
/*
931
 * See The Galois/Counter Mode of Operation, McGrew and Viega.
932
 *  GCM is basically counter mode with a specific initialization and
933
 *  built in macing operation. NOTE: the only difference between Encrypt
934
 *  and Decrypt is when we calculate the mac. That is because the mac must
935
 *  always be calculated on the cipher text, not the plain text, so for
936
 *  encrypt, we do the CTR update first and for decrypt we do the mac first.
937
 */
938
SECStatus
939
GCM_DecryptUpdate(GCMContext *gcm, unsigned char *outbuf,
940
                  unsigned int *outlen, unsigned int maxout,
941
                  const unsigned char *inbuf, unsigned int inlen,
942
                  unsigned int blocksize)
943
0
{
944
0
    SECStatus rv;
945
0
    unsigned int tagBytes;
946
0
    unsigned char tag[MAX_BLOCK_SIZE];
947
0
    const unsigned char *intag;
948
0
    unsigned int len;
949
950
0
    PORT_Assert(blocksize == AES_BLOCK_SIZE);
951
0
    if (blocksize != AES_BLOCK_SIZE) {
952
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
953
0
        return SECFailure;
954
0
    }
955
956
0
    if (!gcm->ctr_context_init) {
957
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
958
0
        return SECFailure;
959
0
    }
960
961
0
    tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
962
963
    /* get the authentication block */
964
0
    if (inlen < tagBytes) {
965
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
966
0
        return SECFailure;
967
0
    }
968
969
0
    inlen -= tagBytes;
970
0
    intag = inbuf + inlen;
971
972
    /* verify the block */
973
0
    rv = gcmHash_Update(gcm->ghash_context, inbuf, inlen);
974
0
    if (rv != SECSuccess) {
975
0
        return SECFailure;
976
0
    }
977
0
    rv = gcm_GetTag(gcm, tag, &len, AES_BLOCK_SIZE);
978
0
    if (rv != SECSuccess) {
979
0
        return SECFailure;
980
0
    }
981
    /* Don't decrypt if we can't authenticate the encrypted data!
982
     * This assumes that if tagBits is not a multiple of 8, intag will
983
     * preserve the masked off missing bits.  */
984
0
    if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) {
985
        /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
986
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
987
0
        PORT_SafeZero(tag, sizeof(tag));
988
0
        return SECFailure;
989
0
    }
990
0
    PORT_SafeZero(tag, sizeof(tag));
991
    /* finish the decryption */
992
0
    return gcm_CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
993
0
                          inbuf, inlen);
994
0
}
995
996
void
997
gcm_InitIVContext(gcmIVContext *gcmIv)
998
0
{
999
0
    gcmIv->counter = 0;
1000
0
    gcmIv->max_count = 0;
1001
0
    gcmIv->ivGen = CKG_GENERATE;
1002
0
    gcmIv->ivLen = 0;
1003
0
    gcmIv->fixedBits = 0;
1004
0
}
1005
1006
/*
1007
 * generate the IV on the fly and return it to the application.
1008
 *   This function keeps a counter, which may be used in the IV
1009
 *   generation, or may be used in simply to make sure we don't
1010
 *   generate to many IV's from this same key.
1011
 *   PKCS #11 defines 4 generating values:
1012
 *       1) CKG_NO_GENERATE: just use the passed in IV as it.
1013
 *       2) CKG_GENERATE: the application doesn't care what generation
1014
 *       scheme is use (we default to counter in this code).
1015
 *       3) CKG_GENERATE_COUNTER: The IV is the value of a counter.
1016
 *       4) CKG_GENERATE_RANDOM: The IV is randomly generated.
1017
 *   We add a fifth rule:
1018
 *       5) CKG_GENERATE_COUNTER_XOR: The Counter value is xor'ed with
1019
 *       the IV.
1020
 *   The value fixedBits specifies the number of bits that will be passed
1021
 *   on from the original IV. The counter or the random data is is loaded
1022
 *   in the remainder of the IV not covered by fixedBits, overwriting any
1023
 *   data there. In the xor case the counter is xor'ed with the data in the
1024
 *   IV. In all cases only bits outside of fixedBits is modified.
1025
 *   The number of IV's we can generate is restricted by the size of the
1026
 *   variable part of the IV and the generation algorithm used. Because of
1027
 *   this, we require subsequent calls on this context to use the same
1028
 *   generator, IV len, and fixed bits as the first call.
1029
 */
1030
SECStatus
1031
gcm_GenerateIV(gcmIVContext *gcmIv, unsigned char *iv, unsigned int ivLen,
1032
               unsigned int fixedBits, CK_GENERATOR_FUNCTION ivGen)
1033
0
{
1034
0
    unsigned int i;
1035
0
    unsigned int flexBits;
1036
0
    unsigned int ivOffset;
1037
0
    unsigned int ivNewCount;
1038
0
    unsigned char ivMask;
1039
0
    unsigned char ivSave;
1040
0
    SECStatus rv;
1041
1042
0
    if (gcmIv->counter != 0) {
1043
        /* If we've already generated a message, make sure all subsequent
1044
         * messages are using the same generator */
1045
0
        if ((gcmIv->ivGen != ivGen) || (gcmIv->fixedBits != fixedBits) ||
1046
0
            (gcmIv->ivLen != ivLen)) {
1047
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
1048
0
            return SECFailure;
1049
0
        }
1050
0
    } else {
1051
        /* remember these values */
1052
0
        gcmIv->ivGen = ivGen;
1053
0
        gcmIv->fixedBits = fixedBits;
1054
0
        gcmIv->ivLen = ivLen;
1055
        /* now calculate how may bits of IV we have to supply */
1056
0
        flexBits = ivLen * PR_BITS_PER_BYTE; /* bytes->bits */
1057
        /* first make sure we aren't going to overflow */
1058
0
        if (flexBits < fixedBits) {
1059
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
1060
0
            return SECFailure;
1061
0
        }
1062
0
        flexBits -= fixedBits;
1063
        /* if we are generating a random number reduce the acceptable bits to
1064
         * avoid birthday attacks */
1065
0
        if (ivGen == CKG_GENERATE_RANDOM) {
1066
0
            if (flexBits <= GCMIV_RANDOM_BIRTHDAY_BITS) {
1067
0
                PORT_SetError(SEC_ERROR_INVALID_ARGS);
1068
0
                return SECFailure;
1069
0
            }
1070
            /* see freebl/blapit.h for how we calculate
1071
             * GCMIV_RANDOM_BIRTHDAY_BITS */
1072
0
            flexBits -= GCMIV_RANDOM_BIRTHDAY_BITS;
1073
0
            flexBits = flexBits >> 1;
1074
0
        }
1075
0
        if (flexBits == 0) {
1076
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
1077
0
            return SECFailure;
1078
0
        }
1079
        /* Turn those bits into the number of IV's we can safely return */
1080
0
        if (flexBits >= sizeof(gcmIv->max_count) * PR_BITS_PER_BYTE) {
1081
0
            gcmIv->max_count = PR_UINT64(0xffffffffffffffff);
1082
0
        } else {
1083
0
            gcmIv->max_count = PR_UINT64(1) << flexBits;
1084
0
        }
1085
0
    }
1086
1087
    /* no generate, accept the IV from the source */
1088
0
    if (ivGen == CKG_NO_GENERATE) {
1089
0
        gcmIv->counter = 1;
1090
0
        return SECSuccess;
1091
0
    }
1092
1093
    /* make sure we haven't exceeded the number of IVs we can return
1094
     * for this key, generator, and IV size */
1095
0
    if (gcmIv->counter >= gcmIv->max_count) {
1096
        /* use a unique error from just bad user input */
1097
0
        PORT_SetError(SEC_ERROR_EXTRA_INPUT);
1098
0
        return SECFailure;
1099
0
    }
1100
1101
    /* build to mask to handle the first byte of the IV */
1102
0
    ivOffset = fixedBits / PR_BITS_PER_BYTE;
1103
0
    ivMask = 0xff >> ((8 - (fixedBits & 7)) & 7);
1104
0
    ivNewCount = ivLen - ivOffset;
1105
1106
    /* finally generate the IV */
1107
0
    switch (ivGen) {
1108
0
        case CKG_GENERATE: /* default to counter */
1109
0
        case CKG_GENERATE_COUNTER:
1110
0
            iv[ivOffset] = (iv[ivOffset] & ~ivMask) |
1111
0
                           (PORT_GET_BYTE_BE(gcmIv->counter, 0, ivNewCount) & ivMask);
1112
0
            for (i = 1; i < ivNewCount; i++) {
1113
0
                iv[ivOffset + i] = PORT_GET_BYTE_BE(gcmIv->counter, i, ivNewCount);
1114
0
            }
1115
0
            break;
1116
        /* for TLS 1.3 */
1117
0
        case CKG_GENERATE_COUNTER_XOR:
1118
0
            iv[ivOffset] ^=
1119
0
                (PORT_GET_BYTE_BE(gcmIv->counter, 0, ivNewCount) & ivMask);
1120
0
            for (i = 1; i < ivNewCount; i++) {
1121
0
                iv[ivOffset + i] ^= PORT_GET_BYTE_BE(gcmIv->counter, i, ivNewCount);
1122
0
            }
1123
0
            break;
1124
0
        case CKG_GENERATE_RANDOM:
1125
0
            ivSave = iv[ivOffset] & ~ivMask;
1126
0
            rv = RNG_GenerateGlobalRandomBytes(iv + ivOffset, ivNewCount);
1127
0
            iv[ivOffset] = ivSave | (iv[ivOffset] & ivMask);
1128
0
            if (rv != SECSuccess) {
1129
0
                return rv;
1130
0
            }
1131
0
            break;
1132
0
    }
1133
0
    gcmIv->counter++;
1134
0
    return SECSuccess;
1135
0
}
1136
1137
SECStatus
1138
GCM_EncryptAEAD(GCMContext *gcm, unsigned char *outbuf,
1139
                unsigned int *outlen, unsigned int maxout,
1140
                const unsigned char *inbuf, unsigned int inlen,
1141
                void *params, unsigned int paramLen,
1142
                const unsigned char *aad, unsigned int aadLen,
1143
                unsigned int blocksize)
1144
0
{
1145
0
    SECStatus rv;
1146
0
    unsigned int tagBytes;
1147
0
    unsigned int len;
1148
0
    const CK_GCM_MESSAGE_PARAMS *gcmParams =
1149
0
        (const CK_GCM_MESSAGE_PARAMS *)params;
1150
1151
0
    PORT_Assert(blocksize == AES_BLOCK_SIZE);
1152
0
    if (blocksize != AES_BLOCK_SIZE) {
1153
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1154
0
        return SECFailure;
1155
0
    }
1156
1157
    /* paramLen comes all the way from the application layer, make sure
1158
     * it's correct */
1159
0
    if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
1160
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1161
0
        return SECFailure;
1162
0
    }
1163
    /* if we were initialized with the C_EncryptInit, we shouldn't be in this
1164
     * function */
1165
0
    if (gcm->ctr_context_init) {
1166
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1167
0
        return SECFailure;
1168
0
    }
1169
1170
0
    if (maxout < inlen) {
1171
0
        *outlen = inlen;
1172
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1173
0
        return SECFailure;
1174
0
    }
1175
1176
0
    rv = gcm_GenerateIV(&gcm->gcm_iv, gcmParams->pIv, gcmParams->ulIvLen,
1177
0
                        gcmParams->ulIvFixedBits, gcmParams->ivGenerator);
1178
0
    if (rv != SECSuccess) {
1179
0
        return SECFailure;
1180
0
    }
1181
1182
0
    rv = gcm_InitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
1183
0
                         gcmParams->ulTagBits, aad, aadLen);
1184
0
    if (rv != SECSuccess) {
1185
0
        return SECFailure;
1186
0
    }
1187
1188
0
    tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
1189
1190
0
    rv = gcm_CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
1191
0
                        inbuf, inlen);
1192
0
    CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
1193
0
    if (rv != SECSuccess) {
1194
0
        return SECFailure;
1195
0
    }
1196
0
    rv = gcmHash_Update(gcm->ghash_context, outbuf, *outlen);
1197
0
    if (rv != SECSuccess) {
1198
0
        PORT_Memset(outbuf, 0, *outlen); /* clear the output buffer */
1199
0
        *outlen = 0;
1200
0
        return SECFailure;
1201
0
    }
1202
0
    rv = gcm_GetTag(gcm, gcmParams->pTag, &len, tagBytes);
1203
0
    if (rv != SECSuccess) {
1204
0
        PORT_Memset(outbuf, 0, *outlen); /* clear the output buffer */
1205
0
        *outlen = 0;
1206
0
        return SECFailure;
1207
0
    };
1208
0
    return SECSuccess;
1209
0
}
1210
1211
SECStatus
1212
GCM_DecryptAEAD(GCMContext *gcm, unsigned char *outbuf,
1213
                unsigned int *outlen, unsigned int maxout,
1214
                const unsigned char *inbuf, unsigned int inlen,
1215
                void *params, unsigned int paramLen,
1216
                const unsigned char *aad, unsigned int aadLen,
1217
                unsigned int blocksize)
1218
0
{
1219
0
    SECStatus rv;
1220
0
    unsigned int tagBytes;
1221
0
    unsigned char tag[MAX_BLOCK_SIZE];
1222
0
    const unsigned char *intag;
1223
0
    unsigned int len;
1224
0
    const CK_GCM_MESSAGE_PARAMS *gcmParams =
1225
0
        (const CK_GCM_MESSAGE_PARAMS *)params;
1226
1227
0
    PORT_Assert(blocksize == AES_BLOCK_SIZE);
1228
0
    if (blocksize != AES_BLOCK_SIZE) {
1229
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1230
0
        return SECFailure;
1231
0
    }
1232
1233
    /* paramLen comes all the way from the application layer, make sure
1234
     * it's correct */
1235
0
    if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
1236
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1237
0
        return SECFailure;
1238
0
    }
1239
    /* if we were initialized with the C_DecryptInit, we shouldn't be in this
1240
     * function */
1241
0
    if (gcm->ctr_context_init) {
1242
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1243
0
        return SECFailure;
1244
0
    }
1245
1246
0
    if (maxout < inlen) {
1247
0
        *outlen = inlen;
1248
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1249
0
        return SECFailure;
1250
0
    }
1251
1252
0
    rv = gcm_InitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
1253
0
                         gcmParams->ulTagBits, aad, aadLen);
1254
0
    if (rv != SECSuccess) {
1255
0
        return SECFailure;
1256
0
    }
1257
1258
0
    tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
1259
0
    intag = gcmParams->pTag;
1260
0
    PORT_Assert(tagBytes != 0);
1261
1262
    /* verify the block */
1263
0
    rv = gcmHash_Update(gcm->ghash_context, inbuf, inlen);
1264
0
    if (rv != SECSuccess) {
1265
0
        CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
1266
0
        return SECFailure;
1267
0
    }
1268
0
    rv = gcm_GetTag(gcm, tag, &len, AES_BLOCK_SIZE);
1269
0
    if (rv != SECSuccess) {
1270
0
        CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
1271
0
        return SECFailure;
1272
0
    }
1273
    /* Don't decrypt if we can't authenticate the encrypted data!
1274
     * This assumes that if tagBits is may not be a multiple of 8, intag will
1275
     * preserve the masked off missing bits.  */
1276
0
    if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) {
1277
        /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
1278
0
        CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
1279
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
1280
0
        PORT_SafeZero(tag, sizeof(tag));
1281
0
        return SECFailure;
1282
0
    }
1283
0
    PORT_SafeZero(tag, sizeof(tag));
1284
    /* finish the decryption */
1285
0
    rv = gcm_CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
1286
0
                        inbuf, inlen);
1287
0
    CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
1288
0
    return rv;
1289
0
}