blob: d7acacedb15cae3e928700f1c3447c1931998210 [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
Jaeden Amero15263302017-09-21 12:53:48 +010042#if !defined(MBEDTLS_GCM_ALT)
43
Matthias Schulz78266782024-02-08 13:54:48 +010044/* 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
Paul Bakker89e80c92012-03-20 13:50:09 +000050/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020051 * Initialize a context
52 */
Gilles Peskine449bd832023-01-11 14:50:10 +010053void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020054{
Gilles Peskine449bd832023-01-11 14:50:10 +010055 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020056}
57
Matthias Schulz0767fda2024-02-07 10:46:28 +010058static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)
59{
60#if defined(MBEDTLS_GCM_LARGETABLE)
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
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020091/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010092 * 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 */
Gilles Peskine449bd832023-01-11 14:50:10 +010099static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +0000100{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200101 int ret, i, j;
Matthias Schulz0767fda2024-02-07 10:46:28 +0100102 uint64_t u64h[2] = { 0 };
103 uint8_t *h = (uint8_t *) u64h;
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100104
Valerio Settibd7528a2023-12-14 09:36:03 +0100105#if defined(MBEDTLS_BLOCK_CIPHER_C)
106 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
107#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100108 size_t olen = 0;
Valerio Settid0eebc12023-11-20 15:17:53 +0100109 ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100110#endif
111 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100112 return ret;
113 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000114
Matthias Schulz0767fda2024-02-07 10:46:28 +0100115 gcm_set_acceleration(ctx);
Paul Bakker89e80c92012-03-20 13:50:09 +0000116
Matthias Schulz0767fda2024-02-07 10:46:28 +0100117 /* 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];
Paul Bakker169b7f42013-06-25 14:58:00 +0200120
Matthias Schulz0767fda2024-02-07 10:46:28 +0100121 switch (ctx->acceleration) {
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100122#if defined(MBEDTLS_AESNI_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100123 case MBEDTLS_GCM_ACC_AESNI:
124 return 0;
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100125#endif
126
Jerry Yu72fd0bd2023-08-18 16:31:01 +0800127#if defined(MBEDTLS_AESCE_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100128 case MBEDTLS_GCM_ACC_AESCE:
129 return 0;
Jerry Yudf87a122023-01-10 18:17:15 +0800130#endif
131
Matthias Schulz0767fda2024-02-07 10:46:28 +0100132 default:
133 /* 0 corresponds to 0 in GF(2^128) */
134 ctx->H[0][0] = 0;
135 ctx->H[0][1] = 0;
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100136
Matthias Schulz0767fda2024-02-07 10:46:28 +0100137 for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
138 gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
139 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000140
Matthias Schulz0767fda2024-02-07 10:46:28 +0100141#if !defined(MBEDTLS_GCM_LARGETABLE)
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
Paul Bakker89e80c92012-03-20 13:50:09 +0000148
Matthias Schulz0767fda2024-02-07 10:46:28 +0100149 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 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000157 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200158
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000160}
161
Gilles Peskine449bd832023-01-11 14:50:10 +0100162int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
163 mbedtls_cipher_id_t cipher,
164 const unsigned char *key,
165 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000166{
Janos Follath24eed8d2019-11-22 13:21:35 +0000167 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000168
Gilles Peskine449bd832023-01-11 14:50:10 +0100169 if (keybits != 128 && keybits != 192 && keybits != 256) {
Tuvshinzaya Erdenekhuuc6b8a672022-08-05 15:31:57 +0100170 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200171 }
172
Valerio Settibd7528a2023-12-14 09:36:03 +0100173#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
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100184 const mbedtls_cipher_info_t *cipher_info;
185
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 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 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000191
Dave Rodgman85a88132023-06-24 11:41:50 +0100192 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 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 }
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100206#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100207
208 if ((ret = gcm_gen_table(ctx)) != 0) {
209 return ret;
210 }
211
212 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000213}
214
Matthias Schulz0767fda2024-02-07 10:46:28 +0100215#if defined(MBEDTLS_GCM_LARGETABLE)
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
Matthias Schulz78266782024-02-08 13:54:48 +0100262 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];
Matthias Schulz0767fda2024-02-07 10:46:28 +0100266
Matthias Schulz78266782024-02-08 13:54:48 +0100267 u64z[1] >>= 8;
268 u8z[8] = u8z[7];
269 u64z[0] >>= 8;
Matthias Schulz0767fda2024-02-07 10:46:28 +0100270
Matthias Schulz78266782024-02-08 13:54:48 +0100271 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];
Matthias Schulz0767fda2024-02-07 10:46:28 +0100277
Matthias Schulz78266782024-02-08 13:54:48 +0100278 u64z[1] <<= 8;
279 u8z[8] = u8z[7];
280 u64z[0] <<= 8;
281
282 u16z[0] ^= last8[rem];
283 }
Matthias Schulz0767fda2024-02-07 10:46:28 +0100284 }
285
286 mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);
287}
288#else
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100289/*
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 */
Dave Rodgman5ff02452023-07-13 15:55:21 +0100294static const uint16_t last4[16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000295{
296 0x0000, 0x1c20, 0x3840, 0x2460,
297 0x7080, 0x6ca0, 0x48c0, 0x54e0,
298 0xe100, 0xfd20, 0xd940, 0xc560,
299 0x9180, 0x8da0, 0xa9c0, 0xb5e0
300};
301
Matthias Schulz0767fda2024-02-07 10:46:28 +0100302static 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];
Matthias Schulz10902c52024-02-09 11:14:50 +0100307 const uint64_t *pu64z = NULL;
Matthias Schulz0767fda2024-02-07 10:46:28 +0100308 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
Matthias Schulz78266782024-02-08 13:54:48 +0100338 MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);
339 MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);
Matthias Schulz0767fda2024-02-07 10:46:28 +0100340}
341#endif
342
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100343/*
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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100347static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
348 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000349{
Matthias Schulz0767fda2024-02-07 10:46:28 +0100350 switch (ctx->acceleration) {
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100351#if defined(MBEDTLS_AESNI_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100352 case MBEDTLS_GCM_ACC_AESNI:
353 mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
354 break;
Jerry Yudf87a122023-01-10 18:17:15 +0800355#endif
356
Matthias Schulz0767fda2024-02-07 10:46:28 +0100357#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
Paul Bakker89e80c92012-03-20 13:50:09 +0000362
Matthias Schulz0767fda2024-02-07 10:46:28 +0100363#if defined(MBEDTLS_GCM_LARGETABLE)
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
Paul Bakker89e80c92012-03-20 13:50:09 +0000372 }
373
Matthias Schulz0767fda2024-02-07 10:46:28 +0100374 return;
Paul Bakker89e80c92012-03-20 13:50:09 +0000375}
376
Gilles Peskine449bd832023-01-11 14:50:10 +0100377int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
378 int mode,
379 const unsigned char *iv, size_t iv_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000380{
Janos Follath24eed8d2019-11-22 13:21:35 +0000381 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000382 unsigned char work_buf[16];
Paul Bakker89e80c92012-03-20 13:50:09 +0000383 const unsigned char *p;
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100384 size_t use_len;
openluopworldeab65ac2021-09-22 23:59:42 +0800385 uint64_t iv_bits;
Valerio Settibd7528a2023-12-14 09:36:03 +0100386#if !defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100387 size_t olen = 0;
388#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000389
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200390 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200391 /* IV is not allowed to be zero length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
393 return MBEDTLS_ERR_GCM_BAD_INPUT;
394 }
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200395
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 memset(ctx->y, 0x00, sizeof(ctx->y));
397 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200398
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200399 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200400 ctx->len = 0;
401 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000402
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 if (iv_len == 12) {
404 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200405 ctx->y[15] = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 } 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);
Paul Bakker89e80c92012-03-20 13:50:09 +0000410
411 p = iv;
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 while (iv_len > 0) {
413 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200416
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000418
419 iv_len -= use_len;
420 p += use_len;
421 }
422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000424
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000426 }
427
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100428
Valerio Settibd7528a2023-12-14 09:36:03 +0100429#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Settid0eebc12023-11-20 15:17:53 +0100430 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr);
Valerio Settibd7528a2023-12-14 09:36:03 +0100431#else
432 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100433#endif
434 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100435 return ret;
436 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000437
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200439}
440
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200441/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200442 * mbedtls_gcm_context::buf contains the partial state of the computation of
443 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200444 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
445 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200446 * * len == 0 && add_len == 0: initial state
447 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
448 * a partial block of AD that has been
449 * xored in but not yet multiplied in.
450 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
451 * the data ends now.
452 * * len % 16 != 0: the first `len % 16` bytes have
453 * a partial block of ciphertext that has
454 * been xored in but not yet multiplied in.
455 * * len > 0 && len % 16 == 0: the authentication tag is correct if
456 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200457 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100458int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
459 const unsigned char *add, size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200460{
461 const unsigned char *p;
Dave Rodgmand22fb732022-11-22 16:53:25 +0000462 size_t use_len, offset;
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800463 uint64_t new_add_len;
Gilles Peskine295fc132021-04-15 18:32:23 +0200464
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800465 /* AD is limited to 2^64 bits, ie 2^61 bytes
466 * Also check for possible overflow */
Chien Wong019c2a72024-01-23 21:38:06 +0800467#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
468 if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
469 return MBEDTLS_ERR_GCM_BAD_INPUT;
470 }
471#endif
472 new_add_len = ctx->add_len + (uint64_t) add_len;
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800473 if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 return MBEDTLS_ERR_GCM_BAD_INPUT;
475 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200476
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200477 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000478 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200479
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200481 use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100482 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200483 use_len = add_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200485
Gilles Peskine449bd832023-01-11 14:50:10 +0100486 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200487
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 if (offset + use_len == 16) {
489 gcm_mult(ctx, ctx->buf, ctx->buf);
490 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200491
492 ctx->add_len += use_len;
493 add_len -= use_len;
494 p += use_len;
495 }
496
497 ctx->add_len += add_len;
498
Gilles Peskine449bd832023-01-11 14:50:10 +0100499 while (add_len >= 16) {
500 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000503
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200504 add_len -= 16;
505 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000506 }
507
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 if (add_len > 0) {
509 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200510 }
511
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200513}
514
Gilles Peskine58fc2722021-04-13 15:58:27 +0200515/* Increment the counter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100516static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200517{
Dave Rodgman46697da2024-01-14 12:59:49 +0000518 uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);
519 x++;
520 MBEDTLS_PUT_UINT32_BE(x, y, 12);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200521}
522
523/* Calculate and apply the encryption mask. Process use_len bytes of data,
524 * starting at position offset in the mask block. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100525static int gcm_mask(mbedtls_gcm_context *ctx,
526 unsigned char ectr[16],
527 size_t offset, size_t use_len,
528 const unsigned char *input,
529 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200530{
Gilles Peskine58fc2722021-04-13 15:58:27 +0200531 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Valerio Settid0eebc12023-11-20 15:17:53 +0100532
Valerio Settibd7528a2023-12-14 09:36:03 +0100533#if defined(MBEDTLS_BLOCK_CIPHER_C)
534 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);
535#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100536 size_t olen = 0;
Valerio Settid0eebc12023-11-20 15:17:53 +0100537 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100538#endif
539 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100540 mbedtls_platform_zeroize(ectr, 16);
541 return ret;
542 }
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100543
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
545 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
546 }
547 mbedtls_xor(output, ectr + offset, input, use_len);
548 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
549 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
550 }
Dave Rodgmand22fb732022-11-22 16:53:25 +0000551
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200553}
554
Gilles Peskine449bd832023-01-11 14:50:10 +0100555int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
556 const unsigned char *input, size_t input_length,
557 unsigned char *output, size_t output_size,
558 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200559{
Janos Follath24eed8d2019-11-22 13:21:35 +0000560 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200561 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200562 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200563 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200565
Gilles Peskine449bd832023-01-11 14:50:10 +0100566 if (output_size < input_length) {
567 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
568 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200569 *output_length = input_length;
570
571 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200572 * on a potentially null pointer.
573 * Returning early also means that the last partial block of AD remains
574 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100575 if (input_length == 0) {
576 return 0;
577 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200578
Gilles Peskine449bd832023-01-11 14:50:10 +0100579 if (output > input && (size_t) (output - input) < input_length) {
580 return MBEDTLS_ERR_GCM_BAD_INPUT;
581 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200582
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200583 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
584 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 if (ctx->len + input_length < ctx->len ||
586 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
587 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200588 }
589
Gilles Peskine449bd832023-01-11 14:50:10 +0100590 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
591 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200592 }
593
Gilles Peskine58fc2722021-04-13 15:58:27 +0200594 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100595 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200596 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200598 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100599 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000600
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
602 return ret;
603 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000604
Gilles Peskine449bd832023-01-11 14:50:10 +0100605 if (offset + use_len == 16) {
606 gcm_mult(ctx, ctx->buf, ctx->buf);
607 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200608
Gilles Peskine58fc2722021-04-13 15:58:27 +0200609 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200610 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 p += use_len;
612 out_p += use_len;
613 }
614
Gilles Peskinea56c4482021-04-15 17:22:35 +0200615 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200616
Gilles Peskine449bd832023-01-11 14:50:10 +0100617 while (input_length >= 16) {
618 gcm_incr(ctx->y);
619 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
620 return ret;
621 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200622
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200624
Gilles Peskinea56c4482021-04-15 17:22:35 +0200625 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200626 p += 16;
627 out_p += 16;
628 }
629
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 if (input_length > 0) {
631 gcm_incr(ctx->y);
632 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
633 return ret;
634 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200635 }
636
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 mbedtls_platform_zeroize(ectr, sizeof(ectr));
638 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200639}
640
Gilles Peskine449bd832023-01-11 14:50:10 +0100641int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
642 unsigned char *output, size_t output_size,
643 size_t *output_length,
644 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200645{
646 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100647 uint64_t orig_len;
648 uint64_t orig_add_len;
649
Gilles Peskine9461e452021-04-15 16:48:32 +0200650 /* We never pass any output in finish(). The output parameter exists only
651 * for the sake of alternative implementations. */
652 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200653 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200654 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200655
Chien Wong858bc652024-01-22 20:47:26 +0800656 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
657 * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
658 * the two multiplications would overflow. */
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100659 orig_len = ctx->len * 8;
660 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200661
Gilles Peskine449bd832023-01-11 14:50:10 +0100662 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
663 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200664 }
665
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 if (tag_len > 16 || tag_len < 4) {
667 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000668 }
669
Gilles Peskine449bd832023-01-11 14:50:10 +0100670 if (ctx->len % 16 != 0) {
671 gcm_mult(ctx, ctx->buf, ctx->buf);
672 }
673
674 memcpy(tag, ctx->base_ectr, tag_len);
675
676 if (orig_len || orig_add_len) {
677 memset(work_buf, 0x00, 16);
678
679 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
680 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
681 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
682 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
683
684 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
685
686 gcm_mult(ctx, ctx->buf, ctx->buf);
687
688 mbedtls_xor(tag, tag, ctx->buf, tag_len);
689 }
690
691 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000692}
693
Gilles Peskine449bd832023-01-11 14:50:10 +0100694int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
695 int mode,
696 size_t length,
697 const unsigned char *iv,
698 size_t iv_len,
699 const unsigned char *add,
700 size_t add_len,
701 const unsigned char *input,
702 unsigned char *output,
703 size_t tag_len,
704 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200705{
Janos Follath24eed8d2019-11-22 13:21:35 +0000706 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200707 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200708
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
710 return ret;
711 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200712
Gilles Peskine449bd832023-01-11 14:50:10 +0100713 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
714 return ret;
715 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200716
Gilles Peskine449bd832023-01-11 14:50:10 +0100717 if ((ret = mbedtls_gcm_update(ctx, input, length,
718 output, length, &olen)) != 0) {
719 return ret;
720 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200721
Gilles Peskine449bd832023-01-11 14:50:10 +0100722 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
723 return ret;
724 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200725
Gilles Peskine449bd832023-01-11 14:50:10 +0100726 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200727}
728
Gilles Peskine449bd832023-01-11 14:50:10 +0100729int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
730 size_t length,
731 const unsigned char *iv,
732 size_t iv_len,
733 const unsigned char *add,
734 size_t add_len,
735 const unsigned char *tag,
736 size_t tag_len,
737 const unsigned char *input,
738 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000739{
Janos Follath24eed8d2019-11-22 13:21:35 +0000740 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000741 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200742 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000743
Gilles Peskine449bd832023-01-11 14:50:10 +0100744 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
745 iv, iv_len, add, add_len,
746 input, output, tag_len, check_tag)) != 0) {
747 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100748 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000749
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200750 /* Check tag in "constant-time" */
Dave Rodgmand26a3d62023-09-11 18:25:16 +0100751 diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
Paul Bakker89e80c92012-03-20 13:50:09 +0000752
Gilles Peskine449bd832023-01-11 14:50:10 +0100753 if (diff != 0) {
754 mbedtls_platform_zeroize(output, length);
755 return MBEDTLS_ERR_GCM_AUTH_FAILED;
756 }
757
758 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000759}
760
Gilles Peskine449bd832023-01-11 14:50:10 +0100761void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200762{
Gilles Peskine449bd832023-01-11 14:50:10 +0100763 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100764 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100765 }
Valerio Settibd7528a2023-12-14 09:36:03 +0100766#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100767 mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
Valerio Settibd7528a2023-12-14 09:36:03 +0100768#else
769 mbedtls_cipher_free(&ctx->cipher_ctx);
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100770#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100771 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200772}
773
Jaeden Amero15263302017-09-21 12:53:48 +0100774#endif /* !MBEDTLS_GCM_ALT */
775
Valerio Setti689c0f72023-12-20 09:53:39 +0100776#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
Paul Bakker89e80c92012-03-20 13:50:09 +0000777/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200778 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000779 *
780 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
781 */
782#define MAX_TESTS 6
783
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100784static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100785{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000786
Yanray Wang93533b52023-05-11 16:45:59 +0800787static const unsigned char key_test_data[][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000788{
789 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
793 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
794 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
795 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200796 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000797};
798
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100799static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100800{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000801
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100802static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100803{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000804
Yanray Wang93533b52023-05-11 16:45:59 +0800805static const unsigned char iv_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000806{
807 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00 },
809 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
810 0xde, 0xca, 0xf8, 0x88 },
811 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200812 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000813 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200814 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000815 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200816 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000817 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200818 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000819};
820
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100821static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100822{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000823
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100824static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100825{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000826
Yanray Wang93533b52023-05-11 16:45:59 +0800827static const unsigned char additional_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000828{
829 { 0x00 },
830 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200831 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000832 0xab, 0xad, 0xda, 0xd2 },
833};
834
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100835static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100836{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000837
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100838static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100839{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000840
Yanray Wang93533b52023-05-11 16:45:59 +0800841static const unsigned char pt_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000842{
843 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
845 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
846 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
847 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
848 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
849 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
850 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
851 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
852 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
853};
854
Yanray Wangd329c692023-05-11 16:40:57 +0800855static const unsigned char ct_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000856{
857 { 0x00 },
858 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
859 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
860 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200861 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000862 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200863 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000864 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200865 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000866 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
867 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
868 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200869 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000870 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200871 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000872 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200873 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000874 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
875 0x3d, 0x58, 0xe0, 0x91 },
876 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200877 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000878 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200879 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000880 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200881 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000882 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
883 0xc2, 0x3f, 0x45, 0x98 },
884 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200885 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000886 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200887 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000888 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200889 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000890 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
891 0x4c, 0x34, 0xae, 0xe5 },
Yanray Wangd329c692023-05-11 16:40:57 +0800892#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000893 { 0x00 },
894 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200895 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000896 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200897 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000898 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200899 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000900 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200901 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000902 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
903 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
904 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200905 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000906 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200907 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
908 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
909 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000910 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200911 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000912 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200913 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000914 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200915 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000916 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200917 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000918 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200919 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000920 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200921 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000922 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200923 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000924 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200925 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000926 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200927 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000928 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200929 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
930 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
931 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
932 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
933 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
934 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
935 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
936 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
937 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
938 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
939 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
940 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
941 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
942 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
943 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
944 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
945 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
946 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000947 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200948 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000949 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200950 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000951 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200952 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000953 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200954 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000955 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200956 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000957 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200958 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000959 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200960 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000961 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200962 0x44, 0xae, 0x7e, 0x3f },
Yanray Wangd329c692023-05-11 16:40:57 +0800963#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000964};
965
Yanray Wangd329c692023-05-11 16:40:57 +0800966static const unsigned char tag_test_data[][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000967{
968 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
969 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
970 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
971 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
972 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200973 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000974 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
975 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
976 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
977 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
978 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
979 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
Yanray Wangd329c692023-05-11 16:40:57 +0800980#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000981 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
982 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
983 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200984 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000985 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
986 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
987 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200988 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000989 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200990 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000991 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200992 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000993 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200994 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000995 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200996 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000997 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200998 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000999 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +02001000 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +00001001 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +02001002 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +00001003 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +02001004 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Yanray Wangd329c692023-05-11 16:40:57 +08001005#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +00001006};
1007
Gilles Peskine449bd832023-01-11 14:50:10 +01001008int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +00001009{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +00001011 unsigned char buf[64];
1012 unsigned char tag_buf[16];
1013 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001015 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +00001016
Gilles Peskine0cd9ab72023-03-16 13:06:14 +01001017 if (verbose != 0) {
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001018#if defined(MBEDTLS_GCM_ALT)
1019 mbedtls_printf(" GCM note: alternative implementation.\n");
1020#else /* MBEDTLS_GCM_ALT */
1021#if defined(MBEDTLS_AESNI_HAVE_CODE)
1022 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
1023 mbedtls_printf(" GCM note: using AESNI.\n");
1024 } else
1025#endif
Jerry Yu2f26a592023-03-31 15:06:33 +08001026
Jerry Yu72fd0bd2023-08-18 16:31:01 +08001027#if defined(MBEDTLS_AESCE_HAVE_CODE)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +01001028 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yu2f26a592023-03-31 15:06:33 +08001029 mbedtls_printf(" GCM note: using AESCE.\n");
1030 } else
1031#endif
1032
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001033 mbedtls_printf(" GCM note: built-in implementation.\n");
1034#endif /* MBEDTLS_GCM_ALT */
1035 }
1036
Yanray Wangd329c692023-05-11 16:40:57 +08001037 static const int loop_limit =
1038 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
1039
1040 for (j = 0; j < loop_limit; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +00001041 int key_len = 128 + 64 * j;
1042
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 for (i = 0; i < MAX_TESTS; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001044 if (verbose != 0) {
1045 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1046 key_len, i, "enc");
1047 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001048
Arto Kinnunen0f066182023-04-20 10:02:46 +08001049 mbedtls_gcm_init(&ctx);
1050
Gilles Peskine449bd832023-01-11 14:50:10 +01001051 ret = mbedtls_gcm_setkey(&ctx, cipher,
1052 key_test_data[key_index_test_data[i]],
1053 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +01001054 /*
1055 * AES-192 is an optional feature that may be unavailable when
1056 * there is an alternative underlying implementation i.e. when
1057 * MBEDTLS_AES_ALT is defined.
1058 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001059 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
1060 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001061 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001062 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001063 goto exit;
1064 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001065
Gilles Peskine449bd832023-01-11 14:50:10 +01001066 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
1067 pt_len_test_data[i],
1068 iv_test_data[iv_index_test_data[i]],
1069 iv_len_test_data[i],
1070 additional_test_data[add_index_test_data[i]],
1071 add_len_test_data[i],
1072 pt_test_data[pt_index_test_data[i]],
1073 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +01001074#if defined(MBEDTLS_GCM_ALT)
1075 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001076 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
1077 iv_len_test_data[i] != 12) {
1078 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +01001079 break;
1080 }
1081#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +01001082 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001083 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001084 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001085
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 if (memcmp(buf, ct_test_data[j * 6 + i],
1087 pt_len_test_data[i]) != 0 ||
1088 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001089 ret = 1;
1090 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +00001091 }
1092
Gilles Peskine449bd832023-01-11 14:50:10 +01001093 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001094
Gilles Peskine449bd832023-01-11 14:50:10 +01001095 if (verbose != 0) {
1096 mbedtls_printf("passed\n");
1097 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001098
Gilles Peskine449bd832023-01-11 14:50:10 +01001099 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001100
Gilles Peskine449bd832023-01-11 14:50:10 +01001101 if (verbose != 0) {
1102 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1103 key_len, i, "dec");
1104 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 ret = mbedtls_gcm_setkey(&ctx, cipher,
1107 key_test_data[key_index_test_data[i]],
1108 key_len);
1109 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001110 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001111 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001112
Gilles Peskine449bd832023-01-11 14:50:10 +01001113 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
1114 pt_len_test_data[i],
1115 iv_test_data[iv_index_test_data[i]],
1116 iv_len_test_data[i],
1117 additional_test_data[add_index_test_data[i]],
1118 add_len_test_data[i],
1119 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +00001120
Gilles Peskine449bd832023-01-11 14:50:10 +01001121 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001122 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001123 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001124
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1126 pt_len_test_data[i]) != 0 ||
1127 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001128 ret = 1;
1129 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +00001130 }
1131
Gilles Peskine449bd832023-01-11 14:50:10 +01001132 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 if (verbose != 0) {
1135 mbedtls_printf("passed\n");
1136 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001137
Gilles Peskine449bd832023-01-11 14:50:10 +01001138 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001139
Gilles Peskine449bd832023-01-11 14:50:10 +01001140 if (verbose != 0) {
1141 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1142 key_len, i, "enc");
1143 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001144
Gilles Peskine449bd832023-01-11 14:50:10 +01001145 ret = mbedtls_gcm_setkey(&ctx, cipher,
1146 key_test_data[key_index_test_data[i]],
1147 key_len);
1148 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001149 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001150 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001151
Gilles Peskine449bd832023-01-11 14:50:10 +01001152 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1153 iv_test_data[iv_index_test_data[i]],
1154 iv_len_test_data[i]);
1155 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001156 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001157 }
Gilles Peskine295fc132021-04-15 18:32:23 +02001158
Gilles Peskine449bd832023-01-11 14:50:10 +01001159 ret = mbedtls_gcm_update_ad(&ctx,
1160 additional_test_data[add_index_test_data[i]],
1161 add_len_test_data[i]);
1162 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001163 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001164 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001165
Gilles Peskine449bd832023-01-11 14:50:10 +01001166 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001167 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001168 ret = mbedtls_gcm_update(&ctx,
1169 pt_test_data[pt_index_test_data[i]],
1170 32,
1171 buf, sizeof(buf), &olen);
1172 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001173 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001174 }
1175 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001176 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001177 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001178
Gilles Peskine449bd832023-01-11 14:50:10 +01001179 ret = mbedtls_gcm_update(&ctx,
1180 pt_test_data[pt_index_test_data[i]] + 32,
1181 rest_len,
1182 buf + 32, sizeof(buf) - 32, &olen);
1183 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001184 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001185 }
1186 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001187 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001188 }
1189 } else {
1190 ret = mbedtls_gcm_update(&ctx,
1191 pt_test_data[pt_index_test_data[i]],
1192 pt_len_test_data[i],
1193 buf, sizeof(buf), &olen);
1194 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001195 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001196 }
1197 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001198 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001199 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001200 }
1201
Gilles Peskine449bd832023-01-11 14:50:10 +01001202 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1203 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001204 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001205 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001206
Gilles Peskine449bd832023-01-11 14:50:10 +01001207 if (memcmp(buf, ct_test_data[j * 6 + i],
1208 pt_len_test_data[i]) != 0 ||
1209 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001210 ret = 1;
1211 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001212 }
1213
Gilles Peskine449bd832023-01-11 14:50:10 +01001214 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001215
Gilles Peskine449bd832023-01-11 14:50:10 +01001216 if (verbose != 0) {
1217 mbedtls_printf("passed\n");
1218 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001219
Gilles Peskine449bd832023-01-11 14:50:10 +01001220 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001221
Gilles Peskine449bd832023-01-11 14:50:10 +01001222 if (verbose != 0) {
1223 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1224 key_len, i, "dec");
1225 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001226
Gilles Peskine449bd832023-01-11 14:50:10 +01001227 ret = mbedtls_gcm_setkey(&ctx, cipher,
1228 key_test_data[key_index_test_data[i]],
1229 key_len);
1230 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001231 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001232 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001233
Gilles Peskine449bd832023-01-11 14:50:10 +01001234 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1235 iv_test_data[iv_index_test_data[i]],
1236 iv_len_test_data[i]);
1237 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001238 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001239 }
1240 ret = mbedtls_gcm_update_ad(&ctx,
1241 additional_test_data[add_index_test_data[i]],
1242 add_len_test_data[i]);
1243 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001244 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001245 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001246
Gilles Peskine449bd832023-01-11 14:50:10 +01001247 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001248 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001249 ret = mbedtls_gcm_update(&ctx,
1250 ct_test_data[j * 6 + i], 32,
1251 buf, sizeof(buf), &olen);
1252 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001253 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001254 }
1255 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001256 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001257 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001258
Gilles Peskine449bd832023-01-11 14:50:10 +01001259 ret = mbedtls_gcm_update(&ctx,
1260 ct_test_data[j * 6 + i] + 32,
1261 rest_len,
1262 buf + 32, sizeof(buf) - 32, &olen);
1263 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001264 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001265 }
1266 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001267 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001268 }
1269 } else {
1270 ret = mbedtls_gcm_update(&ctx,
1271 ct_test_data[j * 6 + i],
1272 pt_len_test_data[i],
1273 buf, sizeof(buf), &olen);
1274 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001275 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001276 }
1277 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001278 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001279 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001280 }
1281
Gilles Peskine449bd832023-01-11 14:50:10 +01001282 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1283 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001284 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001285 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001286
Gilles Peskine449bd832023-01-11 14:50:10 +01001287 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1288 pt_len_test_data[i]) != 0 ||
1289 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001290 ret = 1;
1291 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001292 }
1293
Gilles Peskine449bd832023-01-11 14:50:10 +01001294 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001295
Gilles Peskine449bd832023-01-11 14:50:10 +01001296 if (verbose != 0) {
1297 mbedtls_printf("passed\n");
1298 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001299 }
1300 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001301
Gilles Peskine449bd832023-01-11 14:50:10 +01001302 if (verbose != 0) {
1303 mbedtls_printf("\n");
1304 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001305
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001306 ret = 0;
1307
1308exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001309 if (ret != 0) {
1310 if (verbose != 0) {
1311 mbedtls_printf("failed\n");
1312 }
1313 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001314 }
1315
Gilles Peskine449bd832023-01-11 14:50:10 +01001316 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001317}
1318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321#endif /* MBEDTLS_GCM_C */