blob: 5dfac2349c82cbf1d3789370d332a79b50d3a549 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
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
Jerome Forissier79013242021-07-28 10:24:04 +020018#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020019
20#if defined(MBEDTLS_GCM_C)
21
22#include "mbedtls/gcm.h"
Jens Wiklander32b31802023-10-06 16:59:46 +020023#include "mbedtls/platform.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010024#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020025#include "mbedtls/error.h"
Tom Van Eyckc1633172024-04-09 18:44:13 +020026#include "mbedtls/constant_time.h"
27
28#if defined(MBEDTLS_BLOCK_CIPHER_C)
29#include "block_cipher_internal.h"
30#endif
Jens Wiklander817466c2018-05-22 13:49:31 +020031
32#include <string.h>
33
34#if defined(MBEDTLS_AESNI_C)
Jens Wiklander32b31802023-10-06 16:59:46 +020035#include "aesni.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020036#endif
37
Jens Wiklander32b31802023-10-06 16:59:46 +020038#if defined(MBEDTLS_AESCE_C)
39#include "aesce.h"
40#endif
Jens Wiklander817466c2018-05-22 13:49:31 +020041
Jens Wiklander3d3b0592019-03-20 15:30:29 +010042#if !defined(MBEDTLS_GCM_ALT)
43
Tom Van Eyckc1633172024-04-09 18:44:13 +020044/* 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
Jens Wiklander817466c2018-05-22 13:49:31 +020050/*
Jens Wiklander817466c2018-05-22 13:49:31 +020051 * Initialize a context
52 */
Jens Wiklander32b31802023-10-06 16:59:46 +020053void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020054{
Jens Wiklander32b31802023-10-06 16:59:46 +020055 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Jens Wiklander817466c2018-05-22 13:49:31 +020056}
57
Tom Van Eyckc1633172024-04-09 18:44:13 +020058static 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 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 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
69 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}
79
80static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])
81{
82 uint8_t *u8Dst = (uint8_t *) dst;
83 uint8_t *u8Src = (uint8_t *) src;
84
85 MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);
86 u8Dst[8] |= (u8Src[7] & 0x01) << 7;
87 MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);
88 u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;
89}
90
Jens Wiklander817466c2018-05-22 13:49:31 +020091/*
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 */
Jens Wiklander32b31802023-10-06 16:59:46 +020099static int gcm_gen_table(mbedtls_gcm_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200100{
101 int ret, i, j;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200102 uint64_t u64h[2] = { 0 };
103 uint8_t *h = (uint8_t *) u64h;
Jens Wiklander817466c2018-05-22 13:49:31 +0200104
Tom Van Eyckc1633172024-04-09 18:44:13 +0200105#if defined(MBEDTLS_BLOCK_CIPHER_C)
106 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
107#else
108 size_t olen = 0;
109 ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen);
110#endif
111 if (ret != 0) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200112 return ret;
113 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200114
Tom Van Eyckc1633172024-04-09 18:44:13 +0200115 gcm_set_acceleration(ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200116
Tom Van Eyckc1633172024-04-09 18:44:13 +0200117 /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */
118 ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];
119 ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];
Jens Wiklander817466c2018-05-22 13:49:31 +0200120
Tom Van Eyckc1633172024-04-09 18:44:13 +0200121 switch (ctx->acceleration) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200122#if defined(MBEDTLS_AESNI_HAVE_CODE)
Tom Van Eyckc1633172024-04-09 18:44:13 +0200123 case MBEDTLS_GCM_ACC_AESNI:
124 return 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200125#endif
126
Tom Van Eyckc1633172024-04-09 18:44:13 +0200127#if defined(MBEDTLS_AESCE_HAVE_CODE)
128 case MBEDTLS_GCM_ACC_AESCE:
129 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200130#endif
131
Tom Van Eyckc1633172024-04-09 18:44:13 +0200132 default:
133 /* 0 corresponds to 0 in GF(2^128) */
134 ctx->H[0][0] = 0;
135 ctx->H[0][1] = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200136
Tom Van Eyckc1633172024-04-09 18:44:13 +0200137 for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
138 gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
139 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200140
Tom Van Eyckc1633172024-04-09 18:44:13 +0200141#if !defined(MBEDTLS_GCM_LARGE_TABLE)
142 /* pack elements of H as 64-bits ints, big-endian */
143 for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {
144 MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);
145 MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);
146 }
147#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200148
Tom Van Eyckc1633172024-04-09 18:44:13 +0200149 for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {
150 for (j = 1; j < i; j++) {
151 mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],
152 (unsigned char *) ctx->H[i],
153 (unsigned char *) ctx->H[j],
154 16);
155 }
156 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200157 }
158
Jens Wiklander32b31802023-10-06 16:59:46 +0200159 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200160}
161
Jens Wiklander32b31802023-10-06 16:59:46 +0200162int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
163 mbedtls_cipher_id_t cipher,
164 const unsigned char *key,
165 unsigned int keybits)
Jens Wiklander817466c2018-05-22 13:49:31 +0200166{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200167 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200168
Jens Wiklander32b31802023-10-06 16:59:46 +0200169 if (keybits != 128 && keybits != 192 && keybits != 256) {
170 return MBEDTLS_ERR_GCM_BAD_INPUT;
Jens Wiklander817466c2018-05-22 13:49:31 +0200171 }
172
Tom Van Eyckc1633172024-04-09 18:44:13 +0200173#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
Jens Wiklander32b31802023-10-06 16:59:46 +0200186 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
187 MBEDTLS_MODE_ECB);
188 if (cipher_info == NULL) {
189 return MBEDTLS_ERR_GCM_BAD_INPUT;
190 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200191
Tom Van Eyckc1633172024-04-09 18:44:13 +0200192 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200193 return MBEDTLS_ERR_GCM_BAD_INPUT;
194 }
195
196 mbedtls_cipher_free(&ctx->cipher_ctx);
197
198 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
199 return ret;
200 }
201
202 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
203 MBEDTLS_ENCRYPT)) != 0) {
204 return ret;
205 }
Tom Van Eyckc1633172024-04-09 18:44:13 +0200206#endif
Jens Wiklander32b31802023-10-06 16:59:46 +0200207
208 if ((ret = gcm_gen_table(ctx)) != 0) {
209 return ret;
210 }
211
212 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200213}
214
Tom Van Eyckc1633172024-04-09 18:44:13 +0200215#if defined(MBEDTLS_GCM_LARGE_TABLE)
216static 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
251static 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
Jens Wiklander817466c2018-05-22 13:49:31 +0200289/*
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 */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200294static const uint16_t last4[16] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200295{
296 0x0000, 0x1c20, 0x3840, 0x2460,
297 0x7080, 0x6ca0, 0x48c0, 0x54e0,
298 0xe100, 0xfd20, 0xd940, 0xc560,
299 0x9180, 0x8da0, 0xa9c0, 0xb5e0
300};
301
Tom Van Eyckc1633172024-04-09 18:44:13 +0200302static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])
303{
304 int i = 0;
305 unsigned char lo, hi, rem;
306 uint64_t u64z[2];
307 const uint64_t *pu64z = NULL;
308 uint8_t *u8z = (uint8_t *) u64z;
309
310 lo = x[15] & 0xf;
311 hi = (x[15] >> 4) & 0xf;
312
313 pu64z = H[lo];
314
315 rem = (unsigned char) pu64z[1] & 0xf;
316 u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);
317 u64z[0] = (pu64z[0] >> 4);
318 u64z[0] ^= (uint64_t) last4[rem] << 48;
319 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
320
321 for (i = 14; i >= 0; i--) {
322 lo = x[i] & 0xf;
323 hi = (x[i] >> 4) & 0xf;
324
325 rem = (unsigned char) u64z[1] & 0xf;
326 u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
327 u64z[0] = (u64z[0] >> 4);
328 u64z[0] ^= (uint64_t) last4[rem] << 48;
329 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);
330
331 rem = (unsigned char) u64z[1] & 0xf;
332 u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
333 u64z[0] = (u64z[0] >> 4);
334 u64z[0] ^= (uint64_t) last4[rem] << 48;
335 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
336 }
337
338 MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);
339 MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);
340}
341#endif
342
Jens Wiklander817466c2018-05-22 13:49:31 +0200343/*
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 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200347static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
348 unsigned char output[16])
Jens Wiklander817466c2018-05-22 13:49:31 +0200349{
Tom Van Eyckc1633172024-04-09 18:44:13 +0200350 switch (ctx->acceleration) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200351#if defined(MBEDTLS_AESNI_HAVE_CODE)
Tom Van Eyckc1633172024-04-09 18:44:13 +0200352 case MBEDTLS_GCM_ACC_AESNI:
353 mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
354 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200355#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200356
Tom Van Eyckc1633172024-04-09 18:44:13 +0200357#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
Jens Wiklander817466c2018-05-22 13:49:31 +0200362
Tom Van Eyckc1633172024-04-09 18:44:13 +0200363#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 case MBEDTLS_GCM_ACC_SMALLTABLE:
369 gcm_mult_smalltable(output, x, ctx->H);
370 break;
371#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200372 }
373
Tom Van Eyckc1633172024-04-09 18:44:13 +0200374 return;
Jens Wiklander817466c2018-05-22 13:49:31 +0200375}
376
Jens Wiklander32b31802023-10-06 16:59:46 +0200377int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
378 int mode,
379 const unsigned char *iv, size_t iv_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200380{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200381 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200382 unsigned char work_buf[16];
Jens Wiklander817466c2018-05-22 13:49:31 +0200383 const unsigned char *p;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200384 size_t use_len;
Jerome Forissier039e02d2022-08-09 17:10:15 +0200385 uint64_t iv_bits;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200386#if !defined(MBEDTLS_BLOCK_CIPHER_C)
387 size_t olen = 0;
388#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200389
Jens Wiklander32b31802023-10-06 16:59:46 +0200390 /* IV is limited to 2^64 bits, so 2^61 bytes */
Jens Wiklander817466c2018-05-22 13:49:31 +0200391 /* IV is not allowed to be zero length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200392 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
393 return MBEDTLS_ERR_GCM_BAD_INPUT;
Jens Wiklander817466c2018-05-22 13:49:31 +0200394 }
395
Jens Wiklander32b31802023-10-06 16:59:46 +0200396 memset(ctx->y, 0x00, sizeof(ctx->y));
397 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Jens Wiklander817466c2018-05-22 13:49:31 +0200398
399 ctx->mode = mode;
400 ctx->len = 0;
401 ctx->add_len = 0;
402
Jens Wiklander32b31802023-10-06 16:59:46 +0200403 if (iv_len == 12) {
404 memcpy(ctx->y, iv, iv_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200405 ctx->y[15] = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200406 } else {
407 memset(work_buf, 0x00, 16);
408 iv_bits = (uint64_t) iv_len * 8;
409 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Jens Wiklander817466c2018-05-22 13:49:31 +0200410
411 p = iv;
Jens Wiklander32b31802023-10-06 16:59:46 +0200412 while (iv_len > 0) {
413 use_len = (iv_len < 16) ? iv_len : 16;
Jens Wiklander817466c2018-05-22 13:49:31 +0200414
Tom Van Eyckc1633172024-04-09 18:44:13 +0200415#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
Jens Wiklander32b31802023-10-06 16:59:46 +0200420 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200421
Tom Van Eyckc1633172024-04-09 18:44:13 +0200422#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
423#pragma GCC diagnostic pop
424#endif
425
Jens Wiklander32b31802023-10-06 16:59:46 +0200426 gcm_mult(ctx, ctx->y, ctx->y);
Jens Wiklander817466c2018-05-22 13:49:31 +0200427
428 iv_len -= use_len;
429 p += use_len;
430 }
431
Jens Wiklander32b31802023-10-06 16:59:46 +0200432 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Jens Wiklander817466c2018-05-22 13:49:31 +0200433
Jens Wiklander32b31802023-10-06 16:59:46 +0200434 gcm_mult(ctx, ctx->y, ctx->y);
Jens Wiklander817466c2018-05-22 13:49:31 +0200435 }
436
Tom Van Eyckc1633172024-04-09 18:44:13 +0200437
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 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);
442#endif
443 if (ret != 0) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200444 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200445 }
446
Jens Wiklander32b31802023-10-06 16:59:46 +0200447 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 */
467int 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;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200472 uint64_t new_add_len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200473
Tom Van Eyckc1633172024-04-09 18:44:13 +0200474 /* 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 new_add_len = ctx->add_len + (uint64_t) add_len;
482 if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200483 return MBEDTLS_ERR_GCM_BAD_INPUT;
484 }
485
486 offset = ctx->add_len % 16;
Jens Wiklander817466c2018-05-22 13:49:31 +0200487 p = add;
Jens Wiklander817466c2018-05-22 13:49:31 +0200488
Jens Wiklander32b31802023-10-06 16:59:46 +0200489 if (offset != 0) {
490 use_len = 16 - offset;
491 if (use_len > add_len) {
492 use_len = add_len;
493 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200494
Jens Wiklander32b31802023-10-06 16:59:46 +0200495 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200496
Jens Wiklander32b31802023-10-06 16:59:46 +0200497 if (offset + use_len == 16) {
498 gcm_mult(ctx, ctx->buf, ctx->buf);
499 }
500
501 ctx->add_len += use_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200502 add_len -= use_len;
503 p += use_len;
504 }
505
Jens Wiklander32b31802023-10-06 16:59:46 +0200506 ctx->add_len += add_len;
507
508 while (add_len >= 16) {
509 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
510
511 gcm_mult(ctx, ctx->buf, ctx->buf);
512
513 add_len -= 16;
514 p += 16;
515 }
516
517 if (add_len > 0) {
518 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
519 }
520
521 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200522}
523
Jens Wiklander32b31802023-10-06 16:59:46 +0200524/* Increment the counter. */
525static void gcm_incr(unsigned char y[16])
526{
Tom Van Eyckc1633172024-04-09 18:44:13 +0200527 uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);
528 x++;
529 MBEDTLS_PUT_UINT32_BE(x, y, 12);
Jens Wiklander32b31802023-10-06 16:59:46 +0200530}
531
532/* Calculate and apply the encryption mask. Process use_len bytes of data,
533 * starting at position offset in the mask block. */
534static 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{
Jens Wiklander32b31802023-10-06 16:59:46 +0200540 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
541
Tom Van Eyckc1633172024-04-09 18:44:13 +0200542#if defined(MBEDTLS_BLOCK_CIPHER_C)
543 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);
544#else
545 size_t olen = 0;
546 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);
547#endif
548 if (ret != 0) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200549 mbedtls_platform_zeroize(ectr, 16);
550 return ret;
551 }
552
553 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
554 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
555 }
556 mbedtls_xor(output, ectr + offset, input, use_len);
557 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
558 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
559 }
560
561 return 0;
562}
563
564int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200568{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200569 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200570 const unsigned char *p = input;
Jens Wiklander817466c2018-05-22 13:49:31 +0200571 unsigned char *out_p = output;
Jens Wiklander32b31802023-10-06 16:59:46 +0200572 size_t offset;
573 unsigned char ectr[16] = { 0 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200574
Jens Wiklander32b31802023-10-06 16:59:46 +0200575 if (output_size < input_length) {
576 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
577 }
578 *output_length = input_length;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100579
Jens Wiklander32b31802023-10-06 16:59:46 +0200580 /* 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 if (input_length == 0) {
585 return 0;
586 }
587
588 if (output > input && (size_t) (output - input) < input_length) {
589 return MBEDTLS_ERR_GCM_BAD_INPUT;
590 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200591
592 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
593 * Also check for possible overflow */
Jens Wiklander32b31802023-10-06 16:59:46 +0200594 if (ctx->len + input_length < ctx->len ||
595 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
596 return MBEDTLS_ERR_GCM_BAD_INPUT;
Jens Wiklander817466c2018-05-22 13:49:31 +0200597 }
598
Jens Wiklander32b31802023-10-06 16:59:46 +0200599 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
600 gcm_mult(ctx, ctx->buf, ctx->buf);
601 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200602
Jens Wiklander32b31802023-10-06 16:59:46 +0200603 offset = ctx->len % 16;
604 if (offset != 0) {
605 size_t use_len = 16 - offset;
606 if (use_len > input_length) {
607 use_len = input_length;
Jens Wiklander817466c2018-05-22 13:49:31 +0200608 }
609
Jens Wiklander32b31802023-10-06 16:59:46 +0200610 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
611 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200612 }
613
Jens Wiklander32b31802023-10-06 16:59:46 +0200614 if (offset + use_len == 16) {
615 gcm_mult(ctx, ctx->buf, ctx->buf);
616 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200617
Jens Wiklander32b31802023-10-06 16:59:46 +0200618 ctx->len += use_len;
619 input_length -= use_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200620 p += use_len;
621 out_p += use_len;
622 }
623
Jens Wiklander32b31802023-10-06 16:59:46 +0200624 ctx->len += input_length;
625
626 while (input_length >= 16) {
627 gcm_incr(ctx->y);
628 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
629 return ret;
630 }
631
632 gcm_mult(ctx, ctx->buf, ctx->buf);
633
634 input_length -= 16;
635 p += 16;
636 out_p += 16;
637 }
638
639 if (input_length > 0) {
640 gcm_incr(ctx->y);
641 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
642 return ret;
643 }
644 }
645
646 mbedtls_platform_zeroize(ectr, sizeof(ectr));
647 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200648}
649
Jens Wiklander32b31802023-10-06 16:59:46 +0200650int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200654{
655 unsigned char work_buf[16];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100656 uint64_t orig_len;
657 uint64_t orig_add_len;
658
Jens Wiklander32b31802023-10-06 16:59:46 +0200659 /* 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 *output_length = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100664
Tom Van Eyckc1633172024-04-09 18:44:13 +0200665 /* 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. */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100668 orig_len = ctx->len * 8;
669 orig_add_len = ctx->add_len * 8;
Jens Wiklander817466c2018-05-22 13:49:31 +0200670
Jens Wiklander32b31802023-10-06 16:59:46 +0200671 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
672 gcm_mult(ctx, ctx->buf, ctx->buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200673 }
674
Jens Wiklander32b31802023-10-06 16:59:46 +0200675 if (tag_len > 16 || tag_len < 4) {
676 return MBEDTLS_ERR_GCM_BAD_INPUT;
677 }
678
679 if (ctx->len % 16 != 0) {
680 gcm_mult(ctx, ctx->buf, ctx->buf);
681 }
682
683 memcpy(tag, ctx->base_ectr, tag_len);
684
685 if (orig_len || orig_add_len) {
686 memset(work_buf, 0x00, 16);
687
688 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
689 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
690 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
691 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
692
693 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
694
695 gcm_mult(ctx, ctx->buf, ctx->buf);
696
697 mbedtls_xor(tag, tag, ctx->buf, tag_len);
698 }
699
700 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200701}
702
Jens Wiklander32b31802023-10-06 16:59:46 +0200703int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200714{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200715 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200716 size_t olen;
Jens Wiklander817466c2018-05-22 13:49:31 +0200717
Jens Wiklander32b31802023-10-06 16:59:46 +0200718 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
719 return ret;
720 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100721
Jens Wiklander32b31802023-10-06 16:59:46 +0200722 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
723 return ret;
724 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200725
Jens Wiklander32b31802023-10-06 16:59:46 +0200726 if ((ret = mbedtls_gcm_update(ctx, input, length,
727 output, length, &olen)) != 0) {
728 return ret;
729 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200730
Jens Wiklander32b31802023-10-06 16:59:46 +0200731 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
732 return ret;
733 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200734
Jens Wiklander32b31802023-10-06 16:59:46 +0200735 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200736}
737
Jens Wiklander32b31802023-10-06 16:59:46 +0200738int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200748{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200749 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200750 unsigned char check_tag[16];
Jens Wiklander817466c2018-05-22 13:49:31 +0200751 int diff;
752
Jens Wiklander32b31802023-10-06 16:59:46 +0200753 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 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200757 }
758
759 /* Check tag in "constant-time" */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200760 diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200761
Jens Wiklander32b31802023-10-06 16:59:46 +0200762 if (diff != 0) {
763 mbedtls_platform_zeroize(output, length);
764 return MBEDTLS_ERR_GCM_AUTH_FAILED;
765 }
766
767 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200768}
769
Jens Wiklander32b31802023-10-06 16:59:46 +0200770void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200771{
Jens Wiklander32b31802023-10-06 16:59:46 +0200772 if (ctx == NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100773 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200774 }
Tom Van Eyckc1633172024-04-09 18:44:13 +0200775#if defined(MBEDTLS_BLOCK_CIPHER_C)
776 mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
777#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200778 mbedtls_cipher_free(&ctx->cipher_ctx);
Tom Van Eyckc1633172024-04-09 18:44:13 +0200779#endif
Jens Wiklander32b31802023-10-06 16:59:46 +0200780 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Jens Wiklander817466c2018-05-22 13:49:31 +0200781}
782
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100783#endif /* !MBEDTLS_GCM_ALT */
784
Tom Van Eyckc1633172024-04-09 18:44:13 +0200785#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
Jens Wiklander817466c2018-05-22 13:49:31 +0200786/*
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
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200793static const int key_index_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200794{ 0, 0, 1, 1, 1, 1 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200795
Tom Van Eyckc1633172024-04-09 18:44:13 +0200796static const unsigned char key_test_data[][32] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200797{
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
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200808static const size_t iv_len_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200809{ 12, 12, 12, 12, 8, 60 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200810
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200811static const int iv_index_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200812{ 0, 0, 1, 1, 1, 2 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200813
Tom Van Eyckc1633172024-04-09 18:44:13 +0200814static const unsigned char iv_test_data[][64] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200815{
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
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200830static const size_t add_len_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200831{ 0, 0, 0, 20, 20, 20 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200832
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200833static const int add_index_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200834{ 0, 0, 0, 1, 1, 1 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200835
Tom Van Eyckc1633172024-04-09 18:44:13 +0200836static const unsigned char additional_test_data[][64] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200837{
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
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200844static const size_t pt_len_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200845{ 0, 16, 64, 60, 60, 60 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200846
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200847static const int pt_index_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200848{ 0, 0, 1, 1, 1, 1 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200849
Tom Van Eyckc1633172024-04-09 18:44:13 +0200850static const unsigned char pt_test_data[][64] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200851{
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
Tom Van Eyckc1633172024-04-09 18:44:13 +0200864static const unsigned char ct_test_data[][64] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200865{
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 },
Tom Van Eyckc1633172024-04-09 18:44:13 +0200901#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander817466c2018-05-22 13:49:31 +0200902 { 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 },
Tom Van Eyckc1633172024-04-09 18:44:13 +0200972#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +0200973};
974
Tom Van Eyckc1633172024-04-09 18:44:13 +0200975static const unsigned char tag_test_data[][16] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200976{
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 },
Tom Van Eyckc1633172024-04-09 18:44:13 +0200989#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Jens Wiklander817466c2018-05-22 13:49:31 +0200990 { 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 },
Tom Van Eyckc1633172024-04-09 18:44:13 +02001014#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Jens Wiklander817466c2018-05-22 13:49:31 +02001015};
1016
Jens Wiklander32b31802023-10-06 16:59:46 +02001017int mbedtls_gcm_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02001018{
1019 mbedtls_gcm_context ctx;
1020 unsigned char buf[64];
1021 unsigned char tag_buf[16];
1022 int i, j, ret;
1023 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Jens Wiklander32b31802023-10-06 16:59:46 +02001024 size_t olen;
Jens Wiklander817466c2018-05-22 13:49:31 +02001025
Jens Wiklander32b31802023-10-06 16:59:46 +02001026 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 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
1032 mbedtls_printf(" GCM note: using AESNI.\n");
1033 } else
1034#endif
Tom Van Eyckc1633172024-04-09 18:44:13 +02001035
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
Jens Wiklander32b31802023-10-06 16:59:46 +02001042 mbedtls_printf(" GCM note: built-in implementation.\n");
1043#endif /* MBEDTLS_GCM_ALT */
1044 }
1045
Tom Van Eyckc1633172024-04-09 18:44:13 +02001046 static const int loop_limit =
1047 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
1048
1049 for (j = 0; j < loop_limit; j++) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001050 int key_len = 128 + 64 * j;
1051
Jens Wiklander32b31802023-10-06 16:59:46 +02001052 for (i = 0; i < MAX_TESTS; i++) {
Jens Wiklander32b31802023-10-06 16:59:46 +02001053 if (verbose != 0) {
1054 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1055 key_len, i, "enc");
1056 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001057
Tom Van Eyckc1633172024-04-09 18:44:13 +02001058 mbedtls_gcm_init(&ctx);
1059
Jens Wiklander32b31802023-10-06 16:59:46 +02001060 ret = mbedtls_gcm_setkey(&ctx, cipher,
1061 key_test_data[key_index_test_data[i]],
1062 key_len);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001063 /*
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 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001068 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
1069 mbedtls_printf("skipped\n");
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001070 break;
Jens Wiklander32b31802023-10-06 16:59:46 +02001071 } else if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001072 goto exit;
1073 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001074
Jens Wiklander32b31802023-10-06 16:59:46 +02001075 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
1076 pt_len_test_data[i],
1077 iv_test_data[iv_index_test_data[i]],
1078 iv_len_test_data[i],
1079 additional_test_data[add_index_test_data[i]],
1080 add_len_test_data[i],
1081 pt_test_data[pt_index_test_data[i]],
1082 buf, 16, tag_buf);
Jerome Forissier79013242021-07-28 10:24:04 +02001083#if defined(MBEDTLS_GCM_ALT)
1084 /* Allow alternative implementations to only support 12-byte nonces. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001085 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
1086 iv_len_test_data[i] != 12) {
1087 mbedtls_printf("skipped\n");
Jerome Forissier79013242021-07-28 10:24:04 +02001088 break;
1089 }
1090#endif /* defined(MBEDTLS_GCM_ALT) */
Jens Wiklander32b31802023-10-06 16:59:46 +02001091 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001092 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001093 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001094
Jens Wiklander32b31802023-10-06 16:59:46 +02001095 if (memcmp(buf, ct_test_data[j * 6 + i],
1096 pt_len_test_data[i]) != 0 ||
1097 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001098 ret = 1;
1099 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +02001100 }
1101
Jens Wiklander32b31802023-10-06 16:59:46 +02001102 mbedtls_gcm_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +02001103
Jens Wiklander32b31802023-10-06 16:59:46 +02001104 if (verbose != 0) {
1105 mbedtls_printf("passed\n");
1106 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001107
Jens Wiklander32b31802023-10-06 16:59:46 +02001108 mbedtls_gcm_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001109
Jens Wiklander32b31802023-10-06 16:59:46 +02001110 if (verbose != 0) {
1111 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1112 key_len, i, "dec");
1113 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001114
Jens Wiklander32b31802023-10-06 16:59:46 +02001115 ret = mbedtls_gcm_setkey(&ctx, cipher,
1116 key_test_data[key_index_test_data[i]],
1117 key_len);
1118 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001119 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001120 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001121
Jens Wiklander32b31802023-10-06 16:59:46 +02001122 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
1123 pt_len_test_data[i],
1124 iv_test_data[iv_index_test_data[i]],
1125 iv_len_test_data[i],
1126 additional_test_data[add_index_test_data[i]],
1127 add_len_test_data[i],
1128 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Jens Wiklander817466c2018-05-22 13:49:31 +02001129
Jens Wiklander32b31802023-10-06 16:59:46 +02001130 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001131 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001132 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001133
Jens Wiklander32b31802023-10-06 16:59:46 +02001134 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1135 pt_len_test_data[i]) != 0 ||
1136 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001137 ret = 1;
1138 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +02001139 }
1140
Jens Wiklander32b31802023-10-06 16:59:46 +02001141 mbedtls_gcm_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +02001142
Jens Wiklander32b31802023-10-06 16:59:46 +02001143 if (verbose != 0) {
1144 mbedtls_printf("passed\n");
1145 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001146
Jens Wiklander32b31802023-10-06 16:59:46 +02001147 mbedtls_gcm_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001148
Jens Wiklander32b31802023-10-06 16:59:46 +02001149 if (verbose != 0) {
1150 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1151 key_len, i, "enc");
1152 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001153
Jens Wiklander32b31802023-10-06 16:59:46 +02001154 ret = mbedtls_gcm_setkey(&ctx, cipher,
1155 key_test_data[key_index_test_data[i]],
1156 key_len);
1157 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001158 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001159 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001160
Jens Wiklander32b31802023-10-06 16:59:46 +02001161 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1162 iv_test_data[iv_index_test_data[i]],
1163 iv_len_test_data[i]);
1164 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001165 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001166 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001167
Jens Wiklander32b31802023-10-06 16:59:46 +02001168 ret = mbedtls_gcm_update_ad(&ctx,
1169 additional_test_data[add_index_test_data[i]],
1170 add_len_test_data[i]);
1171 if (ret != 0) {
1172 goto exit;
1173 }
1174
1175 if (pt_len_test_data[i] > 32) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001176 size_t rest_len = pt_len_test_data[i] - 32;
Jens Wiklander32b31802023-10-06 16:59:46 +02001177 ret = mbedtls_gcm_update(&ctx,
1178 pt_test_data[pt_index_test_data[i]],
1179 32,
1180 buf, sizeof(buf), &olen);
1181 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001182 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001183 }
1184 if (olen != 32) {
1185 goto exit;
1186 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001187
Jens Wiklander32b31802023-10-06 16:59:46 +02001188 ret = mbedtls_gcm_update(&ctx,
1189 pt_test_data[pt_index_test_data[i]] + 32,
1190 rest_len,
1191 buf + 32, sizeof(buf) - 32, &olen);
1192 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001193 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001194 }
1195 if (olen != rest_len) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001196 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001197 }
1198 } else {
1199 ret = mbedtls_gcm_update(&ctx,
1200 pt_test_data[pt_index_test_data[i]],
1201 pt_len_test_data[i],
1202 buf, sizeof(buf), &olen);
1203 if (ret != 0) {
1204 goto exit;
1205 }
1206 if (olen != pt_len_test_data[i]) {
1207 goto exit;
1208 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001209 }
1210
Jens Wiklander32b31802023-10-06 16:59:46 +02001211 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1212 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001213 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001214 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001215
Jens Wiklander32b31802023-10-06 16:59:46 +02001216 if (memcmp(buf, ct_test_data[j * 6 + i],
1217 pt_len_test_data[i]) != 0 ||
1218 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001219 ret = 1;
1220 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +02001221 }
1222
Jens Wiklander32b31802023-10-06 16:59:46 +02001223 mbedtls_gcm_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +02001224
Jens Wiklander32b31802023-10-06 16:59:46 +02001225 if (verbose != 0) {
1226 mbedtls_printf("passed\n");
1227 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001228
Jens Wiklander32b31802023-10-06 16:59:46 +02001229 mbedtls_gcm_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001230
Jens Wiklander32b31802023-10-06 16:59:46 +02001231 if (verbose != 0) {
1232 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1233 key_len, i, "dec");
1234 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001235
Jens Wiklander32b31802023-10-06 16:59:46 +02001236 ret = mbedtls_gcm_setkey(&ctx, cipher,
1237 key_test_data[key_index_test_data[i]],
1238 key_len);
1239 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001240 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001241 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001242
Jens Wiklander32b31802023-10-06 16:59:46 +02001243 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1244 iv_test_data[iv_index_test_data[i]],
1245 iv_len_test_data[i]);
1246 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001247 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001248 }
1249 ret = mbedtls_gcm_update_ad(&ctx,
1250 additional_test_data[add_index_test_data[i]],
1251 add_len_test_data[i]);
1252 if (ret != 0) {
1253 goto exit;
1254 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001255
Jens Wiklander32b31802023-10-06 16:59:46 +02001256 if (pt_len_test_data[i] > 32) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001257 size_t rest_len = pt_len_test_data[i] - 32;
Jens Wiklander32b31802023-10-06 16:59:46 +02001258 ret = mbedtls_gcm_update(&ctx,
1259 ct_test_data[j * 6 + i], 32,
1260 buf, sizeof(buf), &olen);
1261 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001262 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001263 }
1264 if (olen != 32) {
1265 goto exit;
1266 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001267
Jens Wiklander32b31802023-10-06 16:59:46 +02001268 ret = mbedtls_gcm_update(&ctx,
1269 ct_test_data[j * 6 + i] + 32,
1270 rest_len,
1271 buf + 32, sizeof(buf) - 32, &olen);
1272 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001273 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001274 }
1275 if (olen != rest_len) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001276 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001277 }
1278 } else {
1279 ret = mbedtls_gcm_update(&ctx,
1280 ct_test_data[j * 6 + i],
1281 pt_len_test_data[i],
1282 buf, sizeof(buf), &olen);
1283 if (ret != 0) {
1284 goto exit;
1285 }
1286 if (olen != pt_len_test_data[i]) {
1287 goto exit;
1288 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001289 }
1290
Jens Wiklander32b31802023-10-06 16:59:46 +02001291 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1292 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001293 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001294 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001295
Jens Wiklander32b31802023-10-06 16:59:46 +02001296 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1297 pt_len_test_data[i]) != 0 ||
1298 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001299 ret = 1;
1300 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +02001301 }
1302
Jens Wiklander32b31802023-10-06 16:59:46 +02001303 mbedtls_gcm_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +02001304
Jens Wiklander32b31802023-10-06 16:59:46 +02001305 if (verbose != 0) {
1306 mbedtls_printf("passed\n");
1307 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001308 }
1309 }
1310
Jens Wiklander32b31802023-10-06 16:59:46 +02001311 if (verbose != 0) {
1312 mbedtls_printf("\n");
1313 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001314
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001315 ret = 0;
1316
1317exit:
Jens Wiklander32b31802023-10-06 16:59:46 +02001318 if (ret != 0) {
1319 if (verbose != 0) {
1320 mbedtls_printf("failed\n");
1321 }
1322 mbedtls_gcm_free(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001323 }
1324
Jens Wiklander32b31802023-10-06 16:59:46 +02001325 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001326}
1327
1328#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
1329
1330#endif /* MBEDTLS_GCM_C */