Coverage Report

Created: 2026-02-18 06:59

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