blob: dda1ff21f510449de52fb2231aea0c51978f69d3 [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker89e80c92012-03-20 13:50:09 +00006 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +01007
Paul Bakker89e80c92012-03-20 13:50:09 +00008/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +01009 * 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.
Paul Bakker89e80c92012-03-20 13:50:09 +000016 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010017
Gilles Peskinedb09ef62020-06-03 01:43:33 +020018#include "common.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020020#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000021
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000022#include "mbedtls/gcm.h"
Gilles Peskineed1c7f42022-09-15 20:14:22 +020023#include "mbedtls/platform.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050024#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000025#include "mbedtls/error.h"
Dave Rodgmand26a3d62023-09-11 18:25:16 +010026#include "mbedtls/constant_time.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000027
Valerio Settibd7528a2023-12-14 09:36:03 +010028#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Setti9b7a8b22023-11-16 08:24:51 +010029#include "block_cipher_internal.h"
30#endif
31
Rich Evans00ab4702015-02-06 13:43:58 +000032#include <string.h>
33
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_AESNI_C)
Chris Jones187782f2021-03-09 17:28:35 +000035#include "aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010036#endif
37
Jerry Yudf87a122023-01-10 18:17:15 +080038#if defined(MBEDTLS_AESCE_C)
39#include "aesce.h"
40#endif
41
Matthias Schulz78266782024-02-08 13:54:48 +010042/* Used to select the acceleration mechanism */
43#define MBEDTLS_GCM_ACC_SMALLTABLE 0
44#define MBEDTLS_GCM_ACC_LARGETABLE 1
45#define MBEDTLS_GCM_ACC_AESNI 2
46#define MBEDTLS_GCM_ACC_AESCE 3
47
Paul Bakker89e80c92012-03-20 13:50:09 +000048/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020049 * Initialize a context
50 */
Gilles Peskine449bd832023-01-11 14:50:10 +010051void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020052{
Gilles Peskine449bd832023-01-11 14:50:10 +010053 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020054}
55
Matthias Schulz0767fda2024-02-07 10:46:28 +010056static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)
57{
Matthias Schulza6ac0f12024-02-09 17:09:42 +010058#if defined(MBEDTLS_GCM_LARGE_TABLE)
Matthias Schulz0767fda2024-02-07 10:46:28 +010059 ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE;
60#else
61 ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE;
62#endif
63
64#if defined(MBEDTLS_AESNI_HAVE_CODE)
65 /* With CLMUL support, we need only h, not the rest of the table */
66 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
67 ctx->acceleration = MBEDTLS_GCM_ACC_AESNI;
68 }
69#endif
70
71#if defined(MBEDTLS_AESCE_HAVE_CODE)
72 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
73 ctx->acceleration = MBEDTLS_GCM_ACC_AESCE;
74 }
75#endif
76}
77
78static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])
79{
80 uint8_t *u8Dst = (uint8_t *) dst;
81 uint8_t *u8Src = (uint8_t *) src;
82
83 MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);
84 u8Dst[8] |= (u8Src[7] & 0x01) << 7;
85 MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);
86 u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;
87}
88
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020089/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010090 * Precompute small multiples of H, that is set
91 * HH[i] || HL[i] = H times i,
92 * where i is seen as a field element as in [MGV], ie high-order bits
93 * correspond to low powers of P. The result is stored in the same way, that
94 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
95 * corresponds to P^127.
96 */
Gilles Peskine449bd832023-01-11 14:50:10 +010097static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000098{
Paul Bakker43aff2a2013-09-09 00:10:27 +020099 int ret, i, j;
Matthias Schulz0767fda2024-02-07 10:46:28 +0100100 uint64_t u64h[2] = { 0 };
101 uint8_t *h = (uint8_t *) u64h;
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100102
Valerio Settibd7528a2023-12-14 09:36:03 +0100103#if defined(MBEDTLS_BLOCK_CIPHER_C)
104 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
105#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100106 size_t olen = 0;
Valerio Settid0eebc12023-11-20 15:17:53 +0100107 ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100108#endif
109 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100110 return ret;
111 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000112
Matthias Schulz0767fda2024-02-07 10:46:28 +0100113 gcm_set_acceleration(ctx);
Paul Bakker89e80c92012-03-20 13:50:09 +0000114
Matthias Schulz0767fda2024-02-07 10:46:28 +0100115 /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */
116 ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];
117 ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];
Paul Bakker169b7f42013-06-25 14:58:00 +0200118
Matthias Schulz0767fda2024-02-07 10:46:28 +0100119 switch (ctx->acceleration) {
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100120#if defined(MBEDTLS_AESNI_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100121 case MBEDTLS_GCM_ACC_AESNI:
122 return 0;
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100123#endif
124
Jerry Yu72fd0bd2023-08-18 16:31:01 +0800125#if defined(MBEDTLS_AESCE_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100126 case MBEDTLS_GCM_ACC_AESCE:
127 return 0;
Jerry Yudf87a122023-01-10 18:17:15 +0800128#endif
129
Matthias Schulz0767fda2024-02-07 10:46:28 +0100130 default:
131 /* 0 corresponds to 0 in GF(2^128) */
132 ctx->H[0][0] = 0;
133 ctx->H[0][1] = 0;
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100134
Matthias Schulz0767fda2024-02-07 10:46:28 +0100135 for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
136 gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
137 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000138
Matthias Schulza6ac0f12024-02-09 17:09:42 +0100139#if !defined(MBEDTLS_GCM_LARGE_TABLE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100140 /* pack elements of H as 64-bits ints, big-endian */
141 for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {
142 MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);
143 MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);
144 }
145#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000146
Matthias Schulz0767fda2024-02-07 10:46:28 +0100147 for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {
148 for (j = 1; j < i; j++) {
149 mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],
150 (unsigned char *) ctx->H[i],
151 (unsigned char *) ctx->H[j],
152 16);
153 }
154 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000155 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000158}
159
Gilles Peskine449bd832023-01-11 14:50:10 +0100160int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
161 mbedtls_cipher_id_t cipher,
162 const unsigned char *key,
163 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000164{
Janos Follath24eed8d2019-11-22 13:21:35 +0000165 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000166
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 if (keybits != 128 && keybits != 192 && keybits != 256) {
Tuvshinzaya Erdenekhuuc6b8a672022-08-05 15:31:57 +0100168 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200169 }
170
Valerio Settibd7528a2023-12-14 09:36:03 +0100171#if defined(MBEDTLS_BLOCK_CIPHER_C)
172 mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
173
174 if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {
175 return ret;
176 }
177
178 if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {
179 return ret;
180 }
181#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100182 const mbedtls_cipher_info_t *cipher_info;
183
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
185 MBEDTLS_MODE_ECB);
186 if (cipher_info == NULL) {
187 return MBEDTLS_ERR_GCM_BAD_INPUT;
188 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000189
Dave Rodgman85a88132023-06-24 11:41:50 +0100190 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 return MBEDTLS_ERR_GCM_BAD_INPUT;
192 }
193
194 mbedtls_cipher_free(&ctx->cipher_ctx);
195
196 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
197 return ret;
198 }
199
200 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
201 MBEDTLS_ENCRYPT)) != 0) {
202 return ret;
203 }
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100204#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100205
206 if ((ret = gcm_gen_table(ctx)) != 0) {
207 return ret;
208 }
209
210 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000211}
212
Matthias Schulza6ac0f12024-02-09 17:09:42 +0100213#if defined(MBEDTLS_GCM_LARGE_TABLE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100214static const uint16_t last8[256] = {
215 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05,
216 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b,
217 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19,
218 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17,
219 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d,
220 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33,
221 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21,
222 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f,
223 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75,
224 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b,
225 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69,
226 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67,
227 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d,
228 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43,
229 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51,
230 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f,
231 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4,
232 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea,
233 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8,
234 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6,
235 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc,
236 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2,
237 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0,
238 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece,
239 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94,
240 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a,
241 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88,
242 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86,
243 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac,
244 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2,
245 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0,
246 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe
247};
248
249static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2])
250{
251 int i;
252 uint64_t u64z[2];
253 uint16_t *u16z = (uint16_t *) u64z;
254 uint8_t *u8z = (uint8_t *) u64z;
255 uint8_t rem;
256
257 u64z[0] = 0;
258 u64z[1] = 0;
259
Matthias Schulz78266782024-02-08 13:54:48 +0100260 if (MBEDTLS_IS_BIG_ENDIAN) {
261 for (i = 15; i > 0; i--) {
262 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
263 rem = u8z[15];
Matthias Schulz0767fda2024-02-07 10:46:28 +0100264
Matthias Schulz78266782024-02-08 13:54:48 +0100265 u64z[1] >>= 8;
266 u8z[8] = u8z[7];
267 u64z[0] >>= 8;
Matthias Schulz0767fda2024-02-07 10:46:28 +0100268
Matthias Schulz78266782024-02-08 13:54:48 +0100269 u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0);
270 }
271 } else {
272 for (i = 15; i > 0; i--) {
273 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
274 rem = u8z[15];
Matthias Schulz0767fda2024-02-07 10:46:28 +0100275
Matthias Schulz78266782024-02-08 13:54:48 +0100276 u64z[1] <<= 8;
277 u8z[8] = u8z[7];
278 u64z[0] <<= 8;
279
280 u16z[0] ^= last8[rem];
281 }
Matthias Schulz0767fda2024-02-07 10:46:28 +0100282 }
283
284 mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);
285}
286#else
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100287/*
288 * Shoup's method for multiplication use this table with
289 * last4[x] = x times P^128
290 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
291 */
Dave Rodgman5ff02452023-07-13 15:55:21 +0100292static const uint16_t last4[16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000293{
294 0x0000, 0x1c20, 0x3840, 0x2460,
295 0x7080, 0x6ca0, 0x48c0, 0x54e0,
296 0xe100, 0xfd20, 0xd940, 0xc560,
297 0x9180, 0x8da0, 0xa9c0, 0xb5e0
298};
299
Matthias Schulz0767fda2024-02-07 10:46:28 +0100300static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])
301{
302 int i = 0;
303 unsigned char lo, hi, rem;
304 uint64_t u64z[2];
Matthias Schulz10902c52024-02-09 11:14:50 +0100305 const uint64_t *pu64z = NULL;
Matthias Schulz0767fda2024-02-07 10:46:28 +0100306 uint8_t *u8z = (uint8_t *) u64z;
307
308 lo = x[15] & 0xf;
309 hi = (x[15] >> 4) & 0xf;
310
311 pu64z = H[lo];
312
313 rem = (unsigned char) pu64z[1] & 0xf;
314 u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);
315 u64z[0] = (pu64z[0] >> 4);
316 u64z[0] ^= (uint64_t) last4[rem] << 48;
317 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
318
319 for (i = 14; i >= 0; i--) {
320 lo = x[i] & 0xf;
321 hi = (x[i] >> 4) & 0xf;
322
323 rem = (unsigned char) u64z[1] & 0xf;
324 u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
325 u64z[0] = (u64z[0] >> 4);
326 u64z[0] ^= (uint64_t) last4[rem] << 48;
327 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);
328
329 rem = (unsigned char) u64z[1] & 0xf;
330 u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
331 u64z[0] = (u64z[0] >> 4);
332 u64z[0] ^= (uint64_t) last4[rem] << 48;
333 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
334 }
335
Matthias Schulz78266782024-02-08 13:54:48 +0100336 MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);
337 MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);
Matthias Schulz0767fda2024-02-07 10:46:28 +0100338}
339#endif
340
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100341/*
342 * Sets output to x times H using the precomputed tables.
343 * x and output are seen as elements of GF(2^128) as in [MGV].
344 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100345static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
346 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000347{
Matthias Schulz0767fda2024-02-07 10:46:28 +0100348 switch (ctx->acceleration) {
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100349#if defined(MBEDTLS_AESNI_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100350 case MBEDTLS_GCM_ACC_AESNI:
351 mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
352 break;
Jerry Yudf87a122023-01-10 18:17:15 +0800353#endif
354
Matthias Schulz0767fda2024-02-07 10:46:28 +0100355#if defined(MBEDTLS_AESCE_HAVE_CODE)
356 case MBEDTLS_GCM_ACC_AESCE:
357 mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
358 break;
359#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000360
Matthias Schulza6ac0f12024-02-09 17:09:42 +0100361#if defined(MBEDTLS_GCM_LARGE_TABLE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100362 case MBEDTLS_GCM_ACC_LARGETABLE:
363 gcm_mult_largetable(output, x, ctx->H);
364 break;
365#else
366 case MBEDTLS_GCM_ACC_SMALLTABLE:
367 gcm_mult_smalltable(output, x, ctx->H);
368 break;
369#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000370 }
371
Matthias Schulz0767fda2024-02-07 10:46:28 +0100372 return;
Paul Bakker89e80c92012-03-20 13:50:09 +0000373}
374
Gilles Peskine449bd832023-01-11 14:50:10 +0100375int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
376 int mode,
377 const unsigned char *iv, size_t iv_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000378{
Janos Follath24eed8d2019-11-22 13:21:35 +0000379 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000380 unsigned char work_buf[16];
Paul Bakker89e80c92012-03-20 13:50:09 +0000381 const unsigned char *p;
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100382 size_t use_len;
openluopworldeab65ac2021-09-22 23:59:42 +0800383 uint64_t iv_bits;
Valerio Settibd7528a2023-12-14 09:36:03 +0100384#if !defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100385 size_t olen = 0;
386#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000387
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200388 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200389 /* IV is not allowed to be zero length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
391 return MBEDTLS_ERR_GCM_BAD_INPUT;
392 }
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200393
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 memset(ctx->y, 0x00, sizeof(ctx->y));
395 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200396
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200397 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200398 ctx->len = 0;
399 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000400
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 if (iv_len == 12) {
402 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200403 ctx->y[15] = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 } else {
405 memset(work_buf, 0x00, 16);
406 iv_bits = (uint64_t) iv_len * 8;
407 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000408
409 p = iv;
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 while (iv_len > 0) {
411 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000412
Dave Rodgman386c39f2024-03-13 09:39:53 +0000413#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
Dave Rodgman4faa34d2024-03-12 16:34:43 +0000414#pragma GCC diagnostic push
415#pragma GCC diagnostic warning "-Wstringop-overflow=0"
416#endif
417
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200419
Dave Rodgman386c39f2024-03-13 09:39:53 +0000420#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
Dave Rodgman4faa34d2024-03-12 16:34:43 +0000421#pragma GCC diagnostic pop
422#endif
423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000425
426 iv_len -= use_len;
427 p += use_len;
428 }
429
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000431
Gilles Peskine449bd832023-01-11 14:50:10 +0100432 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000433 }
434
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100435
Valerio Settibd7528a2023-12-14 09:36:03 +0100436#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Settid0eebc12023-11-20 15:17:53 +0100437 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr);
Valerio Settibd7528a2023-12-14 09:36:03 +0100438#else
439 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100440#endif
441 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100442 return ret;
443 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200446}
447
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200448/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200449 * mbedtls_gcm_context::buf contains the partial state of the computation of
450 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200451 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
452 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200453 * * len == 0 && add_len == 0: initial state
454 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
455 * a partial block of AD that has been
456 * xored in but not yet multiplied in.
457 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
458 * the data ends now.
459 * * len % 16 != 0: the first `len % 16` bytes have
460 * a partial block of ciphertext that has
461 * been xored in but not yet multiplied in.
462 * * len > 0 && len % 16 == 0: the authentication tag is correct if
463 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200464 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100465int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
466 const unsigned char *add, size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200467{
468 const unsigned char *p;
Dave Rodgmand22fb732022-11-22 16:53:25 +0000469 size_t use_len, offset;
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800470 uint64_t new_add_len;
Gilles Peskine295fc132021-04-15 18:32:23 +0200471
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800472 /* AD is limited to 2^64 bits, ie 2^61 bytes
473 * Also check for possible overflow */
Chien Wong019c2a72024-01-23 21:38:06 +0800474#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
475 if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
476 return MBEDTLS_ERR_GCM_BAD_INPUT;
477 }
478#endif
479 new_add_len = ctx->add_len + (uint64_t) add_len;
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800480 if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 return MBEDTLS_ERR_GCM_BAD_INPUT;
482 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200483
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200484 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000485 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200486
Gilles Peskine449bd832023-01-11 14:50:10 +0100487 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200488 use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100489 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200490 use_len = add_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200492
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200494
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 if (offset + use_len == 16) {
496 gcm_mult(ctx, ctx->buf, ctx->buf);
497 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200498
499 ctx->add_len += use_len;
500 add_len -= use_len;
501 p += use_len;
502 }
503
504 ctx->add_len += add_len;
505
Gilles Peskine449bd832023-01-11 14:50:10 +0100506 while (add_len >= 16) {
507 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200508
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000510
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200511 add_len -= 16;
512 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000513 }
514
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 if (add_len > 0) {
516 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200517 }
518
Gilles Peskine449bd832023-01-11 14:50:10 +0100519 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200520}
521
Gilles Peskine58fc2722021-04-13 15:58:27 +0200522/* Increment the counter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100523static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200524{
Dave Rodgman46697da2024-01-14 12:59:49 +0000525 uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);
526 x++;
527 MBEDTLS_PUT_UINT32_BE(x, y, 12);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200528}
529
530/* Calculate and apply the encryption mask. Process use_len bytes of data,
531 * starting at position offset in the mask block. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100532static int gcm_mask(mbedtls_gcm_context *ctx,
533 unsigned char ectr[16],
534 size_t offset, size_t use_len,
535 const unsigned char *input,
536 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200537{
Gilles Peskine58fc2722021-04-13 15:58:27 +0200538 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Valerio Settid0eebc12023-11-20 15:17:53 +0100539
Valerio Settibd7528a2023-12-14 09:36:03 +0100540#if defined(MBEDTLS_BLOCK_CIPHER_C)
541 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);
542#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100543 size_t olen = 0;
Valerio Settid0eebc12023-11-20 15:17:53 +0100544 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100545#endif
546 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100547 mbedtls_platform_zeroize(ectr, 16);
548 return ret;
549 }
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100550
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
552 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
553 }
554 mbedtls_xor(output, ectr + offset, input, use_len);
555 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
556 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
557 }
Dave Rodgmand22fb732022-11-22 16:53:25 +0000558
Gilles Peskine449bd832023-01-11 14:50:10 +0100559 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200560}
561
Gilles Peskine449bd832023-01-11 14:50:10 +0100562int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
563 const unsigned char *input, size_t input_length,
564 unsigned char *output, size_t output_size,
565 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200566{
Janos Follath24eed8d2019-11-22 13:21:35 +0000567 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200568 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200569 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200570 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100571 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200572
Gilles Peskine449bd832023-01-11 14:50:10 +0100573 if (output_size < input_length) {
574 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
575 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200576 *output_length = input_length;
577
578 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200579 * on a potentially null pointer.
580 * Returning early also means that the last partial block of AD remains
581 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 if (input_length == 0) {
583 return 0;
584 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200585
Gilles Peskine449bd832023-01-11 14:50:10 +0100586 if (output > input && (size_t) (output - input) < input_length) {
587 return MBEDTLS_ERR_GCM_BAD_INPUT;
588 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200589
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200590 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
591 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 if (ctx->len + input_length < ctx->len ||
593 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
594 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200595 }
596
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
598 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200599 }
600
Gilles Peskine58fc2722021-04-13 15:58:27 +0200601 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200603 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100604 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200605 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000607
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
609 return ret;
610 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000611
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 if (offset + use_len == 16) {
613 gcm_mult(ctx, ctx->buf, ctx->buf);
614 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200615
Gilles Peskine58fc2722021-04-13 15:58:27 +0200616 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200617 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000618 p += use_len;
619 out_p += use_len;
620 }
621
Gilles Peskinea56c4482021-04-15 17:22:35 +0200622 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200623
Gilles Peskine449bd832023-01-11 14:50:10 +0100624 while (input_length >= 16) {
625 gcm_incr(ctx->y);
626 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
627 return ret;
628 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200629
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200631
Gilles Peskinea56c4482021-04-15 17:22:35 +0200632 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200633 p += 16;
634 out_p += 16;
635 }
636
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 if (input_length > 0) {
638 gcm_incr(ctx->y);
639 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
640 return ret;
641 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200642 }
643
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 mbedtls_platform_zeroize(ectr, sizeof(ectr));
645 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200646}
647
Gilles Peskine449bd832023-01-11 14:50:10 +0100648int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
649 unsigned char *output, size_t output_size,
650 size_t *output_length,
651 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200652{
653 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100654 uint64_t orig_len;
655 uint64_t orig_add_len;
656
Gilles Peskine9461e452021-04-15 16:48:32 +0200657 /* We never pass any output in finish(). The output parameter exists only
658 * for the sake of alternative implementations. */
659 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200660 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200661 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200662
Chien Wong858bc652024-01-22 20:47:26 +0800663 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
664 * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
665 * the two multiplications would overflow. */
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100666 orig_len = ctx->len * 8;
667 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200668
Gilles Peskine449bd832023-01-11 14:50:10 +0100669 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
670 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200671 }
672
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 if (tag_len > 16 || tag_len < 4) {
674 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000675 }
676
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 if (ctx->len % 16 != 0) {
678 gcm_mult(ctx, ctx->buf, ctx->buf);
679 }
680
681 memcpy(tag, ctx->base_ectr, tag_len);
682
683 if (orig_len || orig_add_len) {
684 memset(work_buf, 0x00, 16);
685
686 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
687 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
688 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
689 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
690
691 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
692
693 gcm_mult(ctx, ctx->buf, ctx->buf);
694
695 mbedtls_xor(tag, tag, ctx->buf, tag_len);
696 }
697
698 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000699}
700
Gilles Peskine449bd832023-01-11 14:50:10 +0100701int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
702 int mode,
703 size_t length,
704 const unsigned char *iv,
705 size_t iv_len,
706 const unsigned char *add,
707 size_t add_len,
708 const unsigned char *input,
709 unsigned char *output,
710 size_t tag_len,
711 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200712{
Janos Follath24eed8d2019-11-22 13:21:35 +0000713 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200714 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200715
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
717 return ret;
718 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200719
Gilles Peskine449bd832023-01-11 14:50:10 +0100720 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
721 return ret;
722 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200723
Gilles Peskine449bd832023-01-11 14:50:10 +0100724 if ((ret = mbedtls_gcm_update(ctx, input, length,
725 output, length, &olen)) != 0) {
726 return ret;
727 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200728
Gilles Peskine449bd832023-01-11 14:50:10 +0100729 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
730 return ret;
731 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200732
Gilles Peskine449bd832023-01-11 14:50:10 +0100733 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200734}
735
Gilles Peskine449bd832023-01-11 14:50:10 +0100736int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
737 size_t length,
738 const unsigned char *iv,
739 size_t iv_len,
740 const unsigned char *add,
741 size_t add_len,
742 const unsigned char *tag,
743 size_t tag_len,
744 const unsigned char *input,
745 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000746{
Janos Follath24eed8d2019-11-22 13:21:35 +0000747 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000748 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200749 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000750
Gilles Peskine449bd832023-01-11 14:50:10 +0100751 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
752 iv, iv_len, add, add_len,
753 input, output, tag_len, check_tag)) != 0) {
754 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100755 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000756
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200757 /* Check tag in "constant-time" */
Dave Rodgmand26a3d62023-09-11 18:25:16 +0100758 diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
Paul Bakker89e80c92012-03-20 13:50:09 +0000759
Gilles Peskine449bd832023-01-11 14:50:10 +0100760 if (diff != 0) {
761 mbedtls_platform_zeroize(output, length);
762 return MBEDTLS_ERR_GCM_AUTH_FAILED;
763 }
764
765 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000766}
767
Gilles Peskine449bd832023-01-11 14:50:10 +0100768void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200769{
Gilles Peskine449bd832023-01-11 14:50:10 +0100770 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100771 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 }
Valerio Settibd7528a2023-12-14 09:36:03 +0100773#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100774 mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
Valerio Settibd7528a2023-12-14 09:36:03 +0100775#else
776 mbedtls_cipher_free(&ctx->cipher_ctx);
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100777#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100778 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200779}
780
Valerio Setti689c0f72023-12-20 09:53:39 +0100781#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
Paul Bakker89e80c92012-03-20 13:50:09 +0000782/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200783 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000784 *
785 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
786 */
787#define MAX_TESTS 6
788
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100789static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100790{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000791
Yanray Wang93533b52023-05-11 16:45:59 +0800792static const unsigned char key_test_data[][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000793{
794 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
798 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
799 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
800 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200801 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000802};
803
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100804static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100805{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000806
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100807static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100808{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000809
Yanray Wang93533b52023-05-11 16:45:59 +0800810static const unsigned char iv_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000811{
812 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813 0x00, 0x00, 0x00, 0x00 },
814 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
815 0xde, 0xca, 0xf8, 0x88 },
816 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200817 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000818 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200819 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000820 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200821 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000822 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200823 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000824};
825
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100826static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100827{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000828
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100829static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100830{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000831
Yanray Wang93533b52023-05-11 16:45:59 +0800832static const unsigned char additional_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000833{
834 { 0x00 },
835 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200836 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000837 0xab, 0xad, 0xda, 0xd2 },
838};
839
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100840static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100841{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000842
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100843static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100844{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000845
Yanray Wang93533b52023-05-11 16:45:59 +0800846static const unsigned char pt_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000847{
848 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
850 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
851 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
852 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
853 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
854 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
855 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
856 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
857 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
858};
859
Yanray Wangd329c692023-05-11 16:40:57 +0800860static const unsigned char ct_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000861{
862 { 0x00 },
863 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
864 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
865 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200866 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000867 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200868 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000869 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200870 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000871 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
872 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
873 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200874 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000875 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200876 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000877 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200878 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000879 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
880 0x3d, 0x58, 0xe0, 0x91 },
881 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200882 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000883 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200884 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000885 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200886 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000887 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
888 0xc2, 0x3f, 0x45, 0x98 },
889 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200890 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000891 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200892 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000893 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200894 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000895 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
896 0x4c, 0x34, 0xae, 0xe5 },
Yanray Wangd329c692023-05-11 16:40:57 +0800897#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000898 { 0x00 },
899 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200900 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000901 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200902 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000903 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200904 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000905 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200906 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000907 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
908 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
909 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200910 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000911 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200912 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
913 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
914 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000915 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200916 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000917 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200918 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000919 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200920 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000921 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200922 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000923 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200924 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000925 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200926 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000927 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200928 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000929 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200930 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000931 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200932 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000933 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200934 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
935 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
936 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
937 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
938 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
939 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
940 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
941 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
942 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
943 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
944 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
945 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
946 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
947 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
948 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
949 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
950 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
951 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000952 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200953 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000954 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200955 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000956 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200957 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000958 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200959 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000960 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200961 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000962 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200963 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000964 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200965 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000966 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200967 0x44, 0xae, 0x7e, 0x3f },
Yanray Wangd329c692023-05-11 16:40:57 +0800968#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000969};
970
Yanray Wangd329c692023-05-11 16:40:57 +0800971static const unsigned char tag_test_data[][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000972{
973 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
974 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
975 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
976 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
977 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200978 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000979 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
980 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
981 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
982 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
983 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
984 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
Yanray Wangd329c692023-05-11 16:40:57 +0800985#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000986 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
987 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
988 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200989 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000990 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
991 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
992 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200993 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000994 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200995 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000996 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200997 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000998 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200999 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +00001000 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +02001001 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +00001002 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +02001003 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +00001004 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +02001005 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +00001006 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +02001007 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +00001008 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +02001009 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Yanray Wangd329c692023-05-11 16:40:57 +08001010#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +00001011};
1012
Gilles Peskine449bd832023-01-11 14:50:10 +01001013int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +00001014{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +00001016 unsigned char buf[64];
1017 unsigned char tag_buf[16];
1018 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001020 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +00001021
Gilles Peskine0cd9ab72023-03-16 13:06:14 +01001022 if (verbose != 0) {
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001023#if defined(MBEDTLS_AESNI_HAVE_CODE)
1024 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
1025 mbedtls_printf(" GCM note: using AESNI.\n");
1026 } else
1027#endif
Jerry Yu2f26a592023-03-31 15:06:33 +08001028
Jerry Yu72fd0bd2023-08-18 16:31:01 +08001029#if defined(MBEDTLS_AESCE_HAVE_CODE)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +01001030 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yu2f26a592023-03-31 15:06:33 +08001031 mbedtls_printf(" GCM note: using AESCE.\n");
1032 } else
1033#endif
1034
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001035 mbedtls_printf(" GCM note: built-in implementation.\n");
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001036 }
1037
Yanray Wangd329c692023-05-11 16:40:57 +08001038 static const int loop_limit =
1039 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
1040
1041 for (j = 0; j < loop_limit; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +00001042 int key_len = 128 + 64 * j;
1043
Gilles Peskine449bd832023-01-11 14:50:10 +01001044 for (i = 0; i < MAX_TESTS; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001045 if (verbose != 0) {
1046 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1047 key_len, i, "enc");
1048 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001049
Arto Kinnunen0f066182023-04-20 10:02:46 +08001050 mbedtls_gcm_init(&ctx);
1051
Gilles Peskine449bd832023-01-11 14:50:10 +01001052 ret = mbedtls_gcm_setkey(&ctx, cipher,
1053 key_test_data[key_index_test_data[i]],
1054 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +01001055 /*
1056 * AES-192 is an optional feature that may be unavailable when
Thomas Daubney41376092024-06-04 16:37:42 +01001057 * there is an alternative underlying implementation such as a
1058 * PSA driver.
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +01001059 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
1061 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001062 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001063 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001064 goto exit;
1065 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001066
Gilles Peskine449bd832023-01-11 14:50:10 +01001067 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
1068 pt_len_test_data[i],
1069 iv_test_data[iv_index_test_data[i]],
1070 iv_len_test_data[i],
1071 additional_test_data[add_index_test_data[i]],
1072 add_len_test_data[i],
1073 pt_test_data[pt_index_test_data[i]],
1074 buf, 16, tag_buf);
Gilles Peskine449bd832023-01-11 14:50:10 +01001075 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001076 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001077 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001078
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 if (memcmp(buf, ct_test_data[j * 6 + i],
1080 pt_len_test_data[i]) != 0 ||
1081 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001082 ret = 1;
1083 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +00001084 }
1085
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001087
Gilles Peskine449bd832023-01-11 14:50:10 +01001088 if (verbose != 0) {
1089 mbedtls_printf("passed\n");
1090 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001091
Gilles Peskine449bd832023-01-11 14:50:10 +01001092 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001093
Gilles Peskine449bd832023-01-11 14:50:10 +01001094 if (verbose != 0) {
1095 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1096 key_len, i, "dec");
1097 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001098
Gilles Peskine449bd832023-01-11 14:50:10 +01001099 ret = mbedtls_gcm_setkey(&ctx, cipher,
1100 key_test_data[key_index_test_data[i]],
1101 key_len);
1102 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001103 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
1107 pt_len_test_data[i],
1108 iv_test_data[iv_index_test_data[i]],
1109 iv_len_test_data[i],
1110 additional_test_data[add_index_test_data[i]],
1111 add_len_test_data[i],
1112 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +00001113
Gilles Peskine449bd832023-01-11 14:50:10 +01001114 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001115 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001117
Gilles Peskine449bd832023-01-11 14:50:10 +01001118 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1119 pt_len_test_data[i]) != 0 ||
1120 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001121 ret = 1;
1122 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +00001123 }
1124
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001126
Gilles Peskine449bd832023-01-11 14:50:10 +01001127 if (verbose != 0) {
1128 mbedtls_printf("passed\n");
1129 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001130
Gilles Peskine449bd832023-01-11 14:50:10 +01001131 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001132
Gilles Peskine449bd832023-01-11 14:50:10 +01001133 if (verbose != 0) {
1134 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1135 key_len, i, "enc");
1136 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001137
Gilles Peskine449bd832023-01-11 14:50:10 +01001138 ret = mbedtls_gcm_setkey(&ctx, cipher,
1139 key_test_data[key_index_test_data[i]],
1140 key_len);
1141 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001142 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001143 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001144
Gilles Peskine449bd832023-01-11 14:50:10 +01001145 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1146 iv_test_data[iv_index_test_data[i]],
1147 iv_len_test_data[i]);
1148 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001149 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001150 }
Gilles Peskine295fc132021-04-15 18:32:23 +02001151
Gilles Peskine449bd832023-01-11 14:50:10 +01001152 ret = mbedtls_gcm_update_ad(&ctx,
1153 additional_test_data[add_index_test_data[i]],
1154 add_len_test_data[i]);
1155 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001156 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001157 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001158
Gilles Peskine449bd832023-01-11 14:50:10 +01001159 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001160 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001161 ret = mbedtls_gcm_update(&ctx,
1162 pt_test_data[pt_index_test_data[i]],
1163 32,
1164 buf, sizeof(buf), &olen);
1165 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001166 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001167 }
1168 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001169 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001171
Gilles Peskine449bd832023-01-11 14:50:10 +01001172 ret = mbedtls_gcm_update(&ctx,
1173 pt_test_data[pt_index_test_data[i]] + 32,
1174 rest_len,
1175 buf + 32, sizeof(buf) - 32, &olen);
1176 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001177 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001178 }
1179 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001180 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001181 }
1182 } else {
1183 ret = mbedtls_gcm_update(&ctx,
1184 pt_test_data[pt_index_test_data[i]],
1185 pt_len_test_data[i],
1186 buf, sizeof(buf), &olen);
1187 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001188 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001189 }
1190 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001191 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001193 }
1194
Gilles Peskine449bd832023-01-11 14:50:10 +01001195 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1196 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001197 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001198 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001199
Gilles Peskine449bd832023-01-11 14:50:10 +01001200 if (memcmp(buf, ct_test_data[j * 6 + i],
1201 pt_len_test_data[i]) != 0 ||
1202 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001203 ret = 1;
1204 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001205 }
1206
Gilles Peskine449bd832023-01-11 14:50:10 +01001207 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001208
Gilles Peskine449bd832023-01-11 14:50:10 +01001209 if (verbose != 0) {
1210 mbedtls_printf("passed\n");
1211 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001212
Gilles Peskine449bd832023-01-11 14:50:10 +01001213 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001214
Gilles Peskine449bd832023-01-11 14:50:10 +01001215 if (verbose != 0) {
1216 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1217 key_len, i, "dec");
1218 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001219
Gilles Peskine449bd832023-01-11 14:50:10 +01001220 ret = mbedtls_gcm_setkey(&ctx, cipher,
1221 key_test_data[key_index_test_data[i]],
1222 key_len);
1223 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001224 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001225 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001226
Gilles Peskine449bd832023-01-11 14:50:10 +01001227 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1228 iv_test_data[iv_index_test_data[i]],
1229 iv_len_test_data[i]);
1230 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001231 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001232 }
1233 ret = mbedtls_gcm_update_ad(&ctx,
1234 additional_test_data[add_index_test_data[i]],
1235 add_len_test_data[i]);
1236 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001237 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001238 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001239
Gilles Peskine449bd832023-01-11 14:50:10 +01001240 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001241 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001242 ret = mbedtls_gcm_update(&ctx,
1243 ct_test_data[j * 6 + i], 32,
1244 buf, sizeof(buf), &olen);
1245 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001246 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001247 }
1248 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001249 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001250 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001251
Gilles Peskine449bd832023-01-11 14:50:10 +01001252 ret = mbedtls_gcm_update(&ctx,
1253 ct_test_data[j * 6 + i] + 32,
1254 rest_len,
1255 buf + 32, sizeof(buf) - 32, &olen);
1256 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001257 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001258 }
1259 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001260 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001261 }
1262 } else {
1263 ret = mbedtls_gcm_update(&ctx,
1264 ct_test_data[j * 6 + i],
1265 pt_len_test_data[i],
1266 buf, sizeof(buf), &olen);
1267 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001268 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001269 }
1270 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001271 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001272 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001273 }
1274
Gilles Peskine449bd832023-01-11 14:50:10 +01001275 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1276 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001277 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001278 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001279
Gilles Peskine449bd832023-01-11 14:50:10 +01001280 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1281 pt_len_test_data[i]) != 0 ||
1282 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001283 ret = 1;
1284 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001285 }
1286
Gilles Peskine449bd832023-01-11 14:50:10 +01001287 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001288
Gilles Peskine449bd832023-01-11 14:50:10 +01001289 if (verbose != 0) {
1290 mbedtls_printf("passed\n");
1291 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001292 }
1293 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001294
Gilles Peskine449bd832023-01-11 14:50:10 +01001295 if (verbose != 0) {
1296 mbedtls_printf("\n");
1297 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001298
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001299 ret = 0;
1300
1301exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001302 if (ret != 0) {
1303 if (verbose != 0) {
1304 mbedtls_printf("failed\n");
1305 }
1306 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001307 }
1308
Gilles Peskine449bd832023-01-11 14:50:10 +01001309 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001310}
1311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001312#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314#endif /* MBEDTLS_GCM_C */