blob: 5dfac2349c82cbf1d3789370d332a79b50d3a549 [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{
Matthias Schulza6ac0f12024-02-09 17:09:42 +010060#if defined(MBEDTLS_GCM_LARGE_TABLE)
Matthias Schulz0767fda2024-02-07 10:46:28 +010061 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 Schulza6ac0f12024-02-09 17:09:42 +0100141#if !defined(MBEDTLS_GCM_LARGE_TABLE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100142 /* 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 Schulza6ac0f12024-02-09 17:09:42 +0100215#if defined(MBEDTLS_GCM_LARGE_TABLE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100216static 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 Schulza6ac0f12024-02-09 17:09:42 +0100363#if defined(MBEDTLS_GCM_LARGE_TABLE)
Matthias Schulz0767fda2024-02-07 10:46:28 +0100364 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
Dave Rodgman386c39f2024-03-13 09:39:53 +0000415#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
Dave Rodgman4faa34d2024-03-12 16:34:43 +0000416#pragma GCC diagnostic push
417#pragma GCC diagnostic warning "-Wstringop-overflow=0"
418#endif
419
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200421
Dave Rodgman386c39f2024-03-13 09:39:53 +0000422#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
Dave Rodgman4faa34d2024-03-12 16:34:43 +0000423#pragma GCC diagnostic pop
424#endif
425
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000427
428 iv_len -= use_len;
429 p += use_len;
430 }
431
Gilles Peskine449bd832023-01-11 14:50:10 +0100432 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000433
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000435 }
436
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100437
Valerio Settibd7528a2023-12-14 09:36:03 +0100438#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Settid0eebc12023-11-20 15:17:53 +0100439 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr);
Valerio Settibd7528a2023-12-14 09:36:03 +0100440#else
441 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100442#endif
443 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100444 return ret;
445 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000446
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200448}
449
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200450/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200451 * mbedtls_gcm_context::buf contains the partial state of the computation of
452 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200453 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
454 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200455 * * len == 0 && add_len == 0: initial state
456 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
457 * a partial block of AD that has been
458 * xored in but not yet multiplied in.
459 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
460 * the data ends now.
461 * * len % 16 != 0: the first `len % 16` bytes have
462 * a partial block of ciphertext that has
463 * been xored in but not yet multiplied in.
464 * * len > 0 && len % 16 == 0: the authentication tag is correct if
465 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200466 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100467int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
468 const unsigned char *add, size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200469{
470 const unsigned char *p;
Dave Rodgmand22fb732022-11-22 16:53:25 +0000471 size_t use_len, offset;
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800472 uint64_t new_add_len;
Gilles Peskine295fc132021-04-15 18:32:23 +0200473
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800474 /* AD is limited to 2^64 bits, ie 2^61 bytes
475 * Also check for possible overflow */
Chien Wong019c2a72024-01-23 21:38:06 +0800476#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
477 if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
478 return MBEDTLS_ERR_GCM_BAD_INPUT;
479 }
480#endif
481 new_add_len = ctx->add_len + (uint64_t) add_len;
Chien Wongbf4b5ed2024-01-22 20:43:54 +0800482 if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 return MBEDTLS_ERR_GCM_BAD_INPUT;
484 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200485
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200486 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000487 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200488
Gilles Peskine449bd832023-01-11 14:50:10 +0100489 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200490 use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200492 use_len = add_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200494
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200496
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 if (offset + use_len == 16) {
498 gcm_mult(ctx, ctx->buf, ctx->buf);
499 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200500
501 ctx->add_len += use_len;
502 add_len -= use_len;
503 p += use_len;
504 }
505
506 ctx->add_len += add_len;
507
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 while (add_len >= 16) {
509 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200510
Gilles Peskine449bd832023-01-11 14:50:10 +0100511 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000512
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200513 add_len -= 16;
514 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000515 }
516
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 if (add_len > 0) {
518 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200519 }
520
Gilles Peskine449bd832023-01-11 14:50:10 +0100521 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200522}
523
Gilles Peskine58fc2722021-04-13 15:58:27 +0200524/* Increment the counter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100525static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200526{
Dave Rodgman46697da2024-01-14 12:59:49 +0000527 uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);
528 x++;
529 MBEDTLS_PUT_UINT32_BE(x, y, 12);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200530}
531
532/* Calculate and apply the encryption mask. Process use_len bytes of data,
533 * starting at position offset in the mask block. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100534static int gcm_mask(mbedtls_gcm_context *ctx,
535 unsigned char ectr[16],
536 size_t offset, size_t use_len,
537 const unsigned char *input,
538 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200539{
Gilles Peskine58fc2722021-04-13 15:58:27 +0200540 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Valerio Settid0eebc12023-11-20 15:17:53 +0100541
Valerio Settibd7528a2023-12-14 09:36:03 +0100542#if defined(MBEDTLS_BLOCK_CIPHER_C)
543 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);
544#else
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100545 size_t olen = 0;
Valerio Settid0eebc12023-11-20 15:17:53 +0100546 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);
Valerio Settid0eebc12023-11-20 15:17:53 +0100547#endif
548 if (ret != 0) {
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100549 mbedtls_platform_zeroize(ectr, 16);
550 return ret;
551 }
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100552
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
554 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
555 }
556 mbedtls_xor(output, ectr + offset, input, use_len);
557 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
558 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
559 }
Dave Rodgmand22fb732022-11-22 16:53:25 +0000560
Gilles Peskine449bd832023-01-11 14:50:10 +0100561 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200562}
563
Gilles Peskine449bd832023-01-11 14:50:10 +0100564int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
565 const unsigned char *input, size_t input_length,
566 unsigned char *output, size_t output_size,
567 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200568{
Janos Follath24eed8d2019-11-22 13:21:35 +0000569 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200570 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200571 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200572 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100573 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200574
Gilles Peskine449bd832023-01-11 14:50:10 +0100575 if (output_size < input_length) {
576 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
577 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200578 *output_length = input_length;
579
580 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200581 * on a potentially null pointer.
582 * Returning early also means that the last partial block of AD remains
583 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 if (input_length == 0) {
585 return 0;
586 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 if (output > input && (size_t) (output - input) < input_length) {
589 return MBEDTLS_ERR_GCM_BAD_INPUT;
590 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200591
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200592 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
593 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100594 if (ctx->len + input_length < ctx->len ||
595 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
596 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200597 }
598
Gilles Peskine449bd832023-01-11 14:50:10 +0100599 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
600 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200601 }
602
Gilles Peskine58fc2722021-04-13 15:58:27 +0200603 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100604 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200605 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200607 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000609
Gilles Peskine449bd832023-01-11 14:50:10 +0100610 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
611 return ret;
612 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000613
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 if (offset + use_len == 16) {
615 gcm_mult(ctx, ctx->buf, ctx->buf);
616 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200617
Gilles Peskine58fc2722021-04-13 15:58:27 +0200618 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200619 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000620 p += use_len;
621 out_p += use_len;
622 }
623
Gilles Peskinea56c4482021-04-15 17:22:35 +0200624 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200625
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 while (input_length >= 16) {
627 gcm_incr(ctx->y);
628 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
629 return ret;
630 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200631
Gilles Peskine449bd832023-01-11 14:50:10 +0100632 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200633
Gilles Peskinea56c4482021-04-15 17:22:35 +0200634 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200635 p += 16;
636 out_p += 16;
637 }
638
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 if (input_length > 0) {
640 gcm_incr(ctx->y);
641 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
642 return ret;
643 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200644 }
645
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 mbedtls_platform_zeroize(ectr, sizeof(ectr));
647 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200648}
649
Gilles Peskine449bd832023-01-11 14:50:10 +0100650int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
651 unsigned char *output, size_t output_size,
652 size_t *output_length,
653 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200654{
655 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100656 uint64_t orig_len;
657 uint64_t orig_add_len;
658
Gilles Peskine9461e452021-04-15 16:48:32 +0200659 /* We never pass any output in finish(). The output parameter exists only
660 * for the sake of alternative implementations. */
661 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200662 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200663 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200664
Chien Wong858bc652024-01-22 20:47:26 +0800665 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
666 * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
667 * the two multiplications would overflow. */
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100668 orig_len = ctx->len * 8;
669 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200670
Gilles Peskine449bd832023-01-11 14:50:10 +0100671 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
672 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200673 }
674
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 if (tag_len > 16 || tag_len < 4) {
676 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000677 }
678
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 if (ctx->len % 16 != 0) {
680 gcm_mult(ctx, ctx->buf, ctx->buf);
681 }
682
683 memcpy(tag, ctx->base_ectr, tag_len);
684
685 if (orig_len || orig_add_len) {
686 memset(work_buf, 0x00, 16);
687
688 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
689 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
690 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
691 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
692
693 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
694
695 gcm_mult(ctx, ctx->buf, ctx->buf);
696
697 mbedtls_xor(tag, tag, ctx->buf, tag_len);
698 }
699
700 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000701}
702
Gilles Peskine449bd832023-01-11 14:50:10 +0100703int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
704 int mode,
705 size_t length,
706 const unsigned char *iv,
707 size_t iv_len,
708 const unsigned char *add,
709 size_t add_len,
710 const unsigned char *input,
711 unsigned char *output,
712 size_t tag_len,
713 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200714{
Janos Follath24eed8d2019-11-22 13:21:35 +0000715 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200716 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200717
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
719 return ret;
720 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200721
Gilles Peskine449bd832023-01-11 14:50:10 +0100722 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
723 return ret;
724 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200725
Gilles Peskine449bd832023-01-11 14:50:10 +0100726 if ((ret = mbedtls_gcm_update(ctx, input, length,
727 output, length, &olen)) != 0) {
728 return ret;
729 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200730
Gilles Peskine449bd832023-01-11 14:50:10 +0100731 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
732 return ret;
733 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200734
Gilles Peskine449bd832023-01-11 14:50:10 +0100735 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200736}
737
Gilles Peskine449bd832023-01-11 14:50:10 +0100738int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
739 size_t length,
740 const unsigned char *iv,
741 size_t iv_len,
742 const unsigned char *add,
743 size_t add_len,
744 const unsigned char *tag,
745 size_t tag_len,
746 const unsigned char *input,
747 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000748{
Janos Follath24eed8d2019-11-22 13:21:35 +0000749 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000750 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200751 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000752
Gilles Peskine449bd832023-01-11 14:50:10 +0100753 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
754 iv, iv_len, add, add_len,
755 input, output, tag_len, check_tag)) != 0) {
756 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100757 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000758
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200759 /* Check tag in "constant-time" */
Dave Rodgmand26a3d62023-09-11 18:25:16 +0100760 diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
Paul Bakker89e80c92012-03-20 13:50:09 +0000761
Gilles Peskine449bd832023-01-11 14:50:10 +0100762 if (diff != 0) {
763 mbedtls_platform_zeroize(output, length);
764 return MBEDTLS_ERR_GCM_AUTH_FAILED;
765 }
766
767 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000768}
769
Gilles Peskine449bd832023-01-11 14:50:10 +0100770void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200771{
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100773 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100774 }
Valerio Settibd7528a2023-12-14 09:36:03 +0100775#if defined(MBEDTLS_BLOCK_CIPHER_C)
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100776 mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
Valerio Settibd7528a2023-12-14 09:36:03 +0100777#else
778 mbedtls_cipher_free(&ctx->cipher_ctx);
Valerio Setti9b7a8b22023-11-16 08:24:51 +0100779#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100780 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200781}
782
Jaeden Amero15263302017-09-21 12:53:48 +0100783#endif /* !MBEDTLS_GCM_ALT */
784
Valerio Setti689c0f72023-12-20 09:53:39 +0100785#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
Paul Bakker89e80c92012-03-20 13:50:09 +0000786/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200787 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000788 *
789 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
790 */
791#define MAX_TESTS 6
792
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100793static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100794{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000795
Yanray Wang93533b52023-05-11 16:45:59 +0800796static const unsigned char key_test_data[][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000797{
798 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
800 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
802 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
803 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
804 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200805 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000806};
807
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100808static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100809{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000810
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100811static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100812{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000813
Yanray Wang93533b52023-05-11 16:45:59 +0800814static const unsigned char iv_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000815{
816 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 0x00, 0x00, 0x00, 0x00 },
818 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
819 0xde, 0xca, 0xf8, 0x88 },
820 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200821 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000822 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200823 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000824 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200825 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000826 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200827 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000828};
829
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100830static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100831{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000832
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100833static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100834{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000835
Yanray Wang93533b52023-05-11 16:45:59 +0800836static const unsigned char additional_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000837{
838 { 0x00 },
839 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200840 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000841 0xab, 0xad, 0xda, 0xd2 },
842};
843
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100844static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100845{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000846
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100847static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100848{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000849
Yanray Wang93533b52023-05-11 16:45:59 +0800850static const unsigned char pt_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000851{
852 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
854 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
855 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
856 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
857 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
858 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
859 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
860 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
861 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
862};
863
Yanray Wangd329c692023-05-11 16:40:57 +0800864static const unsigned char ct_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000865{
866 { 0x00 },
867 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
868 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
869 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200870 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000871 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200872 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000873 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200874 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000875 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
876 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
877 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200878 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000879 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200880 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000881 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200882 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000883 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
884 0x3d, 0x58, 0xe0, 0x91 },
885 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200886 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000887 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200888 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000889 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200890 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000891 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
892 0xc2, 0x3f, 0x45, 0x98 },
893 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200894 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000895 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200896 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000897 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200898 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000899 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
900 0x4c, 0x34, 0xae, 0xe5 },
Yanray Wangd329c692023-05-11 16:40:57 +0800901#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000902 { 0x00 },
903 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200904 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000905 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200906 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000907 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200908 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000909 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200910 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000911 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
912 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
913 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200914 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000915 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200916 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
917 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
918 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000919 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200920 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000921 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200922 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000923 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200924 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000925 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200926 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000927 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200928 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000929 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200930 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000931 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200932 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000933 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200934 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000935 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200936 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000937 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200938 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
939 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
940 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
941 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
942 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
943 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
944 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
945 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
946 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
947 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
948 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
949 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
950 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
951 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
952 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
953 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
954 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
955 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000956 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200957 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000958 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200959 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000960 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200961 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000962 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200963 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000964 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200965 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000966 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200967 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000968 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200969 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000970 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200971 0x44, 0xae, 0x7e, 0x3f },
Yanray Wangd329c692023-05-11 16:40:57 +0800972#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000973};
974
Yanray Wangd329c692023-05-11 16:40:57 +0800975static const unsigned char tag_test_data[][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000976{
977 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
978 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
979 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
980 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
981 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200982 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000983 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
984 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
985 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
986 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
987 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
988 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
Yanray Wangd329c692023-05-11 16:40:57 +0800989#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000990 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
991 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
992 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200993 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000994 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
995 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
996 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200997 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000998 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200999 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +00001000 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +02001001 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +00001002 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +02001003 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +00001004 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +02001005 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +00001006 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +02001007 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +00001008 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +02001009 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +00001010 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +02001011 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +00001012 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +02001013 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Yanray Wangd329c692023-05-11 16:40:57 +08001014#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +00001015};
1016
Gilles Peskine449bd832023-01-11 14:50:10 +01001017int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +00001018{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +00001020 unsigned char buf[64];
1021 unsigned char tag_buf[16];
1022 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001024 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +00001025
Gilles Peskine0cd9ab72023-03-16 13:06:14 +01001026 if (verbose != 0) {
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001027#if defined(MBEDTLS_GCM_ALT)
1028 mbedtls_printf(" GCM note: alternative implementation.\n");
1029#else /* MBEDTLS_GCM_ALT */
1030#if defined(MBEDTLS_AESNI_HAVE_CODE)
1031 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
1032 mbedtls_printf(" GCM note: using AESNI.\n");
1033 } else
1034#endif
Jerry Yu2f26a592023-03-31 15:06:33 +08001035
Jerry Yu72fd0bd2023-08-18 16:31:01 +08001036#if defined(MBEDTLS_AESCE_HAVE_CODE)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +01001037 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yu2f26a592023-03-31 15:06:33 +08001038 mbedtls_printf(" GCM note: using AESCE.\n");
1039 } else
1040#endif
1041
Gilles Peskine7e67bd52023-03-10 22:35:24 +01001042 mbedtls_printf(" GCM note: built-in implementation.\n");
1043#endif /* MBEDTLS_GCM_ALT */
1044 }
1045
Yanray Wangd329c692023-05-11 16:40:57 +08001046 static const int loop_limit =
1047 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
1048
1049 for (j = 0; j < loop_limit; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +00001050 int key_len = 128 + 64 * j;
1051
Gilles Peskine449bd832023-01-11 14:50:10 +01001052 for (i = 0; i < MAX_TESTS; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001053 if (verbose != 0) {
1054 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1055 key_len, i, "enc");
1056 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001057
Arto Kinnunen0f066182023-04-20 10:02:46 +08001058 mbedtls_gcm_init(&ctx);
1059
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 ret = mbedtls_gcm_setkey(&ctx, cipher,
1061 key_test_data[key_index_test_data[i]],
1062 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +01001063 /*
1064 * AES-192 is an optional feature that may be unavailable when
1065 * there is an alternative underlying implementation i.e. when
1066 * MBEDTLS_AES_ALT is defined.
1067 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001068 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
1069 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001070 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001071 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001072 goto exit;
1073 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001074
Gilles Peskine449bd832023-01-11 14:50:10 +01001075 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
1076 pt_len_test_data[i],
1077 iv_test_data[iv_index_test_data[i]],
1078 iv_len_test_data[i],
1079 additional_test_data[add_index_test_data[i]],
1080 add_len_test_data[i],
1081 pt_test_data[pt_index_test_data[i]],
1082 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +01001083#if defined(MBEDTLS_GCM_ALT)
1084 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001085 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
1086 iv_len_test_data[i] != 12) {
1087 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +01001088 break;
1089 }
1090#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001092 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001093 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001094
Gilles Peskine449bd832023-01-11 14:50:10 +01001095 if (memcmp(buf, ct_test_data[j * 6 + i],
1096 pt_len_test_data[i]) != 0 ||
1097 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001098 ret = 1;
1099 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +00001100 }
1101
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001103
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 if (verbose != 0) {
1105 mbedtls_printf("passed\n");
1106 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001107
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001109
Gilles Peskine449bd832023-01-11 14:50:10 +01001110 if (verbose != 0) {
1111 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1112 key_len, i, "dec");
1113 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001114
Gilles Peskine449bd832023-01-11 14:50:10 +01001115 ret = mbedtls_gcm_setkey(&ctx, cipher,
1116 key_test_data[key_index_test_data[i]],
1117 key_len);
1118 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001119 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001120 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001121
Gilles Peskine449bd832023-01-11 14:50:10 +01001122 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
1123 pt_len_test_data[i],
1124 iv_test_data[iv_index_test_data[i]],
1125 iv_len_test_data[i],
1126 additional_test_data[add_index_test_data[i]],
1127 add_len_test_data[i],
1128 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +00001129
Gilles Peskine449bd832023-01-11 14:50:10 +01001130 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001131 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001132 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1135 pt_len_test_data[i]) != 0 ||
1136 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001137 ret = 1;
1138 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +00001139 }
1140
Gilles Peskine449bd832023-01-11 14:50:10 +01001141 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001142
Gilles Peskine449bd832023-01-11 14:50:10 +01001143 if (verbose != 0) {
1144 mbedtls_printf("passed\n");
1145 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001146
Gilles Peskine449bd832023-01-11 14:50:10 +01001147 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001148
Gilles Peskine449bd832023-01-11 14:50:10 +01001149 if (verbose != 0) {
1150 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1151 key_len, i, "enc");
1152 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001153
Gilles Peskine449bd832023-01-11 14:50:10 +01001154 ret = mbedtls_gcm_setkey(&ctx, cipher,
1155 key_test_data[key_index_test_data[i]],
1156 key_len);
1157 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001158 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001159 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001160
Gilles Peskine449bd832023-01-11 14:50:10 +01001161 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1162 iv_test_data[iv_index_test_data[i]],
1163 iv_len_test_data[i]);
1164 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001165 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001166 }
Gilles Peskine295fc132021-04-15 18:32:23 +02001167
Gilles Peskine449bd832023-01-11 14:50:10 +01001168 ret = mbedtls_gcm_update_ad(&ctx,
1169 additional_test_data[add_index_test_data[i]],
1170 add_len_test_data[i]);
1171 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001172 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001173 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001174
Gilles Peskine449bd832023-01-11 14:50:10 +01001175 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001176 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001177 ret = mbedtls_gcm_update(&ctx,
1178 pt_test_data[pt_index_test_data[i]],
1179 32,
1180 buf, sizeof(buf), &olen);
1181 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001182 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001183 }
1184 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001185 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001186 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001187
Gilles Peskine449bd832023-01-11 14:50:10 +01001188 ret = mbedtls_gcm_update(&ctx,
1189 pt_test_data[pt_index_test_data[i]] + 32,
1190 rest_len,
1191 buf + 32, sizeof(buf) - 32, &olen);
1192 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001193 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001194 }
1195 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001196 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001197 }
1198 } else {
1199 ret = mbedtls_gcm_update(&ctx,
1200 pt_test_data[pt_index_test_data[i]],
1201 pt_len_test_data[i],
1202 buf, sizeof(buf), &olen);
1203 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001204 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001205 }
1206 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001207 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001208 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001209 }
1210
Gilles Peskine449bd832023-01-11 14:50:10 +01001211 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1212 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001213 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001214 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001215
Gilles Peskine449bd832023-01-11 14:50:10 +01001216 if (memcmp(buf, ct_test_data[j * 6 + i],
1217 pt_len_test_data[i]) != 0 ||
1218 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001219 ret = 1;
1220 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001221 }
1222
Gilles Peskine449bd832023-01-11 14:50:10 +01001223 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001224
Gilles Peskine449bd832023-01-11 14:50:10 +01001225 if (verbose != 0) {
1226 mbedtls_printf("passed\n");
1227 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001228
Gilles Peskine449bd832023-01-11 14:50:10 +01001229 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001230
Gilles Peskine449bd832023-01-11 14:50:10 +01001231 if (verbose != 0) {
1232 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1233 key_len, i, "dec");
1234 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001235
Gilles Peskine449bd832023-01-11 14:50:10 +01001236 ret = mbedtls_gcm_setkey(&ctx, cipher,
1237 key_test_data[key_index_test_data[i]],
1238 key_len);
1239 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001240 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001241 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001242
Gilles Peskine449bd832023-01-11 14:50:10 +01001243 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1244 iv_test_data[iv_index_test_data[i]],
1245 iv_len_test_data[i]);
1246 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001247 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001248 }
1249 ret = mbedtls_gcm_update_ad(&ctx,
1250 additional_test_data[add_index_test_data[i]],
1251 add_len_test_data[i]);
1252 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001253 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001254 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001255
Gilles Peskine449bd832023-01-11 14:50:10 +01001256 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001257 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001258 ret = mbedtls_gcm_update(&ctx,
1259 ct_test_data[j * 6 + i], 32,
1260 buf, sizeof(buf), &olen);
1261 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001262 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001263 }
1264 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001265 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001266 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001267
Gilles Peskine449bd832023-01-11 14:50:10 +01001268 ret = mbedtls_gcm_update(&ctx,
1269 ct_test_data[j * 6 + i] + 32,
1270 rest_len,
1271 buf + 32, sizeof(buf) - 32, &olen);
1272 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001273 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001274 }
1275 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001276 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001277 }
1278 } else {
1279 ret = mbedtls_gcm_update(&ctx,
1280 ct_test_data[j * 6 + i],
1281 pt_len_test_data[i],
1282 buf, sizeof(buf), &olen);
1283 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001284 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001285 }
1286 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001287 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001288 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001289 }
1290
Gilles Peskine449bd832023-01-11 14:50:10 +01001291 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1292 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001293 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001294 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001295
Gilles Peskine449bd832023-01-11 14:50:10 +01001296 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1297 pt_len_test_data[i]) != 0 ||
1298 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001299 ret = 1;
1300 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001301 }
1302
Gilles Peskine449bd832023-01-11 14:50:10 +01001303 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001304
Gilles Peskine449bd832023-01-11 14:50:10 +01001305 if (verbose != 0) {
1306 mbedtls_printf("passed\n");
1307 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001308 }
1309 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001310
Gilles Peskine449bd832023-01-11 14:50:10 +01001311 if (verbose != 0) {
1312 mbedtls_printf("\n");
1313 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001314
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001315 ret = 0;
1316
1317exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001318 if (ret != 0) {
1319 if (verbose != 0) {
1320 mbedtls_printf("failed\n");
1321 }
1322 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001323 }
1324
Gilles Peskine449bd832023-01-11 14:50:10 +01001325 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001326}
1327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330#endif /* MBEDTLS_GCM_C */