Coverage Report

Created: 2024-11-21 07:03

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