blob: d3e773278fbbde887c576b396b2417791657e8d0 [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 Rodgman7ff79652023-11-03 12:04:52 +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 Peskine7705a462022-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 Rodgmanc2805202023-09-11 18:25:16 +010026#include "mbedtls/constant_time.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000027
Rich Evans00ab4702015-02-06 13:43:58 +000028#include <string.h>
29
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if defined(MBEDTLS_AESNI_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010032#endif
33
Jaeden Amero15263302017-09-21 12:53:48 +010034#if !defined(MBEDTLS_GCM_ALT)
35
k-stachowiak8ffc92a2018-12-12 14:21:59 +010036/* Parameter validation macros */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010037#define GCM_VALIDATE_RET(cond) \
38 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_GCM_BAD_INPUT)
39#define GCM_VALIDATE(cond) \
40 MBEDTLS_INTERNAL_VALIDATE(cond)
k-stachowiak8ffc92a2018-12-12 14:21:59 +010041
Paul Bakker89e80c92012-03-20 13:50:09 +000042/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020043 * Initialize a context
44 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010045void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020046{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010047 GCM_VALIDATE(ctx != NULL);
48 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020049}
50
51/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010052 * Precompute small multiples of H, that is set
53 * HH[i] || HL[i] = H times i,
54 * where i is seen as a field element as in [MGV], ie high-order bits
55 * correspond to low powers of P. The result is stored in the same way, that
56 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
57 * corresponds to P^127.
58 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010059static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000060{
Paul Bakker43aff2a2013-09-09 00:10:27 +020061 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000062 uint64_t hi, lo;
63 uint64_t vl, vh;
64 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020065 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020066
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067 memset(h, 0, 16);
68 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
69 return ret;
70 }
Paul Bakker89e80c92012-03-20 13:50:09 +000071
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010072 /* pack h as two 64-bits ints, big-endian */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010073 hi = MBEDTLS_GET_UINT32_BE(h, 0);
74 lo = MBEDTLS_GET_UINT32_BE(h, 4);
Paul Bakker89e80c92012-03-20 13:50:09 +000075 vh = (uint64_t) hi << 32 | lo;
76
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010077 hi = MBEDTLS_GET_UINT32_BE(h, 8);
78 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +000079 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020080
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010081 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000082 ctx->HL[8] = vl;
83 ctx->HH[8] = vh;
84
Gilles Peskine5511a342023-03-10 22:29:32 +010085#if defined(MBEDTLS_AESNI_HAVE_CODE)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010086 /* With CLMUL support, we need only h, not the rest of the table */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010087 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
88 return 0;
89 }
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010090#endif
91
92 /* 0 corresponds to 0 in GF(2^128) */
93 ctx->HH[0] = 0;
94 ctx->HL[0] = 0;
95
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010096 for (i = 4; i > 0; i >>= 1) {
97 uint32_t T = (vl & 1) * 0xe1000000U;
98 vl = (vh << 63) | (vl >> 1);
99 vh = (vh >> 1) ^ ((uint64_t) T << 32);
Paul Bakker89e80c92012-03-20 13:50:09 +0000100
101 ctx->HL[i] = vl;
102 ctx->HH[i] = vh;
103 }
104
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100105 for (i = 2; i <= 8; i *= 2) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000106 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
107 vh = *HiH;
108 vl = *HiL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100109 for (j = 1; j < i; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000110 HiH[j] = vh ^ ctx->HH[j];
111 HiL[j] = vl ^ ctx->HL[j];
112 }
113 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200114
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000116}
117
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100118int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
119 mbedtls_cipher_id_t cipher,
120 const unsigned char *key,
121 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000122{
Janos Follath24eed8d2019-11-22 13:21:35 +0000123 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000125
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100126 GCM_VALIDATE_RET(ctx != NULL);
127 GCM_VALIDATE_RET(key != NULL);
128 GCM_VALIDATE_RET(keybits == 128 || keybits == 192 || keybits == 256);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100129
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100130 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
131 MBEDTLS_MODE_ECB);
132 if (cipher_info == NULL) {
133 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200134 }
135
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100136 if (cipher_info->block_size != 16) {
137 return MBEDTLS_ERR_GCM_BAD_INPUT;
138 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000139
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140 mbedtls_cipher_free(&ctx->cipher_ctx);
141
142 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
143 return ret;
144 }
145
146 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
147 MBEDTLS_ENCRYPT)) != 0) {
148 return ret;
149 }
150
151 if ((ret = gcm_gen_table(ctx)) != 0) {
152 return ret;
153 }
154
155 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000156}
157
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100158/*
159 * Shoup's method for multiplication use this table with
160 * last4[x] = x times P^128
161 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
162 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000163static const uint64_t last4[16] =
164{
165 0x0000, 0x1c20, 0x3840, 0x2460,
166 0x7080, 0x6ca0, 0x48c0, 0x54e0,
167 0xe100, 0xfd20, 0xd940, 0xc560,
168 0x9180, 0x8da0, 0xa9c0, 0xb5e0
169};
170
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100171/*
172 * Sets output to x times H using the precomputed tables.
173 * x and output are seen as elements of GF(2^128) as in [MGV].
174 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100175static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
176 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000177{
178 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000179 unsigned char lo, hi, rem;
180 uint64_t zh, zl;
181
Gilles Peskine5511a342023-03-10 22:29:32 +0100182#if defined(MBEDTLS_AESNI_HAVE_CODE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100183 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100184 unsigned char h[16];
185
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100186 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
187 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
188 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
189 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100190
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100191 mbedtls_aesni_gcm_mult(output, x, h);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100192 return;
193 }
Gilles Peskine5511a342023-03-10 22:29:32 +0100194#endif /* MBEDTLS_AESNI_HAVE_CODE */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100195
Paul Bakker89e80c92012-03-20 13:50:09 +0000196 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000197
198 zh = ctx->HH[lo];
199 zl = ctx->HL[lo];
200
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100201 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000202 lo = x[i] & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000204
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100205 if (i != 15) {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000206 rem = (unsigned char) zl & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100207 zl = (zh << 60) | (zl >> 4);
208 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000209 zh ^= (uint64_t) last4[rem] << 48;
210 zh ^= ctx->HH[lo];
211 zl ^= ctx->HL[lo];
212
213 }
214
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000215 rem = (unsigned char) zl & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100216 zl = (zh << 60) | (zl >> 4);
217 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000218 zh ^= (uint64_t) last4[rem] << 48;
219 zh ^= ctx->HH[hi];
220 zl ^= ctx->HL[hi];
221 }
222
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100223 MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
224 MBEDTLS_PUT_UINT32_BE(zh, output, 4);
225 MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
226 MBEDTLS_PUT_UINT32_BE(zl, output, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000227}
228
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100229int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
230 int mode,
231 const unsigned char *iv,
232 size_t iv_len,
233 const unsigned char *add,
234 size_t add_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000235{
Janos Follath24eed8d2019-11-22 13:21:35 +0000236 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000237 unsigned char work_buf[16];
238 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000239 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200240 size_t use_len, olen = 0;
openluopworld5d5f5202021-11-05 00:13:43 +0800241 uint64_t iv_bits;
Paul Bakker89e80c92012-03-20 13:50:09 +0000242
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100243 GCM_VALIDATE_RET(ctx != NULL);
David Horstmann90b94ff2024-02-01 19:32:46 +0000244 GCM_VALIDATE_RET(iv_len == 0 || iv != NULL);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100245 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100246
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200247 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200248 /* IV is not allowed to be zero length */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100249 if (iv_len == 0 ||
250 ((uint64_t) iv_len) >> 61 != 0 ||
251 ((uint64_t) add_len) >> 61 != 0) {
252 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200253 }
254
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100255 memset(ctx->y, 0x00, sizeof(ctx->y));
256 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200257
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200258 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200259 ctx->len = 0;
260 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000261
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100262 if (iv_len == 12) {
263 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200264 ctx->y[15] = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100265 } else {
266 memset(work_buf, 0x00, 16);
267 iv_bits = (uint64_t) iv_len * 8;
268 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000269
270 p = iv;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100271 while (iv_len > 0) {
272 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000273
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100274 for (i = 0; i < use_len; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200275 ctx->y[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100276 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200277
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100278 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000279
280 iv_len -= use_len;
281 p += use_len;
282 }
283
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284 for (i = 0; i < 16; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200285 ctx->y[i] ^= work_buf[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000287
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100288 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000289 }
290
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
292 ctx->base_ectr, &olen)) != 0) {
293 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200294 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000295
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200296 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000297 p = add;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100298 while (add_len > 0) {
299 use_len = (add_len < 16) ? add_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000300
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 for (i = 0; i < use_len; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200302 ctx->buf[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100303 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200304
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100305 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000306
307 add_len -= use_len;
308 p += use_len;
309 }
310
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100311 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200312}
313
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100314int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
315 size_t length,
316 const unsigned char *input,
317 unsigned char *output)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200318{
Janos Follath24eed8d2019-11-22 13:21:35 +0000319 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200320 unsigned char ectr[16];
321 size_t i;
322 const unsigned char *p;
323 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200324 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200325
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100326 GCM_VALIDATE_RET(ctx != NULL);
327 GCM_VALIDATE_RET(length == 0 || input != NULL);
328 GCM_VALIDATE_RET(length == 0 || output != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100329
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100330 if (output > input && (size_t) (output - input) < length) {
331 return MBEDTLS_ERR_GCM_BAD_INPUT;
332 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200333
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200334 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
335 * Also check for possible overflow */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100336 if (ctx->len + length < ctx->len ||
337 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull) {
338 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200339 }
340
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200341 ctx->len += length;
342
Paul Bakker89e80c92012-03-20 13:50:09 +0000343 p = input;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344 while (length > 0) {
345 use_len = (length < 16) ? length : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000346
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347 for (i = 16; i > 12; i--) {
348 if (++ctx->y[i - 1] != 0) {
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000349 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100350 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200351 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000352
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100353 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
354 &olen)) != 0) {
355 return ret;
356 }
357
358 for (i = 0; i < use_len; i++) {
359 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200360 ctx->buf[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100361 }
Paul Bakker67f9d532012-10-23 11:49:05 +0000362 out_p[i] = ectr[i] ^ p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100363 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200364 ctx->buf[i] ^= out_p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100365 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000366 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200367
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100368 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker169b7f42013-06-25 14:58:00 +0200369
Paul Bakker89e80c92012-03-20 13:50:09 +0000370 length -= use_len;
371 p += use_len;
372 out_p += use_len;
373 }
374
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100375 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200376}
377
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100378int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
379 unsigned char *tag,
380 size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200381{
382 unsigned char work_buf[16];
383 size_t i;
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100384 uint64_t orig_len;
385 uint64_t orig_add_len;
386
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100387 GCM_VALIDATE_RET(ctx != NULL);
388 GCM_VALIDATE_RET(tag != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100389
390 orig_len = ctx->len * 8;
391 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200392
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100393 if (tag_len > 16 || tag_len < 4) {
394 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000395 }
396
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100397 memcpy(tag, ctx->base_ectr, tag_len);
398
399 if (orig_len || orig_add_len) {
400 memset(work_buf, 0x00, 16);
401
402 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
403 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
404 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
405 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
406
407 for (i = 0; i < 16; i++) {
408 ctx->buf[i] ^= work_buf[i];
409 }
410
411 gcm_mult(ctx, ctx->buf, ctx->buf);
412
413 for (i = 0; i < tag_len; i++) {
414 tag[i] ^= ctx->buf[i];
415 }
416 }
417
418 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000419}
420
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100421int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
422 int mode,
423 size_t length,
424 const unsigned char *iv,
425 size_t iv_len,
426 const unsigned char *add,
427 size_t add_len,
428 const unsigned char *input,
429 unsigned char *output,
430 size_t tag_len,
431 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200432{
Janos Follath24eed8d2019-11-22 13:21:35 +0000433 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200434
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100435 GCM_VALIDATE_RET(ctx != NULL);
David Horstmann90b94ff2024-02-01 19:32:46 +0000436 GCM_VALIDATE_RET(iv_len == 0 || iv != NULL);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
438 GCM_VALIDATE_RET(length == 0 || input != NULL);
439 GCM_VALIDATE_RET(length == 0 || output != NULL);
440 GCM_VALIDATE_RET(tag != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100441
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100442 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len, add, add_len)) != 0) {
443 return ret;
444 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200445
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100446 if ((ret = mbedtls_gcm_update(ctx, length, input, output)) != 0) {
447 return ret;
448 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200449
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100450 if ((ret = mbedtls_gcm_finish(ctx, tag, tag_len)) != 0) {
451 return ret;
452 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200453
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100454 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200455}
456
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100457int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
458 size_t length,
459 const unsigned char *iv,
460 size_t iv_len,
461 const unsigned char *add,
462 size_t add_len,
463 const unsigned char *tag,
464 size_t tag_len,
465 const unsigned char *input,
466 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000467{
Janos Follath24eed8d2019-11-22 13:21:35 +0000468 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000469 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200470 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000471
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100472 GCM_VALIDATE_RET(ctx != NULL);
David Horstmann90b94ff2024-02-01 19:32:46 +0000473 GCM_VALIDATE_RET(iv_len == 0 || iv != NULL);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100474 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
475 GCM_VALIDATE_RET(tag != NULL);
476 GCM_VALIDATE_RET(length == 0 || input != NULL);
477 GCM_VALIDATE_RET(length == 0 || output != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100478
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100479 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
480 iv, iv_len, add, add_len,
481 input, output, tag_len, check_tag)) != 0) {
482 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100483 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000484
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200485 /* Check tag in "constant-time" */
Dave Rodgmanc2805202023-09-11 18:25:16 +0100486 diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
Paul Bakker89e80c92012-03-20 13:50:09 +0000487
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100488 if (diff != 0) {
489 mbedtls_platform_zeroize(output, length);
490 return MBEDTLS_ERR_GCM_AUTH_FAILED;
491 }
492
493 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000494}
495
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100496void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200497{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100498 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100499 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100500 }
501 mbedtls_cipher_free(&ctx->cipher_ctx);
502 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200503}
504
Jaeden Amero15263302017-09-21 12:53:48 +0100505#endif /* !MBEDTLS_GCM_ALT */
506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000508/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200509 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000510 *
511 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
512 */
513#define MAX_TESTS 6
514
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100515static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100516{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000517
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100518static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000519{
520 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
524 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
525 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
526 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200527 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000528};
529
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100530static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100531{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000532
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100533static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100534{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000535
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100536static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000537{
538 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00 },
540 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
541 0xde, 0xca, 0xf8, 0x88 },
542 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200543 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000544 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200545 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000546 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200547 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000548 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200549 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000550};
551
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100552static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100553{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000554
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100555static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100556{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000557
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100558static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000559{
560 { 0x00 },
561 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200562 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000563 0xab, 0xad, 0xda, 0xd2 },
564};
565
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100566static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100567{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000568
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100569static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100570{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000571
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100572static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000573{
574 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
576 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
577 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
578 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
579 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
580 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
581 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
582 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
583 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
584};
585
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100586static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000587{
588 { 0x00 },
589 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
590 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
591 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200592 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000593 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200594 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000595 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200596 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000597 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
598 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
599 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200600 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000601 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200602 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000603 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200604 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000605 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
606 0x3d, 0x58, 0xe0, 0x91 },
607 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200610 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
614 0xc2, 0x3f, 0x45, 0x98 },
615 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200618 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000619 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200620 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000621 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
622 0x4c, 0x34, 0xae, 0xe5 },
623 { 0x00 },
624 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200625 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000626 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200627 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000628 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200629 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000630 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200631 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000632 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
633 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
634 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200635 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000636 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
638 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
639 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000640 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200641 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
660 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
661 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
662 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
663 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
664 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
665 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
666 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
667 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
668 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
669 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
670 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
671 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
672 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
673 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
674 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
675 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
676 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000677 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200678 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000679 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200680 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000681 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200682 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000683 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000693};
694
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100695static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000696{
697 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
698 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
699 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
700 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
701 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200702 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000703 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
704 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
705 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
706 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
707 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
708 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
709 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
710 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
711 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200712 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000713 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
714 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
715 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000733};
734
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100735int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000736{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000738 unsigned char buf[64];
739 unsigned char tag_buf[16];
740 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000742
Gilles Peskinede345782023-03-16 13:06:14 +0100743 if (verbose != 0) {
Gilles Peskine2c8ad942023-03-10 22:35:24 +0100744#if defined(MBEDTLS_GCM_ALT)
745 mbedtls_printf(" GCM note: alternative implementation.\n");
746#else /* MBEDTLS_GCM_ALT */
747#if defined(MBEDTLS_AESNI_HAVE_CODE)
748 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Tom Cosgrove640b7612023-03-19 15:07:06 +0000749 mbedtls_printf(" GCM note: using AESNI via ");
750#if MBEDTLS_AESNI_HAVE_CODE == 1
751 mbedtls_printf("assembly");
752#elif MBEDTLS_AESNI_HAVE_CODE == 2
753 mbedtls_printf("intrinsics");
754#else
755 mbedtls_printf("(unknown)");
756#endif
757 mbedtls_printf(".\n");
Gilles Peskine2c8ad942023-03-10 22:35:24 +0100758 } else
759#endif
760 mbedtls_printf(" GCM note: built-in implementation.\n");
761#endif /* MBEDTLS_GCM_ALT */
762 }
763
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100764 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000765 int key_len = 128 + 64 * j;
766
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100767 for (i = 0; i < MAX_TESTS; i++) {
768 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100769
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100770 if (verbose != 0) {
771 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
772 key_len, i, "enc");
773 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200774
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100775 ret = mbedtls_gcm_setkey(&ctx, cipher,
776 key_test_data[key_index_test_data[i]],
777 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100778 /*
779 * AES-192 is an optional feature that may be unavailable when
780 * there is an alternative underlying implementation i.e. when
781 * MBEDTLS_AES_ALT is defined.
782 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100783 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
784 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100785 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100786 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100787 goto exit;
788 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000789
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100790 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
791 pt_len_test_data[i],
792 iv_test_data[iv_index_test_data[i]],
793 iv_len_test_data[i],
794 additional_test_data[add_index_test_data[i]],
795 add_len_test_data[i],
796 pt_test_data[pt_index_test_data[i]],
797 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100798#if defined(MBEDTLS_GCM_ALT)
799 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100800 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
801 iv_len_test_data[i] != 12) {
802 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100803 break;
804 }
805#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100806 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100807 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100808 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000809
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100810 if (memcmp(buf, ct_test_data[j * 6 + i],
811 pt_len_test_data[i]) != 0 ||
812 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100813 ret = 1;
814 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000815 }
816
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100817 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200818
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100819 if (verbose != 0) {
820 mbedtls_printf("passed\n");
821 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000822
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100823 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100824
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100825 if (verbose != 0) {
826 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
827 key_len, i, "dec");
828 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200829
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100830 ret = mbedtls_gcm_setkey(&ctx, cipher,
831 key_test_data[key_index_test_data[i]],
832 key_len);
833 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100834 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100835 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000836
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100837 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
838 pt_len_test_data[i],
839 iv_test_data[iv_index_test_data[i]],
840 iv_len_test_data[i],
841 additional_test_data[add_index_test_data[i]],
842 add_len_test_data[i],
843 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000844
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100845 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100846 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100847 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100848
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100849 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
850 pt_len_test_data[i]) != 0 ||
851 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100852 ret = 1;
853 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000854 }
855
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100856 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200857
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100858 if (verbose != 0) {
859 mbedtls_printf("passed\n");
860 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200861
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100862 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100863
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100864 if (verbose != 0) {
865 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
866 key_len, i, "enc");
867 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200868
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100869 ret = mbedtls_gcm_setkey(&ctx, cipher,
870 key_test_data[key_index_test_data[i]],
871 key_len);
872 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100873 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100874 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200875
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100876 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
877 iv_test_data[iv_index_test_data[i]],
878 iv_len_test_data[i],
879 additional_test_data[add_index_test_data[i]],
880 add_len_test_data[i]);
881 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100882 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100883 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200884
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100885 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100886 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100887 ret = mbedtls_gcm_update(&ctx, 32,
888 pt_test_data[pt_index_test_data[i]],
889 buf);
890 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100891 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100892 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200893
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100894 ret = mbedtls_gcm_update(&ctx, rest_len,
895 pt_test_data[pt_index_test_data[i]] + 32,
896 buf + 32);
897 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100898 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100899 }
900 } else {
901 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
902 pt_test_data[pt_index_test_data[i]],
903 buf);
904 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100905 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100906 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200907 }
908
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100909 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
910 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100911 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100912 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100913
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100914 if (memcmp(buf, ct_test_data[j * 6 + i],
915 pt_len_test_data[i]) != 0 ||
916 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100917 ret = 1;
918 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200919 }
920
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100921 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200922
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100923 if (verbose != 0) {
924 mbedtls_printf("passed\n");
925 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200926
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100927 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100928
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100929 if (verbose != 0) {
930 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
931 key_len, i, "dec");
932 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200933
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100934 ret = mbedtls_gcm_setkey(&ctx, cipher,
935 key_test_data[key_index_test_data[i]],
936 key_len);
937 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100938 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100939 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200940
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100941 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
942 iv_test_data[iv_index_test_data[i]],
943 iv_len_test_data[i],
944 additional_test_data[add_index_test_data[i]],
945 add_len_test_data[i]);
946 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100947 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100948 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200949
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100950 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100951 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100952 ret = mbedtls_gcm_update(&ctx, 32, ct_test_data[j * 6 + i],
953 buf);
954 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100955 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100956 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200957
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100958 ret = mbedtls_gcm_update(&ctx, rest_len,
959 ct_test_data[j * 6 + i] + 32,
960 buf + 32);
961 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100962 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100963 }
964 } else {
965 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
966 ct_test_data[j * 6 + i],
967 buf);
968 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100969 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100970 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200971 }
972
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100973 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
974 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100975 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100976 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100977
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100978 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
979 pt_len_test_data[i]) != 0 ||
980 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100981 ret = 1;
982 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200983 }
984
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100985 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200986
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100987 if (verbose != 0) {
988 mbedtls_printf("passed\n");
989 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000990 }
991 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200992
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100993 if (verbose != 0) {
994 mbedtls_printf("\n");
995 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000996
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100997 ret = 0;
998
999exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001000 if (ret != 0) {
1001 if (verbose != 0) {
1002 mbedtls_printf("failed\n");
1003 }
1004 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001005 }
1006
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001007 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001008}
1009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001011
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001012#endif /* MBEDTLS_GCM_C */