blob: 4a01f5c68735bde27c62c798027c8bfe7b12b086 [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
Paul Bakker89e80c92012-03-20 13:50:09 +000044/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020045 * Initialize a context
46 */
Gilles Peskine449bd832023-01-11 14:50:10 +010047void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020048{
Gilles Peskine449bd832023-01-11 14:50:10 +010049 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020050}
51
Matthias Schulz0767fda2024-02-07 10:46:28 +010052static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)
53{
54#if defined(MBEDTLS_GCM_LARGETABLE)
55 ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE;
56#else
57 ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE;
58#endif
59
60#if defined(MBEDTLS_AESNI_HAVE_CODE)
61 /* With CLMUL support, we need only h, not the rest of the table */
62 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
63 ctx->acceleration = MBEDTLS_GCM_ACC_AESNI;
64 }
65#endif
66
67#if defined(MBEDTLS_AESCE_HAVE_CODE)
68 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
69 ctx->acceleration = MBEDTLS_GCM_ACC_AESCE;
70 }
71#endif
72}
73
74static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])
75{
76 uint8_t *u8Dst = (uint8_t *) dst;
77 uint8_t *u8Src = (uint8_t *) src;
78
79 MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);
80 u8Dst[8] |= (u8Src[7] & 0x01) << 7;
81 MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);
82 u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;
83}
84
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020085/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010086 * Precompute small multiples of H, that is set
87 * HH[i] || HL[i] = H times i,
88 * where i is seen as a field element as in [MGV], ie high-order bits
89 * correspond to low powers of P. The result is stored in the same way, that
90 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
91 * corresponds to P^127.
92 */
Gilles Peskine449bd832023-01-11 14:50:10 +010093static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000094{
Paul Bakker43aff2a2013-09-09 00:10:27 +020095 int ret, i, j;
Matthias Schulz0767fda2024-02-07 10:46:28 +010096 uint64_t u64h[2] = { 0 };
97 uint8_t *h = (uint8_t *) u64h;
Valerio Setti9b7a8b22023-11-16 08:24:51 +010098
Valerio Settibd7528a2023-12-14 09:36:03 +010099#if defined(MBEDTLS_BLOCK_CIPHER_C)
100 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
101#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100102 size_t olen = 0;
Valerio Settid0eebc12023-11-20 15:17:53 +0100103 ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100104#endif
105 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100106 return ret;
107 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000108
Matthias Schulz0767fda2024-02-07 10:46:28 +0100109 gcm_set_acceleration(ctx);
Paul Bakker89e80c92012-03-20 13:50:09 +0000110
Matthias Schulz0767fda2024-02-07 10:46:28 +0100111 /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */
112 ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];
113 ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];
Paul Bakker169b7f42013-06-25 14:58:00 +0200114
Matthias Schulz0767fda2024-02-07 10:46:28 +0100115 switch (ctx->acceleration) {
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100116#if defined(MBEDTLS_AESNI_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100117 case MBEDTLS_GCM_ACC_AESNI:
118 return 0;
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100119#endif
120
Jerry Yu72fd0bd2023-08-18 16:31:01 +0800121#if defined(MBEDTLS_AESCE_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100122 case MBEDTLS_GCM_ACC_AESCE:
123 return 0;
Jerry Yudf87a122023-01-10 18:17:15 +0800124#endif
125
Matthias Schulz0767fda2024-02-07 10:46:28 +0100126 default:
127 /* 0 corresponds to 0 in GF(2^128) */
128 ctx->H[0][0] = 0;
129 ctx->H[0][1] = 0;
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100130
Matthias Schulz0767fda2024-02-07 10:46:28 +0100131 for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
132 gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
133 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000134
Matthias Schulz0767fda2024-02-07 10:46:28 +0100135#if !defined(MBEDTLS_GCM_LARGETABLE)
136 /* pack elements of H as 64-bits ints, big-endian */
137 for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {
138 MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);
139 MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);
140 }
141#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000142
Matthias Schulz0767fda2024-02-07 10:46:28 +0100143 for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {
144 for (j = 1; j < i; j++) {
145 mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],
146 (unsigned char *) ctx->H[i],
147 (unsigned char *) ctx->H[j],
148 16);
149 }
150 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000151 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200152
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000154}
155
Gilles Peskine449bd832023-01-11 14:50:10 +0100156int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
157 mbedtls_cipher_id_t cipher,
158 const unsigned char *key,
159 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000160{
Janos Follath24eed8d2019-11-22 13:21:35 +0000161 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000162
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 if (keybits != 128 && keybits != 192 && keybits != 256) {
Tuvshinzaya Erdenekhuuc6b8a672022-08-05 15:31:57 +0100164 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200165 }
166
Valerio Settibd7528a2023-12-14 09:36:03 +0100167#if defined(MBEDTLS_BLOCK_CIPHER_C)
168 mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
169
170 if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {
171 return ret;
172 }
173
174 if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {
175 return ret;
176 }
177#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100178 const mbedtls_cipher_info_t *cipher_info;
179
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
181 MBEDTLS_MODE_ECB);
182 if (cipher_info == NULL) {
183 return MBEDTLS_ERR_GCM_BAD_INPUT;
184 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000185
Dave Rodgman85a88132023-06-24 11:41:50 +0100186 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 return MBEDTLS_ERR_GCM_BAD_INPUT;
188 }
189
190 mbedtls_cipher_free(&ctx->cipher_ctx);
191
192 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
193 return ret;
194 }
195
196 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
197 MBEDTLS_ENCRYPT)) != 0) {
198 return ret;
199 }
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100200#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100201
202 if ((ret = gcm_gen_table(ctx)) != 0) {
203 return ret;
204 }
205
206 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000207}
208
Matthias Schulz0767fda2024-02-07 10:46:28 +0100209#if defined(MBEDTLS_GCM_LARGETABLE)
210static const uint16_t last8[256] = {
211 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05,
212 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b,
213 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19,
214 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17,
215 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d,
216 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33,
217 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21,
218 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f,
219 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75,
220 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b,
221 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69,
222 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67,
223 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d,
224 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43,
225 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51,
226 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f,
227 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4,
228 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea,
229 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8,
230 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6,
231 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc,
232 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2,
233 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0,
234 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece,
235 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94,
236 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a,
237 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88,
238 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86,
239 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac,
240 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2,
241 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0,
242 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe
243};
244
245static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2])
246{
247 int i;
248 uint64_t u64z[2];
249 uint16_t *u16z = (uint16_t *) u64z;
250 uint8_t *u8z = (uint8_t *) u64z;
251 uint8_t rem;
252
253 u64z[0] = 0;
254 u64z[1] = 0;
255
256 for (i = 15; i > 0; i--) {
257 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
258
259 rem = u8z[15];
260
261 u64z[1] <<= 8;
262 u8z[8] = u8z[7];
263 u64z[0] <<= 8;
264
265 u8z[0] = 0;
266 u16z[0] ^= last8[rem];
267 }
268
269 mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);
270}
271#else
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100272/*
273 * Shoup's method for multiplication use this table with
274 * last4[x] = x times P^128
275 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
276 */
Dave Rodgman5ff02452023-07-13 15:55:21 +0100277static const uint16_t last4[16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000278{
279 0x0000, 0x1c20, 0x3840, 0x2460,
280 0x7080, 0x6ca0, 0x48c0, 0x54e0,
281 0xe100, 0xfd20, 0xd940, 0xc560,
282 0x9180, 0x8da0, 0xa9c0, 0xb5e0
283};
284
Matthias Schulz0767fda2024-02-07 10:46:28 +0100285static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])
286{
287 int i = 0;
288 unsigned char lo, hi, rem;
289 uint64_t u64z[2];
290 const uint64_t *pu64z = 0;
291 uint8_t *u8z = (uint8_t *) u64z;
292
293 lo = x[15] & 0xf;
294 hi = (x[15] >> 4) & 0xf;
295
296 pu64z = H[lo];
297
298 rem = (unsigned char) pu64z[1] & 0xf;
299 u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);
300 u64z[0] = (pu64z[0] >> 4);
301 u64z[0] ^= (uint64_t) last4[rem] << 48;
302 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
303
304 for (i = 14; i >= 0; i--) {
305 lo = x[i] & 0xf;
306 hi = (x[i] >> 4) & 0xf;
307
308 rem = (unsigned char) u64z[1] & 0xf;
309 u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
310 u64z[0] = (u64z[0] >> 4);
311 u64z[0] ^= (uint64_t) last4[rem] << 48;
312 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);
313
314 rem = (unsigned char) u64z[1] & 0xf;
315 u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
316 u64z[0] = (u64z[0] >> 4);
317 u64z[0] ^= (uint64_t) last4[rem] << 48;
318 mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
319 }
320
321 MBEDTLS_PUT_UINT32_BE(u64z[0] >> 32, output, 0);
322 MBEDTLS_PUT_UINT32_BE(u64z[0], output, 4);
323 MBEDTLS_PUT_UINT32_BE(u64z[1] >> 32, output, 8);
324 MBEDTLS_PUT_UINT32_BE(u64z[1], output, 12);
325}
326#endif
327
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100328/*
329 * Sets output to x times H using the precomputed tables.
330 * x and output are seen as elements of GF(2^128) as in [MGV].
331 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100332static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
333 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000334{
Matthias Schulz0767fda2024-02-07 10:46:28 +0100335 switch (ctx->acceleration) {
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100336#if defined(MBEDTLS_AESNI_HAVE_CODE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100337 case MBEDTLS_GCM_ACC_AESNI:
338 mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
339 break;
Jerry Yudf87a122023-01-10 18:17:15 +0800340#endif
341
Matthias Schulz0767fda2024-02-07 10:46:28 +0100342#if defined(MBEDTLS_AESCE_HAVE_CODE)
343 case MBEDTLS_GCM_ACC_AESCE:
344 mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
345 break;
346#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000347
Matthias Schulz0767fda2024-02-07 10:46:28 +0100348#if defined(MBEDTLS_GCM_LARGETABLE)
349 case MBEDTLS_GCM_ACC_LARGETABLE:
350 gcm_mult_largetable(output, x, ctx->H);
351 break;
352#else
353 case MBEDTLS_GCM_ACC_SMALLTABLE:
354 gcm_mult_smalltable(output, x, ctx->H);
355 break;
356#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000357 }
358
Matthias Schulz0767fda2024-02-07 10:46:28 +0100359 return;
Paul Bakker89e80c92012-03-20 13:50:09 +0000360}
361
Gilles Peskine449bd832023-01-11 14:50:10 +0100362int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
363 int mode,
364 const unsigned char *iv, size_t iv_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000365{
Janos Follath24eed8d2019-11-22 13:21:35 +0000366 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000367 unsigned char work_buf[16];
Paul Bakker89e80c92012-03-20 13:50:09 +0000368 const unsigned char *p;
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100369 size_t use_len;
openluopworldeab65ac2021-09-22 23:59:42 +0800370 uint64_t iv_bits;
Valerio Settibd7528a2023-12-14 09:36:03 +0100371#if !defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100372 size_t olen = 0;
373#endif
Paul Bakker89e80c92012-03-20 13:50:09 +0000374
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200375 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200376 /* IV is not allowed to be zero length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
378 return MBEDTLS_ERR_GCM_BAD_INPUT;
379 }
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200380
Gilles Peskine449bd832023-01-11 14:50:10 +0100381 memset(ctx->y, 0x00, sizeof(ctx->y));
382 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200383
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200384 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200385 ctx->len = 0;
386 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 if (iv_len == 12) {
389 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200390 ctx->y[15] = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100391 } else {
392 memset(work_buf, 0x00, 16);
393 iv_bits = (uint64_t) iv_len * 8;
394 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000395
396 p = iv;
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 while (iv_len > 0) {
398 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000399
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200401
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000403
404 iv_len -= use_len;
405 p += use_len;
406 }
407
Gilles Peskine449bd832023-01-11 14:50:10 +0100408 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000411 }
412
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100413
Valerio Settibd7528a2023-12-14 09:36:03 +0100414#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Settid0eebc12023-11-20 15:17:53 +0100415 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr);
Valerio Settibd7528a2023-12-14 09:36:03 +0100416#else
417 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100418#endif
419 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100420 return ret;
421 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200424}
425
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200426/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200427 * mbedtls_gcm_context::buf contains the partial state of the computation of
428 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200429 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
430 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200431 * * len == 0 && add_len == 0: initial state
432 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
433 * a partial block of AD that has been
434 * xored in but not yet multiplied in.
435 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
436 * the data ends now.
437 * * len % 16 != 0: the first `len % 16` bytes have
438 * a partial block of ciphertext that has
439 * been xored in but not yet multiplied in.
440 * * len > 0 && len % 16 == 0: the authentication tag is correct if
441 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200442 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100443int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
444 const unsigned char *add, size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200445{
446 const unsigned char *p;
Dave Rodgmand22fb732022-11-22 16:53:25 +0000447 size_t use_len, offset;
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800448 uint64_t new_add_len;
Gilles Peskine295fc132021-04-15 18:32:23 +0200449
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800450 /* AD is limited to 2^64 bits, ie 2^61 bytes
451 * Also check for possible overflow */
Chien Wong019c2a72024-01-23 21:38:06 +0800452#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
453 if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
454 return MBEDTLS_ERR_GCM_BAD_INPUT;
455 }
456#endif
457 new_add_len = ctx->add_len + (uint64_t) add_len;
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800458 if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 return MBEDTLS_ERR_GCM_BAD_INPUT;
460 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200461
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200462 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000463 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200464
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200466 use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200468 use_len = add_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200470
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200472
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 if (offset + use_len == 16) {
474 gcm_mult(ctx, ctx->buf, ctx->buf);
475 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200476
477 ctx->add_len += use_len;
478 add_len -= use_len;
479 p += use_len;
480 }
481
482 ctx->add_len += add_len;
483
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 while (add_len >= 16) {
485 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200486
Gilles Peskine449bd832023-01-11 14:50:10 +0100487 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000488
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200489 add_len -= 16;
490 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000491 }
492
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 if (add_len > 0) {
494 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200495 }
496
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200498}
499
Gilles Peskine58fc2722021-04-13 15:58:27 +0200500/* Increment the counter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100501static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200502{
Dave Rodgman46697da2024-01-14 12:59:49 +0000503 uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);
504 x++;
505 MBEDTLS_PUT_UINT32_BE(x, y, 12);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200506}
507
508/* Calculate and apply the encryption mask. Process use_len bytes of data,
509 * starting at position offset in the mask block. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100510static int gcm_mask(mbedtls_gcm_context *ctx,
511 unsigned char ectr[16],
512 size_t offset, size_t use_len,
513 const unsigned char *input,
514 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200515{
Gilles Peskine58fc2722021-04-13 15:58:27 +0200516 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Valerio Settid0eebc12023-11-20 15:17:53 +0100517
Valerio Settibd7528a2023-12-14 09:36:03 +0100518#if defined(MBEDTLS_BLOCK_CIPHER_C)
519 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);
520#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100521 size_t olen = 0;
Valerio Settid0eebc12023-11-20 15:17:53 +0100522 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100523#endif
524 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100525 mbedtls_platform_zeroize(ectr, 16);
526 return ret;
527 }
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100528
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
530 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
531 }
532 mbedtls_xor(output, ectr + offset, input, use_len);
533 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
534 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
535 }
Dave Rodgmand22fb732022-11-22 16:53:25 +0000536
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200538}
539
Gilles Peskine449bd832023-01-11 14:50:10 +0100540int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
541 const unsigned char *input, size_t input_length,
542 unsigned char *output, size_t output_size,
543 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200544{
Janos Follath24eed8d2019-11-22 13:21:35 +0000545 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200546 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200547 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200548 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200550
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 if (output_size < input_length) {
552 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
553 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200554 *output_length = input_length;
555
556 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200557 * on a potentially null pointer.
558 * Returning early also means that the last partial block of AD remains
559 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 if (input_length == 0) {
561 return 0;
562 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200563
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 if (output > input && (size_t) (output - input) < input_length) {
565 return MBEDTLS_ERR_GCM_BAD_INPUT;
566 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200567
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200568 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
569 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 if (ctx->len + input_length < ctx->len ||
571 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
572 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200573 }
574
Gilles Peskine449bd832023-01-11 14:50:10 +0100575 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
576 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200577 }
578
Gilles Peskine58fc2722021-04-13 15:58:27 +0200579 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200581 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200583 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000585
Gilles Peskine449bd832023-01-11 14:50:10 +0100586 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
587 return ret;
588 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000589
Gilles Peskine449bd832023-01-11 14:50:10 +0100590 if (offset + use_len == 16) {
591 gcm_mult(ctx, ctx->buf, ctx->buf);
592 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200593
Gilles Peskine58fc2722021-04-13 15:58:27 +0200594 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200595 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000596 p += use_len;
597 out_p += use_len;
598 }
599
Gilles Peskinea56c4482021-04-15 17:22:35 +0200600 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200601
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 while (input_length >= 16) {
603 gcm_incr(ctx->y);
604 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
605 return ret;
606 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200607
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200609
Gilles Peskinea56c4482021-04-15 17:22:35 +0200610 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200611 p += 16;
612 out_p += 16;
613 }
614
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 if (input_length > 0) {
616 gcm_incr(ctx->y);
617 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
618 return ret;
619 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200620 }
621
Gilles Peskine449bd832023-01-11 14:50:10 +0100622 mbedtls_platform_zeroize(ectr, sizeof(ectr));
623 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200624}
625
Gilles Peskine449bd832023-01-11 14:50:10 +0100626int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
627 unsigned char *output, size_t output_size,
628 size_t *output_length,
629 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200630{
631 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100632 uint64_t orig_len;
633 uint64_t orig_add_len;
634
Gilles Peskine9461e452021-04-15 16:48:32 +0200635 /* We never pass any output in finish(). The output parameter exists only
636 * for the sake of alternative implementations. */
637 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200638 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200639 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200640
Chien Wong858bc652024-01-22 20:47:26 +0800641 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
642 * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
643 * the two multiplications would overflow. */
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100644 orig_len = ctx->len * 8;
645 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200646
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
648 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200649 }
650
Gilles Peskine449bd832023-01-11 14:50:10 +0100651 if (tag_len > 16 || tag_len < 4) {
652 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000653 }
654
Gilles Peskine449bd832023-01-11 14:50:10 +0100655 if (ctx->len % 16 != 0) {
656 gcm_mult(ctx, ctx->buf, ctx->buf);
657 }
658
659 memcpy(tag, ctx->base_ectr, tag_len);
660
661 if (orig_len || orig_add_len) {
662 memset(work_buf, 0x00, 16);
663
664 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
665 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
666 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
667 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
668
669 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
670
671 gcm_mult(ctx, ctx->buf, ctx->buf);
672
673 mbedtls_xor(tag, tag, ctx->buf, tag_len);
674 }
675
676 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000677}
678
Gilles Peskine449bd832023-01-11 14:50:10 +0100679int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
680 int mode,
681 size_t length,
682 const unsigned char *iv,
683 size_t iv_len,
684 const unsigned char *add,
685 size_t add_len,
686 const unsigned char *input,
687 unsigned char *output,
688 size_t tag_len,
689 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200690{
Janos Follath24eed8d2019-11-22 13:21:35 +0000691 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200692 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200693
Gilles Peskine449bd832023-01-11 14:50:10 +0100694 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
695 return ret;
696 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200697
Gilles Peskine449bd832023-01-11 14:50:10 +0100698 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
699 return ret;
700 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200701
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 if ((ret = mbedtls_gcm_update(ctx, input, length,
703 output, length, &olen)) != 0) {
704 return ret;
705 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200706
Gilles Peskine449bd832023-01-11 14:50:10 +0100707 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
708 return ret;
709 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200710
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200712}
713
Gilles Peskine449bd832023-01-11 14:50:10 +0100714int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
715 size_t length,
716 const unsigned char *iv,
717 size_t iv_len,
718 const unsigned char *add,
719 size_t add_len,
720 const unsigned char *tag,
721 size_t tag_len,
722 const unsigned char *input,
723 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000724{
Janos Follath24eed8d2019-11-22 13:21:35 +0000725 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200727 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000728
Gilles Peskine449bd832023-01-11 14:50:10 +0100729 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
730 iv, iv_len, add, add_len,
731 input, output, tag_len, check_tag)) != 0) {
732 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100733 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000734
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200735 /* Check tag in "constant-time" */
Dave Rodgmand26a3d62023-09-11 18:25:16 +0100736 diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
Paul Bakker89e80c92012-03-20 13:50:09 +0000737
Gilles Peskine449bd832023-01-11 14:50:10 +0100738 if (diff != 0) {
739 mbedtls_platform_zeroize(output, length);
740 return MBEDTLS_ERR_GCM_AUTH_FAILED;
741 }
742
743 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000744}
745
Gilles Peskine449bd832023-01-11 14:50:10 +0100746void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200747{
Gilles Peskine449bd832023-01-11 14:50:10 +0100748 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100749 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100750 }
Valerio Settibd7528a2023-12-14 09:36:03 +0100751#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100752 mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
Valerio Settibd7528a2023-12-14 09:36:03 +0100753#else
754 mbedtls_cipher_free(&ctx->cipher_ctx);
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100755#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100756 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200757}
758
Jaeden Amero15263302017-09-21 12:53:48 +0100759#endif /* !MBEDTLS_GCM_ALT */
760
Valerio Setti689c0f72023-12-20 09:53:39 +0100761#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
Paul Bakker89e80c92012-03-20 13:50:09 +0000762/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200763 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000764 *
765 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
766 */
767#define MAX_TESTS 6
768
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100769static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100770{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000771
Yanray Wang93533b52023-05-11 16:45:59 +0800772static const unsigned char key_test_data[][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000773{
774 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
778 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
779 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
780 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200781 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000782};
783
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100784static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100785{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000786
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100787static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100788{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000789
Yanray Wang93533b52023-05-11 16:45:59 +0800790static const unsigned char iv_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000791{
792 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x00 },
794 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
795 0xde, 0xca, 0xf8, 0x88 },
796 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200797 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000798 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200799 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000800 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200801 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000802 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200803 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000804};
805
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100806static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100807{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000808
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100809static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100810{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000811
Yanray Wang93533b52023-05-11 16:45:59 +0800812static const unsigned char additional_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000813{
814 { 0x00 },
815 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200816 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000817 0xab, 0xad, 0xda, 0xd2 },
818};
819
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100820static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100821{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000822
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100823static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100824{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000825
Yanray Wang93533b52023-05-11 16:45:59 +0800826static const unsigned char pt_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000827{
828 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
830 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
831 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
832 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
833 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
834 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
835 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
836 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
837 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
838};
839
Yanray Wangd329c692023-05-11 16:40:57 +0800840static const unsigned char ct_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000841{
842 { 0x00 },
843 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
844 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
845 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200846 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000847 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200848 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000849 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200850 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000851 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
852 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
853 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200854 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000855 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200856 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000857 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200858 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000859 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
860 0x3d, 0x58, 0xe0, 0x91 },
861 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200862 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000863 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200864 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000865 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200866 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000867 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
868 0xc2, 0x3f, 0x45, 0x98 },
869 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200870 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000871 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200872 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000873 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200874 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000875 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
876 0x4c, 0x34, 0xae, 0xe5 },
Yanray Wangd329c692023-05-11 16:40:57 +0800877#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000878 { 0x00 },
879 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200880 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000881 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200882 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000883 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200884 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000885 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200886 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000887 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
888 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
889 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200890 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000891 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200892 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
893 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
894 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000895 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200896 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000897 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200898 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000899 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200900 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000901 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200902 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000903 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200904 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000905 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200906 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000907 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200908 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000909 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200910 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000911 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200912 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000913 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200914 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
915 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
916 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
917 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
918 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
919 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
920 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
921 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
922 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
923 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
924 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
925 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
926 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
927 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
928 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
929 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
930 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
931 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000932 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200933 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000934 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200935 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000936 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200937 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000938 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200939 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000940 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200941 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000942 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200943 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000944 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200945 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000946 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200947 0x44, 0xae, 0x7e, 0x3f },
Yanray Wangd329c692023-05-11 16:40:57 +0800948#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000949};
950
Yanray Wangd329c692023-05-11 16:40:57 +0800951static const unsigned char tag_test_data[][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000952{
953 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
954 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
955 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
956 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
957 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200958 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000959 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
960 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
961 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
962 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
963 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
964 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
Yanray Wangd329c692023-05-11 16:40:57 +0800965#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000966 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
967 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
968 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200969 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000970 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
971 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
972 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200973 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000974 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200975 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000976 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200977 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000978 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200979 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000980 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200981 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000982 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200983 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000984 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200985 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000986 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200987 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000988 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200989 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Yanray Wangd329c692023-05-11 16:40:57 +0800990#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000991};
992
Gilles Peskine449bd832023-01-11 14:50:10 +0100993int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000994{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200995 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000996 unsigned char buf[64];
997 unsigned char tag_buf[16];
998 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200999 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001000 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +00001001
Gilles Peskine0cd9ab72023-03-16 13:06:14 +01001002 if (verbose != 0) {
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001003#if defined(MBEDTLS_GCM_ALT)
1004 mbedtls_printf(" GCM note: alternative implementation.\n");
1005#else /* MBEDTLS_GCM_ALT */
1006#if defined(MBEDTLS_AESNI_HAVE_CODE)
1007 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
1008 mbedtls_printf(" GCM note: using AESNI.\n");
1009 } else
1010#endif
Jerry Yu2f26a592023-03-31 15:06:33 +08001011
Jerry Yu72fd0bd2023-08-18 16:31:01 +08001012#if defined(MBEDTLS_AESCE_HAVE_CODE)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +01001013 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yu2f26a592023-03-31 15:06:33 +08001014 mbedtls_printf(" GCM note: using AESCE.\n");
1015 } else
1016#endif
1017
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001018 mbedtls_printf(" GCM note: built-in implementation.\n");
1019#endif /* MBEDTLS_GCM_ALT */
1020 }
1021
Yanray Wangd329c692023-05-11 16:40:57 +08001022 static const int loop_limit =
1023 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
1024
1025 for (j = 0; j < loop_limit; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +00001026 int key_len = 128 + 64 * j;
1027
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 for (i = 0; i < MAX_TESTS; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001029 if (verbose != 0) {
1030 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1031 key_len, i, "enc");
1032 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001033
Arto Kinnunen0f066182023-04-20 10:02:46 +08001034 mbedtls_gcm_init(&ctx);
1035
Gilles Peskine449bd832023-01-11 14:50:10 +01001036 ret = mbedtls_gcm_setkey(&ctx, cipher,
1037 key_test_data[key_index_test_data[i]],
1038 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +01001039 /*
1040 * AES-192 is an optional feature that may be unavailable when
1041 * there is an alternative underlying implementation i.e. when
1042 * MBEDTLS_AES_ALT is defined.
1043 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001044 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
1045 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001046 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001047 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001048 goto exit;
1049 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001050
Gilles Peskine449bd832023-01-11 14:50:10 +01001051 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
1052 pt_len_test_data[i],
1053 iv_test_data[iv_index_test_data[i]],
1054 iv_len_test_data[i],
1055 additional_test_data[add_index_test_data[i]],
1056 add_len_test_data[i],
1057 pt_test_data[pt_index_test_data[i]],
1058 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +01001059#if defined(MBEDTLS_GCM_ALT)
1060 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001061 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
1062 iv_len_test_data[i] != 12) {
1063 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +01001064 break;
1065 }
1066#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +01001067 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001068 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001069 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001070
Gilles Peskine449bd832023-01-11 14:50:10 +01001071 if (memcmp(buf, ct_test_data[j * 6 + i],
1072 pt_len_test_data[i]) != 0 ||
1073 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001074 ret = 1;
1075 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +00001076 }
1077
Gilles Peskine449bd832023-01-11 14:50:10 +01001078 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001079
Gilles Peskine449bd832023-01-11 14:50:10 +01001080 if (verbose != 0) {
1081 mbedtls_printf("passed\n");
1082 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001083
Gilles Peskine449bd832023-01-11 14:50:10 +01001084 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001085
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 if (verbose != 0) {
1087 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1088 key_len, i, "dec");
1089 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001090
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 ret = mbedtls_gcm_setkey(&ctx, cipher,
1092 key_test_data[key_index_test_data[i]],
1093 key_len);
1094 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001095 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001096 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001097
Gilles Peskine449bd832023-01-11 14:50:10 +01001098 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
1099 pt_len_test_data[i],
1100 iv_test_data[iv_index_test_data[i]],
1101 iv_len_test_data[i],
1102 additional_test_data[add_index_test_data[i]],
1103 add_len_test_data[i],
1104 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +00001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001107 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001109
Gilles Peskine449bd832023-01-11 14:50:10 +01001110 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1111 pt_len_test_data[i]) != 0 ||
1112 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001113 ret = 1;
1114 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +00001115 }
1116
Gilles Peskine449bd832023-01-11 14:50:10 +01001117 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001118
Gilles Peskine449bd832023-01-11 14:50:10 +01001119 if (verbose != 0) {
1120 mbedtls_printf("passed\n");
1121 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001122
Gilles Peskine449bd832023-01-11 14:50:10 +01001123 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001124
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 if (verbose != 0) {
1126 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1127 key_len, i, "enc");
1128 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001129
Gilles Peskine449bd832023-01-11 14:50:10 +01001130 ret = mbedtls_gcm_setkey(&ctx, cipher,
1131 key_test_data[key_index_test_data[i]],
1132 key_len);
1133 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001134 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001135 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001136
Gilles Peskine449bd832023-01-11 14:50:10 +01001137 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1138 iv_test_data[iv_index_test_data[i]],
1139 iv_len_test_data[i]);
1140 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001141 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001142 }
Gilles Peskine295fc132021-04-15 18:32:23 +02001143
Gilles Peskine449bd832023-01-11 14:50:10 +01001144 ret = mbedtls_gcm_update_ad(&ctx,
1145 additional_test_data[add_index_test_data[i]],
1146 add_len_test_data[i]);
1147 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001148 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001149 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001150
Gilles Peskine449bd832023-01-11 14:50:10 +01001151 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001152 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001153 ret = mbedtls_gcm_update(&ctx,
1154 pt_test_data[pt_index_test_data[i]],
1155 32,
1156 buf, sizeof(buf), &olen);
1157 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001158 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001159 }
1160 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001161 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001162 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001163
Gilles Peskine449bd832023-01-11 14:50:10 +01001164 ret = mbedtls_gcm_update(&ctx,
1165 pt_test_data[pt_index_test_data[i]] + 32,
1166 rest_len,
1167 buf + 32, sizeof(buf) - 32, &olen);
1168 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001169 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 }
1171 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001172 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001173 }
1174 } else {
1175 ret = mbedtls_gcm_update(&ctx,
1176 pt_test_data[pt_index_test_data[i]],
1177 pt_len_test_data[i],
1178 buf, sizeof(buf), &olen);
1179 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001180 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001181 }
1182 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001183 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001184 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001185 }
1186
Gilles Peskine449bd832023-01-11 14:50:10 +01001187 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1188 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001189 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001190 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001191
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 if (memcmp(buf, ct_test_data[j * 6 + i],
1193 pt_len_test_data[i]) != 0 ||
1194 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001195 ret = 1;
1196 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001197 }
1198
Gilles Peskine449bd832023-01-11 14:50:10 +01001199 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001200
Gilles Peskine449bd832023-01-11 14:50:10 +01001201 if (verbose != 0) {
1202 mbedtls_printf("passed\n");
1203 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001204
Gilles Peskine449bd832023-01-11 14:50:10 +01001205 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001206
Gilles Peskine449bd832023-01-11 14:50:10 +01001207 if (verbose != 0) {
1208 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1209 key_len, i, "dec");
1210 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001211
Gilles Peskine449bd832023-01-11 14:50:10 +01001212 ret = mbedtls_gcm_setkey(&ctx, cipher,
1213 key_test_data[key_index_test_data[i]],
1214 key_len);
1215 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001216 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001217 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001218
Gilles Peskine449bd832023-01-11 14:50:10 +01001219 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1220 iv_test_data[iv_index_test_data[i]],
1221 iv_len_test_data[i]);
1222 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001223 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001224 }
1225 ret = mbedtls_gcm_update_ad(&ctx,
1226 additional_test_data[add_index_test_data[i]],
1227 add_len_test_data[i]);
1228 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001229 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001230 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001231
Gilles Peskine449bd832023-01-11 14:50:10 +01001232 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001233 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001234 ret = mbedtls_gcm_update(&ctx,
1235 ct_test_data[j * 6 + i], 32,
1236 buf, sizeof(buf), &olen);
1237 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001238 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001239 }
1240 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001241 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001242 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001243
Gilles Peskine449bd832023-01-11 14:50:10 +01001244 ret = mbedtls_gcm_update(&ctx,
1245 ct_test_data[j * 6 + i] + 32,
1246 rest_len,
1247 buf + 32, sizeof(buf) - 32, &olen);
1248 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001249 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001250 }
1251 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001252 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001253 }
1254 } else {
1255 ret = mbedtls_gcm_update(&ctx,
1256 ct_test_data[j * 6 + i],
1257 pt_len_test_data[i],
1258 buf, sizeof(buf), &olen);
1259 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001260 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001261 }
1262 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001263 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001264 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001265 }
1266
Gilles Peskine449bd832023-01-11 14:50:10 +01001267 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1268 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001269 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001270 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001271
Gilles Peskine449bd832023-01-11 14:50:10 +01001272 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1273 pt_len_test_data[i]) != 0 ||
1274 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001275 ret = 1;
1276 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001277 }
1278
Gilles Peskine449bd832023-01-11 14:50:10 +01001279 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001280
Gilles Peskine449bd832023-01-11 14:50:10 +01001281 if (verbose != 0) {
1282 mbedtls_printf("passed\n");
1283 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001284 }
1285 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001286
Gilles Peskine449bd832023-01-11 14:50:10 +01001287 if (verbose != 0) {
1288 mbedtls_printf("\n");
1289 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001290
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001291 ret = 0;
1292
1293exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001294 if (ret != 0) {
1295 if (verbose != 0) {
1296 mbedtls_printf("failed\n");
1297 }
1298 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001299 }
1300
Gilles Peskine449bd832023-01-11 14:50:10 +01001301 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001302}
1303
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001304#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306#endif /* MBEDTLS_GCM_C */