Line data Source code
1 : /*
2 : * NIST SP800-38D compliant GCM implementation
3 : *
4 : * Copyright The Mbed TLS Contributors
5 : * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 : */
7 :
8 : /*
9 : * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
10 : *
11 : * See also:
12 : * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
13 : *
14 : * We use the algorithm described as Shoup's method with 4-bit tables in
15 : * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
16 : */
17 :
18 : #include "common.h"
19 :
20 : #if defined(MBEDTLS_GCM_C)
21 :
22 : #include "mbedtls/gcm.h"
23 : #include "mbedtls/platform.h"
24 : #include "mbedtls/platform_util.h"
25 : #include "mbedtls/error.h"
26 : #include "mbedtls/constant_time.h"
27 :
28 : #if defined(MBEDTLS_BLOCK_CIPHER_C)
29 : #include "block_cipher_internal.h"
30 : #endif
31 :
32 : #include <string.h>
33 :
34 : #if defined(MBEDTLS_AESNI_C)
35 : #include "aesni.h"
36 : #endif
37 :
38 : #if defined(MBEDTLS_AESCE_C)
39 : #include "aesce.h"
40 : #endif
41 :
42 : #if !defined(MBEDTLS_GCM_ALT)
43 :
44 : /* Used to select the acceleration mechanism */
45 : #define MBEDTLS_GCM_ACC_SMALLTABLE 0
46 : #define MBEDTLS_GCM_ACC_LARGETABLE 1
47 : #define MBEDTLS_GCM_ACC_AESNI 2
48 : #define MBEDTLS_GCM_ACC_AESCE 3
49 :
50 : /*
51 : * Initialize a context
52 : */
53 795 : void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
54 : {
55 795 : memset(ctx, 0, sizeof(mbedtls_gcm_context));
56 795 : }
57 :
58 795 : static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)
59 : {
60 : #if defined(MBEDTLS_GCM_LARGE_TABLE)
61 : ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE;
62 : #else
63 795 : ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE;
64 : #endif
65 :
66 : #if defined(MBEDTLS_AESNI_HAVE_CODE)
67 : /* With CLMUL support, we need only h, not the rest of the table */
68 795 : if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
69 795 : ctx->acceleration = MBEDTLS_GCM_ACC_AESNI;
70 : }
71 : #endif
72 :
73 : #if defined(MBEDTLS_AESCE_HAVE_CODE)
74 : if (MBEDTLS_AESCE_HAS_SUPPORT()) {
75 : ctx->acceleration = MBEDTLS_GCM_ACC_AESCE;
76 : }
77 : #endif
78 795 : }
79 :
80 0 : static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])
81 : {
82 0 : uint8_t *u8Dst = (uint8_t *) dst;
83 0 : uint8_t *u8Src = (uint8_t *) src;
84 :
85 0 : MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);
86 0 : u8Dst[8] |= (u8Src[7] & 0x01) << 7;
87 0 : MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);
88 0 : u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;
89 0 : }
90 :
91 : /*
92 : * Precompute small multiples of H, that is set
93 : * HH[i] || HL[i] = H times i,
94 : * where i is seen as a field element as in [MGV], ie high-order bits
95 : * correspond to low powers of P. The result is stored in the same way, that
96 : * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
97 : * corresponds to P^127.
98 : */
99 795 : static int gcm_gen_table(mbedtls_gcm_context *ctx)
100 : {
101 : int ret, i, j;
102 795 : uint64_t u64h[2] = { 0 };
103 795 : uint8_t *h = (uint8_t *) u64h;
104 :
105 : #if defined(MBEDTLS_BLOCK_CIPHER_C)
106 : ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
107 : #else
108 795 : size_t olen = 0;
109 795 : ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen);
110 : #endif
111 795 : if (ret != 0) {
112 0 : return ret;
113 : }
114 :
115 795 : gcm_set_acceleration(ctx);
116 :
117 : /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */
118 795 : ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];
119 795 : ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];
120 :
121 795 : switch (ctx->acceleration) {
122 : #if defined(MBEDTLS_AESNI_HAVE_CODE)
123 795 : case MBEDTLS_GCM_ACC_AESNI:
124 795 : return 0;
125 : #endif
126 :
127 : #if defined(MBEDTLS_AESCE_HAVE_CODE)
128 : case MBEDTLS_GCM_ACC_AESCE:
129 : return 0;
130 : #endif
131 :
132 0 : default:
133 : /* 0 corresponds to 0 in GF(2^128) */
134 0 : ctx->H[0][0] = 0;
135 0 : ctx->H[0][1] = 0;
136 :
137 0 : for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
138 0 : gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
139 : }
140 :
141 : #if !defined(MBEDTLS_GCM_LARGE_TABLE)
142 : /* pack elements of H as 64-bits ints, big-endian */
143 0 : for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {
144 0 : MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);
145 0 : MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);
146 : }
147 : #endif
148 :
149 0 : for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {
150 0 : for (j = 1; j < i; j++) {
151 0 : mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],
152 0 : (unsigned char *) ctx->H[i],
153 0 : (unsigned char *) ctx->H[j],
154 : 16);
155 : }
156 : }
157 : }
158 :
159 0 : return 0;
160 : }
161 :
162 795 : int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
163 : mbedtls_cipher_id_t cipher,
164 : const unsigned char *key,
165 : unsigned int keybits)
166 : {
167 795 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
168 :
169 795 : if (keybits != 128 && keybits != 192 && keybits != 256) {
170 0 : return MBEDTLS_ERR_GCM_BAD_INPUT;
171 : }
172 :
173 : #if defined(MBEDTLS_BLOCK_CIPHER_C)
174 : mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
175 :
176 : if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {
177 : return ret;
178 : }
179 :
180 : if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {
181 : return ret;
182 : }
183 : #else
184 : const mbedtls_cipher_info_t *cipher_info;
185 :
186 795 : cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
187 : MBEDTLS_MODE_ECB);
188 795 : if (cipher_info == NULL) {
189 0 : return MBEDTLS_ERR_GCM_BAD_INPUT;
190 : }
191 :
192 795 : if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
193 0 : return MBEDTLS_ERR_GCM_BAD_INPUT;
194 : }
195 :
196 795 : mbedtls_cipher_free(&ctx->cipher_ctx);
197 :
198 795 : if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
199 0 : return ret;
200 : }
201 :
202 795 : if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
203 : MBEDTLS_ENCRYPT)) != 0) {
204 0 : return ret;
205 : }
206 : #endif
207 :
208 795 : if ((ret = gcm_gen_table(ctx)) != 0) {
209 0 : return ret;
210 : }
211 :
212 795 : return 0;
213 : }
214 :
215 : #if defined(MBEDTLS_GCM_LARGE_TABLE)
216 : static const uint16_t last8[256] = {
217 : 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05,
218 : 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b,
219 : 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19,
220 : 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17,
221 : 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d,
222 : 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33,
223 : 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21,
224 : 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f,
225 : 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75,
226 : 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b,
227 : 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69,
228 : 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67,
229 : 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d,
230 : 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43,
231 : 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51,
232 : 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f,
233 : 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4,
234 : 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea,
235 : 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8,
236 : 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6,
237 : 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc,
238 : 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2,
239 : 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0,
240 : 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece,
241 : 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94,
242 : 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a,
243 : 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88,
244 : 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86,
245 : 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac,
246 : 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2,
247 : 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0,
248 : 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe
249 : };
250 :
251 : static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2])
252 : {
253 : int i;
254 : uint64_t u64z[2];
255 : uint16_t *u16z = (uint16_t *) u64z;
256 : uint8_t *u8z = (uint8_t *) u64z;
257 : uint8_t rem;
258 :
259 : u64z[0] = 0;
260 : u64z[1] = 0;
261 :
262 : if (MBEDTLS_IS_BIG_ENDIAN) {
263 : for (i = 15; i > 0; i--) {
264 : mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
265 : rem = u8z[15];
266 :
267 : u64z[1] >>= 8;
268 : u8z[8] = u8z[7];
269 : u64z[0] >>= 8;
270 :
271 : u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0);
272 : }
273 : } else {
274 : for (i = 15; i > 0; i--) {
275 : mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
276 : rem = u8z[15];
277 :
278 : u64z[1] <<= 8;
279 : u8z[8] = u8z[7];
280 : u64z[0] <<= 8;
281 :
282 : u16z[0] ^= last8[rem];
283 : }
284 : }
285 :
286 : mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);
287 : }
288 : #else
289 : /*
290 : * Shoup's method for multiplication use this table with
291 : * last4[x] = x times P^128
292 : * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
293 : */
294 : static const uint16_t last4[16] =
295 : {
296 : 0x0000, 0x1c20, 0x3840, 0x2460,
297 : 0x7080, 0x6ca0, 0x48c0, 0x54e0,
298 : 0xe100, 0xfd20, 0xd940, 0xc560,
299 : 0x9180, 0x8da0, 0xa9c0, 0xb5e0
300 : };
301 :
302 0 : static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])
303 : {
304 0 : int i = 0;
305 : unsigned char lo, hi, rem;
306 : uint64_t u64z[2];
307 0 : const uint64_t *pu64z = NULL;
308 0 : uint8_t *u8z = (uint8_t *) u64z;
309 :
310 0 : lo = x[15] & 0xf;
311 0 : hi = (x[15] >> 4) & 0xf;
312 :
313 0 : pu64z = H[lo];
314 :
315 0 : rem = (unsigned char) pu64z[1] & 0xf;
316 0 : u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);
317 0 : u64z[0] = (pu64z[0] >> 4);
318 0 : u64z[0] ^= (uint64_t) last4[rem] << 48;
319 0 : mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
320 :
321 0 : for (i = 14; i >= 0; i--) {
322 0 : lo = x[i] & 0xf;
323 0 : hi = (x[i] >> 4) & 0xf;
324 :
325 0 : rem = (unsigned char) u64z[1] & 0xf;
326 0 : u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
327 0 : u64z[0] = (u64z[0] >> 4);
328 0 : u64z[0] ^= (uint64_t) last4[rem] << 48;
329 0 : mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);
330 :
331 0 : rem = (unsigned char) u64z[1] & 0xf;
332 0 : u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
333 0 : u64z[0] = (u64z[0] >> 4);
334 0 : u64z[0] ^= (uint64_t) last4[rem] << 48;
335 0 : mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
336 : }
337 :
338 0 : MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);
339 0 : MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);
340 0 : }
341 : #endif
342 :
343 : /*
344 : * Sets output to x times H using the precomputed tables.
345 : * x and output are seen as elements of GF(2^128) as in [MGV].
346 : */
347 3624 : static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
348 : unsigned char output[16])
349 : {
350 3624 : switch (ctx->acceleration) {
351 : #if defined(MBEDTLS_AESNI_HAVE_CODE)
352 3624 : case MBEDTLS_GCM_ACC_AESNI:
353 3624 : mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
354 3624 : break;
355 : #endif
356 :
357 : #if defined(MBEDTLS_AESCE_HAVE_CODE)
358 : case MBEDTLS_GCM_ACC_AESCE:
359 : mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
360 : break;
361 : #endif
362 :
363 : #if defined(MBEDTLS_GCM_LARGE_TABLE)
364 : case MBEDTLS_GCM_ACC_LARGETABLE:
365 : gcm_mult_largetable(output, x, ctx->H);
366 : break;
367 : #else
368 0 : case MBEDTLS_GCM_ACC_SMALLTABLE:
369 0 : gcm_mult_smalltable(output, x, ctx->H);
370 0 : break;
371 : #endif
372 : }
373 :
374 3624 : return;
375 : }
376 :
377 795 : int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
378 : int mode,
379 : const unsigned char *iv, size_t iv_len)
380 : {
381 795 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
382 : unsigned char work_buf[16];
383 : const unsigned char *p;
384 : size_t use_len;
385 : uint64_t iv_bits;
386 : #if !defined(MBEDTLS_BLOCK_CIPHER_C)
387 795 : size_t olen = 0;
388 : #endif
389 :
390 : /* IV is limited to 2^64 bits, so 2^61 bytes */
391 : /* IV is not allowed to be zero length */
392 795 : if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
393 0 : return MBEDTLS_ERR_GCM_BAD_INPUT;
394 : }
395 :
396 795 : memset(ctx->y, 0x00, sizeof(ctx->y));
397 795 : memset(ctx->buf, 0x00, sizeof(ctx->buf));
398 :
399 795 : ctx->mode = mode;
400 795 : ctx->len = 0;
401 795 : ctx->add_len = 0;
402 :
403 795 : if (iv_len == 12) {
404 795 : memcpy(ctx->y, iv, iv_len);
405 795 : ctx->y[15] = 1;
406 : } else {
407 0 : memset(work_buf, 0x00, 16);
408 0 : iv_bits = (uint64_t) iv_len * 8;
409 0 : MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
410 :
411 0 : p = iv;
412 0 : while (iv_len > 0) {
413 0 : use_len = (iv_len < 16) ? iv_len : 16;
414 :
415 : #if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
416 : #pragma GCC diagnostic push
417 : #pragma GCC diagnostic warning "-Wstringop-overflow=0"
418 : #endif
419 :
420 0 : mbedtls_xor(ctx->y, ctx->y, p, use_len);
421 :
422 : #if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
423 : #pragma GCC diagnostic pop
424 : #endif
425 :
426 0 : gcm_mult(ctx, ctx->y, ctx->y);
427 :
428 0 : iv_len -= use_len;
429 0 : p += use_len;
430 : }
431 :
432 0 : mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
433 :
434 0 : gcm_mult(ctx, ctx->y, ctx->y);
435 : }
436 :
437 :
438 : #if defined(MBEDTLS_BLOCK_CIPHER_C)
439 : ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr);
440 : #else
441 795 : ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);
442 : #endif
443 795 : if (ret != 0) {
444 0 : return ret;
445 : }
446 :
447 795 : return 0;
448 : }
449 :
450 : /**
451 : * mbedtls_gcm_context::buf contains the partial state of the computation of
452 : * the authentication tag.
453 : * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
454 : * different stages of the computation:
455 : * * len == 0 && add_len == 0: initial state
456 : * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
457 : * a partial block of AD that has been
458 : * xored in but not yet multiplied in.
459 : * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
460 : * the data ends now.
461 : * * len % 16 != 0: the first `len % 16` bytes have
462 : * a partial block of ciphertext that has
463 : * been xored in but not yet multiplied in.
464 : * * len > 0 && len % 16 == 0: the authentication tag is correct if
465 : * the data ends now.
466 : */
467 795 : int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
468 : const unsigned char *add, size_t add_len)
469 : {
470 : const unsigned char *p;
471 : size_t use_len, offset;
472 : uint64_t new_add_len;
473 :
474 : /* AD is limited to 2^64 bits, ie 2^61 bytes
475 : * Also check for possible overflow */
476 : #if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
477 : if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
478 : return MBEDTLS_ERR_GCM_BAD_INPUT;
479 : }
480 : #endif
481 795 : new_add_len = ctx->add_len + (uint64_t) add_len;
482 795 : if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
483 0 : return MBEDTLS_ERR_GCM_BAD_INPUT;
484 : }
485 :
486 795 : offset = ctx->add_len % 16;
487 795 : p = add;
488 :
489 795 : if (offset != 0) {
490 0 : use_len = 16 - offset;
491 0 : if (use_len > add_len) {
492 0 : use_len = add_len;
493 : }
494 :
495 0 : mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
496 :
497 0 : if (offset + use_len == 16) {
498 0 : gcm_mult(ctx, ctx->buf, ctx->buf);
499 : }
500 :
501 0 : ctx->add_len += use_len;
502 0 : add_len -= use_len;
503 0 : p += use_len;
504 : }
505 :
506 795 : ctx->add_len += add_len;
507 :
508 799 : while (add_len >= 16) {
509 4 : mbedtls_xor(ctx->buf, ctx->buf, p, 16);
510 :
511 4 : gcm_mult(ctx, ctx->buf, ctx->buf);
512 :
513 4 : add_len -= 16;
514 4 : p += 16;
515 : }
516 :
517 795 : if (add_len > 0) {
518 795 : mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
519 : }
520 :
521 795 : return 0;
522 : }
523 :
524 : /* Increment the counter. */
525 2030 : static void gcm_incr(unsigned char y[16])
526 : {
527 2030 : uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);
528 2030 : x++;
529 2030 : MBEDTLS_PUT_UINT32_BE(x, y, 12);
530 2030 : }
531 :
532 : /* Calculate and apply the encryption mask. Process use_len bytes of data,
533 : * starting at position offset in the mask block. */
534 2030 : static int gcm_mask(mbedtls_gcm_context *ctx,
535 : unsigned char ectr[16],
536 : size_t offset, size_t use_len,
537 : const unsigned char *input,
538 : unsigned char *output)
539 : {
540 2030 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
541 :
542 : #if defined(MBEDTLS_BLOCK_CIPHER_C)
543 : ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);
544 : #else
545 2030 : size_t olen = 0;
546 2030 : ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);
547 : #endif
548 2030 : if (ret != 0) {
549 0 : mbedtls_platform_zeroize(ectr, 16);
550 0 : return ret;
551 : }
552 :
553 2030 : if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
554 846 : mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
555 : }
556 2030 : mbedtls_xor(output, ectr + offset, input, use_len);
557 2030 : if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
558 1184 : mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
559 : }
560 :
561 2030 : return 0;
562 : }
563 :
564 795 : int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
565 : const unsigned char *input, size_t input_length,
566 : unsigned char *output, size_t output_size,
567 : size_t *output_length)
568 : {
569 795 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
570 795 : const unsigned char *p = input;
571 795 : unsigned char *out_p = output;
572 : size_t offset;
573 795 : unsigned char ectr[16] = { 0 };
574 :
575 795 : if (output_size < input_length) {
576 0 : return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
577 : }
578 795 : *output_length = input_length;
579 :
580 : /* Exit early if input_length==0 so that we don't do any pointer arithmetic
581 : * on a potentially null pointer.
582 : * Returning early also means that the last partial block of AD remains
583 : * untouched for mbedtls_gcm_finish */
584 795 : if (input_length == 0) {
585 0 : return 0;
586 : }
587 :
588 795 : if (output > input && (size_t) (output - input) < input_length) {
589 0 : return MBEDTLS_ERR_GCM_BAD_INPUT;
590 : }
591 :
592 : /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
593 : * Also check for possible overflow */
594 795 : if (ctx->len + input_length < ctx->len ||
595 795 : (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
596 0 : return MBEDTLS_ERR_GCM_BAD_INPUT;
597 : }
598 :
599 795 : if (ctx->len == 0 && ctx->add_len % 16 != 0) {
600 795 : gcm_mult(ctx, ctx->buf, ctx->buf);
601 : }
602 :
603 795 : offset = ctx->len % 16;
604 795 : if (offset != 0) {
605 0 : size_t use_len = 16 - offset;
606 0 : if (use_len > input_length) {
607 0 : use_len = input_length;
608 : }
609 :
610 0 : if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
611 0 : return ret;
612 : }
613 :
614 0 : if (offset + use_len == 16) {
615 0 : gcm_mult(ctx, ctx->buf, ctx->buf);
616 : }
617 :
618 0 : ctx->len += use_len;
619 0 : input_length -= use_len;
620 0 : p += use_len;
621 0 : out_p += use_len;
622 : }
623 :
624 795 : ctx->len += input_length;
625 :
626 2091 : while (input_length >= 16) {
627 1296 : gcm_incr(ctx->y);
628 1296 : if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
629 0 : return ret;
630 : }
631 :
632 1296 : gcm_mult(ctx, ctx->buf, ctx->buf);
633 :
634 1296 : input_length -= 16;
635 1296 : p += 16;
636 1296 : out_p += 16;
637 : }
638 :
639 795 : if (input_length > 0) {
640 734 : gcm_incr(ctx->y);
641 734 : if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
642 0 : return ret;
643 : }
644 : }
645 :
646 795 : mbedtls_platform_zeroize(ectr, sizeof(ectr));
647 795 : return 0;
648 : }
649 :
650 795 : int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
651 : unsigned char *output, size_t output_size,
652 : size_t *output_length,
653 : unsigned char *tag, size_t tag_len)
654 : {
655 : unsigned char work_buf[16];
656 : uint64_t orig_len;
657 : uint64_t orig_add_len;
658 :
659 : /* We never pass any output in finish(). The output parameter exists only
660 : * for the sake of alternative implementations. */
661 : (void) output;
662 : (void) output_size;
663 795 : *output_length = 0;
664 :
665 : /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
666 : * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
667 : * the two multiplications would overflow. */
668 795 : orig_len = ctx->len * 8;
669 795 : orig_add_len = ctx->add_len * 8;
670 :
671 795 : if (ctx->len == 0 && ctx->add_len % 16 != 0) {
672 0 : gcm_mult(ctx, ctx->buf, ctx->buf);
673 : }
674 :
675 795 : if (tag_len > 16 || tag_len < 4) {
676 0 : return MBEDTLS_ERR_GCM_BAD_INPUT;
677 : }
678 :
679 795 : if (ctx->len % 16 != 0) {
680 734 : gcm_mult(ctx, ctx->buf, ctx->buf);
681 : }
682 :
683 795 : memcpy(tag, ctx->base_ectr, tag_len);
684 :
685 795 : if (orig_len || orig_add_len) {
686 795 : memset(work_buf, 0x00, 16);
687 :
688 795 : MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
689 795 : MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
690 795 : MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
691 795 : MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
692 :
693 795 : mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
694 :
695 795 : gcm_mult(ctx, ctx->buf, ctx->buf);
696 :
697 795 : mbedtls_xor(tag, tag, ctx->buf, tag_len);
698 : }
699 :
700 795 : return 0;
701 : }
702 :
703 795 : int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
704 : int mode,
705 : size_t length,
706 : const unsigned char *iv,
707 : size_t iv_len,
708 : const unsigned char *add,
709 : size_t add_len,
710 : const unsigned char *input,
711 : unsigned char *output,
712 : size_t tag_len,
713 : unsigned char *tag)
714 : {
715 795 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
716 : size_t olen;
717 :
718 795 : if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
719 0 : return ret;
720 : }
721 :
722 795 : if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
723 0 : return ret;
724 : }
725 :
726 795 : if ((ret = mbedtls_gcm_update(ctx, input, length,
727 : output, length, &olen)) != 0) {
728 0 : return ret;
729 : }
730 :
731 795 : if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
732 0 : return ret;
733 : }
734 :
735 795 : return 0;
736 : }
737 :
738 328 : int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
739 : size_t length,
740 : const unsigned char *iv,
741 : size_t iv_len,
742 : const unsigned char *add,
743 : size_t add_len,
744 : const unsigned char *tag,
745 : size_t tag_len,
746 : const unsigned char *input,
747 : unsigned char *output)
748 : {
749 328 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
750 : unsigned char check_tag[16];
751 : int diff;
752 :
753 328 : if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
754 : iv, iv_len, add, add_len,
755 : input, output, tag_len, check_tag)) != 0) {
756 0 : return ret;
757 : }
758 :
759 : /* Check tag in "constant-time" */
760 328 : diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
761 :
762 328 : if (diff != 0) {
763 27 : mbedtls_platform_zeroize(output, length);
764 27 : return MBEDTLS_ERR_GCM_AUTH_FAILED;
765 : }
766 :
767 301 : return 0;
768 : }
769 :
770 795 : void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
771 : {
772 795 : if (ctx == NULL) {
773 0 : return;
774 : }
775 : #if defined(MBEDTLS_BLOCK_CIPHER_C)
776 : mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
777 : #else
778 795 : mbedtls_cipher_free(&ctx->cipher_ctx);
779 : #endif
780 795 : mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
781 : }
782 :
783 : #endif /* !MBEDTLS_GCM_ALT */
784 :
785 : #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
786 : /*
787 : * AES-GCM test vectors from:
788 : *
789 : * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
790 : */
791 : #define MAX_TESTS 6
792 :
793 : static const int key_index_test_data[MAX_TESTS] =
794 : { 0, 0, 1, 1, 1, 1 };
795 :
796 : static const unsigned char key_test_data[][32] =
797 : {
798 : { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
800 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
801 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
802 : { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
803 : 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
804 : 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
805 : 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
806 : };
807 :
808 : static const size_t iv_len_test_data[MAX_TESTS] =
809 : { 12, 12, 12, 12, 8, 60 };
810 :
811 : static const int iv_index_test_data[MAX_TESTS] =
812 : { 0, 0, 1, 1, 1, 2 };
813 :
814 : static const unsigned char iv_test_data[][64] =
815 : {
816 : { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 : 0x00, 0x00, 0x00, 0x00 },
818 : { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
819 : 0xde, 0xca, 0xf8, 0x88 },
820 : { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
821 : 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
822 : 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
823 : 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
824 : 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
825 : 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
826 : 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
827 : 0xa6, 0x37, 0xb3, 0x9b },
828 : };
829 :
830 : static const size_t add_len_test_data[MAX_TESTS] =
831 : { 0, 0, 0, 20, 20, 20 };
832 :
833 : static const int add_index_test_data[MAX_TESTS] =
834 : { 0, 0, 0, 1, 1, 1 };
835 :
836 : static const unsigned char additional_test_data[][64] =
837 : {
838 : { 0x00 },
839 : { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
840 : 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
841 : 0xab, 0xad, 0xda, 0xd2 },
842 : };
843 :
844 : static const size_t pt_len_test_data[MAX_TESTS] =
845 : { 0, 16, 64, 60, 60, 60 };
846 :
847 : static const int pt_index_test_data[MAX_TESTS] =
848 : { 0, 0, 1, 1, 1, 1 };
849 :
850 : static const unsigned char pt_test_data[][64] =
851 : {
852 : { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
854 : { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
855 : 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
856 : 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
857 : 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
858 : 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
859 : 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
860 : 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
861 : 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
862 : };
863 :
864 : static const unsigned char ct_test_data[][64] =
865 : {
866 : { 0x00 },
867 : { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
868 : 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
869 : { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
870 : 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
871 : 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
872 : 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
873 : 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
874 : 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
875 : 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
876 : 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
877 : { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
878 : 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
879 : 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
880 : 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
881 : 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
882 : 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
883 : 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
884 : 0x3d, 0x58, 0xe0, 0x91 },
885 : { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
886 : 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
887 : 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
888 : 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
889 : 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
890 : 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
891 : 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
892 : 0xc2, 0x3f, 0x45, 0x98 },
893 : { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
894 : 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
895 : 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
896 : 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
897 : 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
898 : 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
899 : 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
900 : 0x4c, 0x34, 0xae, 0xe5 },
901 : #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
902 : { 0x00 },
903 : { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
904 : 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
905 : { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
906 : 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
907 : 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
908 : 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
909 : 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
910 : 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
911 : 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
912 : 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
913 : { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
914 : 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
915 : 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
916 : 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
917 : 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
918 : 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
919 : 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
920 : 0xcc, 0xda, 0x27, 0x10 },
921 : { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
922 : 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
923 : 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
924 : 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
925 : 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
926 : 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
927 : 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
928 : 0xa0, 0xf0, 0x62, 0xf7 },
929 : { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
930 : 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
931 : 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
932 : 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
933 : 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
934 : 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
935 : 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
936 : 0xe9, 0xb7, 0x37, 0x3b },
937 : { 0x00 },
938 : { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
939 : 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
940 : { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
941 : 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
942 : 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
943 : 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
944 : 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
945 : 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
946 : 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
947 : 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
948 : { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
949 : 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
950 : 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
951 : 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
952 : 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
953 : 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
954 : 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
955 : 0xbc, 0xc9, 0xf6, 0x62 },
956 : { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
957 : 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
958 : 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
959 : 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
960 : 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
961 : 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
962 : 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
963 : 0xf4, 0x7c, 0x9b, 0x1f },
964 : { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
965 : 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
966 : 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
967 : 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
968 : 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
969 : 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
970 : 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
971 : 0x44, 0xae, 0x7e, 0x3f },
972 : #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
973 : };
974 :
975 : static const unsigned char tag_test_data[][16] =
976 : {
977 : { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
978 : 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
979 : { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
980 : 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
981 : { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
982 : 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
983 : { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
984 : 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
985 : { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
986 : 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
987 : { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
988 : 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
989 : #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
990 : { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
991 : 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
992 : { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
993 : 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
994 : { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
995 : 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
996 : { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
997 : 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
998 : { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
999 : 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
1000 : { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
1001 : 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
1002 : { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
1003 : 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
1004 : { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
1005 : 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
1006 : { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
1007 : 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
1008 : { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
1009 : 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
1010 : { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
1011 : 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
1012 : { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
1013 : 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
1014 : #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
1015 : };
1016 :
1017 0 : int mbedtls_gcm_self_test(int verbose)
1018 : {
1019 : mbedtls_gcm_context ctx;
1020 : unsigned char buf[64];
1021 : unsigned char tag_buf[16];
1022 : int i, j, ret;
1023 0 : mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
1024 : size_t olen;
1025 :
1026 0 : if (verbose != 0) {
1027 : #if defined(MBEDTLS_GCM_ALT)
1028 : mbedtls_printf(" GCM note: alternative implementation.\n");
1029 : #else /* MBEDTLS_GCM_ALT */
1030 : #if defined(MBEDTLS_AESNI_HAVE_CODE)
1031 0 : if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
1032 0 : mbedtls_printf(" GCM note: using AESNI.\n");
1033 : } else
1034 : #endif
1035 :
1036 : #if defined(MBEDTLS_AESCE_HAVE_CODE)
1037 : if (MBEDTLS_AESCE_HAS_SUPPORT()) {
1038 : mbedtls_printf(" GCM note: using AESCE.\n");
1039 : } else
1040 : #endif
1041 :
1042 0 : mbedtls_printf(" GCM note: built-in implementation.\n");
1043 : #endif /* MBEDTLS_GCM_ALT */
1044 : }
1045 :
1046 : static const int loop_limit =
1047 : (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
1048 :
1049 0 : for (j = 0; j < loop_limit; j++) {
1050 0 : int key_len = 128 + 64 * j;
1051 :
1052 0 : for (i = 0; i < MAX_TESTS; i++) {
1053 0 : if (verbose != 0) {
1054 0 : mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1055 : key_len, i, "enc");
1056 : }
1057 :
1058 0 : mbedtls_gcm_init(&ctx);
1059 :
1060 0 : ret = mbedtls_gcm_setkey(&ctx, cipher,
1061 0 : key_test_data[key_index_test_data[i]],
1062 : key_len);
1063 : /*
1064 : * AES-192 is an optional feature that may be unavailable when
1065 : * there is an alternative underlying implementation i.e. when
1066 : * MBEDTLS_AES_ALT is defined.
1067 : */
1068 0 : if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
1069 0 : mbedtls_printf("skipped\n");
1070 0 : break;
1071 0 : } else if (ret != 0) {
1072 0 : goto exit;
1073 : }
1074 :
1075 0 : ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
1076 0 : pt_len_test_data[i],
1077 0 : iv_test_data[iv_index_test_data[i]],
1078 0 : iv_len_test_data[i],
1079 0 : additional_test_data[add_index_test_data[i]],
1080 0 : add_len_test_data[i],
1081 0 : pt_test_data[pt_index_test_data[i]],
1082 : buf, 16, tag_buf);
1083 : #if defined(MBEDTLS_GCM_ALT)
1084 : /* Allow alternative implementations to only support 12-byte nonces. */
1085 : if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
1086 : iv_len_test_data[i] != 12) {
1087 : mbedtls_printf("skipped\n");
1088 : break;
1089 : }
1090 : #endif /* defined(MBEDTLS_GCM_ALT) */
1091 0 : if (ret != 0) {
1092 0 : goto exit;
1093 : }
1094 :
1095 0 : if (memcmp(buf, ct_test_data[j * 6 + i],
1096 0 : pt_len_test_data[i]) != 0 ||
1097 0 : memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
1098 0 : ret = 1;
1099 0 : goto exit;
1100 : }
1101 :
1102 0 : mbedtls_gcm_free(&ctx);
1103 :
1104 0 : if (verbose != 0) {
1105 0 : mbedtls_printf("passed\n");
1106 : }
1107 :
1108 0 : mbedtls_gcm_init(&ctx);
1109 :
1110 0 : if (verbose != 0) {
1111 0 : mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1112 : key_len, i, "dec");
1113 : }
1114 :
1115 0 : ret = mbedtls_gcm_setkey(&ctx, cipher,
1116 0 : key_test_data[key_index_test_data[i]],
1117 : key_len);
1118 0 : if (ret != 0) {
1119 0 : goto exit;
1120 : }
1121 :
1122 0 : ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
1123 0 : pt_len_test_data[i],
1124 0 : iv_test_data[iv_index_test_data[i]],
1125 0 : iv_len_test_data[i],
1126 0 : additional_test_data[add_index_test_data[i]],
1127 0 : add_len_test_data[i],
1128 0 : ct_test_data[j * 6 + i], buf, 16, tag_buf);
1129 :
1130 0 : if (ret != 0) {
1131 0 : goto exit;
1132 : }
1133 :
1134 0 : if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1135 0 : pt_len_test_data[i]) != 0 ||
1136 0 : memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
1137 0 : ret = 1;
1138 0 : goto exit;
1139 : }
1140 :
1141 0 : mbedtls_gcm_free(&ctx);
1142 :
1143 0 : if (verbose != 0) {
1144 0 : mbedtls_printf("passed\n");
1145 : }
1146 :
1147 0 : mbedtls_gcm_init(&ctx);
1148 :
1149 0 : if (verbose != 0) {
1150 0 : mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1151 : key_len, i, "enc");
1152 : }
1153 :
1154 0 : ret = mbedtls_gcm_setkey(&ctx, cipher,
1155 0 : key_test_data[key_index_test_data[i]],
1156 : key_len);
1157 0 : if (ret != 0) {
1158 0 : goto exit;
1159 : }
1160 :
1161 0 : ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1162 0 : iv_test_data[iv_index_test_data[i]],
1163 0 : iv_len_test_data[i]);
1164 0 : if (ret != 0) {
1165 0 : goto exit;
1166 : }
1167 :
1168 0 : ret = mbedtls_gcm_update_ad(&ctx,
1169 0 : additional_test_data[add_index_test_data[i]],
1170 0 : add_len_test_data[i]);
1171 0 : if (ret != 0) {
1172 0 : goto exit;
1173 : }
1174 :
1175 0 : if (pt_len_test_data[i] > 32) {
1176 0 : size_t rest_len = pt_len_test_data[i] - 32;
1177 0 : ret = mbedtls_gcm_update(&ctx,
1178 0 : pt_test_data[pt_index_test_data[i]],
1179 : 32,
1180 : buf, sizeof(buf), &olen);
1181 0 : if (ret != 0) {
1182 0 : goto exit;
1183 : }
1184 0 : if (olen != 32) {
1185 0 : goto exit;
1186 : }
1187 :
1188 0 : ret = mbedtls_gcm_update(&ctx,
1189 0 : pt_test_data[pt_index_test_data[i]] + 32,
1190 : rest_len,
1191 : buf + 32, sizeof(buf) - 32, &olen);
1192 0 : if (ret != 0) {
1193 0 : goto exit;
1194 : }
1195 0 : if (olen != rest_len) {
1196 0 : goto exit;
1197 : }
1198 : } else {
1199 0 : ret = mbedtls_gcm_update(&ctx,
1200 0 : pt_test_data[pt_index_test_data[i]],
1201 0 : pt_len_test_data[i],
1202 : buf, sizeof(buf), &olen);
1203 0 : if (ret != 0) {
1204 0 : goto exit;
1205 : }
1206 0 : if (olen != pt_len_test_data[i]) {
1207 0 : goto exit;
1208 : }
1209 : }
1210 :
1211 0 : ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1212 0 : if (ret != 0) {
1213 0 : goto exit;
1214 : }
1215 :
1216 0 : if (memcmp(buf, ct_test_data[j * 6 + i],
1217 0 : pt_len_test_data[i]) != 0 ||
1218 0 : memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
1219 0 : ret = 1;
1220 0 : goto exit;
1221 : }
1222 :
1223 0 : mbedtls_gcm_free(&ctx);
1224 :
1225 0 : if (verbose != 0) {
1226 0 : mbedtls_printf("passed\n");
1227 : }
1228 :
1229 0 : mbedtls_gcm_init(&ctx);
1230 :
1231 0 : if (verbose != 0) {
1232 0 : mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1233 : key_len, i, "dec");
1234 : }
1235 :
1236 0 : ret = mbedtls_gcm_setkey(&ctx, cipher,
1237 0 : key_test_data[key_index_test_data[i]],
1238 : key_len);
1239 0 : if (ret != 0) {
1240 0 : goto exit;
1241 : }
1242 :
1243 0 : ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1244 0 : iv_test_data[iv_index_test_data[i]],
1245 0 : iv_len_test_data[i]);
1246 0 : if (ret != 0) {
1247 0 : goto exit;
1248 : }
1249 0 : ret = mbedtls_gcm_update_ad(&ctx,
1250 0 : additional_test_data[add_index_test_data[i]],
1251 0 : add_len_test_data[i]);
1252 0 : if (ret != 0) {
1253 0 : goto exit;
1254 : }
1255 :
1256 0 : if (pt_len_test_data[i] > 32) {
1257 0 : size_t rest_len = pt_len_test_data[i] - 32;
1258 0 : ret = mbedtls_gcm_update(&ctx,
1259 0 : ct_test_data[j * 6 + i], 32,
1260 : buf, sizeof(buf), &olen);
1261 0 : if (ret != 0) {
1262 0 : goto exit;
1263 : }
1264 0 : if (olen != 32) {
1265 0 : goto exit;
1266 : }
1267 :
1268 0 : ret = mbedtls_gcm_update(&ctx,
1269 0 : ct_test_data[j * 6 + i] + 32,
1270 : rest_len,
1271 : buf + 32, sizeof(buf) - 32, &olen);
1272 0 : if (ret != 0) {
1273 0 : goto exit;
1274 : }
1275 0 : if (olen != rest_len) {
1276 0 : goto exit;
1277 : }
1278 : } else {
1279 0 : ret = mbedtls_gcm_update(&ctx,
1280 0 : ct_test_data[j * 6 + i],
1281 0 : pt_len_test_data[i],
1282 : buf, sizeof(buf), &olen);
1283 0 : if (ret != 0) {
1284 0 : goto exit;
1285 : }
1286 0 : if (olen != pt_len_test_data[i]) {
1287 0 : goto exit;
1288 : }
1289 : }
1290 :
1291 0 : ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1292 0 : if (ret != 0) {
1293 0 : goto exit;
1294 : }
1295 :
1296 0 : if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1297 0 : pt_len_test_data[i]) != 0 ||
1298 0 : memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
1299 0 : ret = 1;
1300 0 : goto exit;
1301 : }
1302 :
1303 0 : mbedtls_gcm_free(&ctx);
1304 :
1305 0 : if (verbose != 0) {
1306 0 : mbedtls_printf("passed\n");
1307 : }
1308 : }
1309 : }
1310 :
1311 0 : if (verbose != 0) {
1312 0 : mbedtls_printf("\n");
1313 : }
1314 :
1315 0 : ret = 0;
1316 :
1317 0 : exit:
1318 0 : if (ret != 0) {
1319 0 : if (verbose != 0) {
1320 0 : mbedtls_printf("failed\n");
1321 : }
1322 0 : mbedtls_gcm_free(&ctx);
1323 : }
1324 :
1325 0 : return ret;
1326 : }
1327 :
1328 : #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
1329 :
1330 : #endif /* MBEDTLS_GCM_C */
|