blob: 0c958c729ad902c17a3245c8006dcf0678452817 [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
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker89e80c92012-03-20 13:50:09 +000018 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010019
Paul Bakker89e80c92012-03-20 13:50:09 +000020/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010021 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
22 *
23 * See also:
24 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
25 *
26 * We use the algorithm described as Shoup's method with 4-bit tables in
27 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000028 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010029
Gilles Peskinedb09ef62020-06-03 01:43:33 +020030#include "common.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/gcm.h"
Gilles Peskine7705a462022-09-15 20:14:22 +020035#include "mbedtls/platform.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050036#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000037#include "mbedtls/error.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_AESNI_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000042#include "mbedtls/aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010043#endif
44
Jaeden Amero15263302017-09-21 12:53:48 +010045#if !defined(MBEDTLS_GCM_ALT)
46
k-stachowiak8ffc92a2018-12-12 14:21:59 +010047/* Parameter validation macros */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010048#define GCM_VALIDATE_RET(cond) \
49 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_GCM_BAD_INPUT)
50#define GCM_VALIDATE(cond) \
51 MBEDTLS_INTERNAL_VALIDATE(cond)
k-stachowiak8ffc92a2018-12-12 14:21:59 +010052
Paul Bakker89e80c92012-03-20 13:50:09 +000053/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020054 * Initialize a context
55 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010056void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020057{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010058 GCM_VALIDATE(ctx != NULL);
59 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020060}
61
62/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010063 * Precompute small multiples of H, that is set
64 * HH[i] || HL[i] = H times i,
65 * where i is seen as a field element as in [MGV], ie high-order bits
66 * correspond to low powers of P. The result is stored in the same way, that
67 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
68 * corresponds to P^127.
69 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010070static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000071{
Paul Bakker43aff2a2013-09-09 00:10:27 +020072 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000073 uint64_t hi, lo;
74 uint64_t vl, vh;
75 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020076 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020077
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078 memset(h, 0, 16);
79 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
80 return ret;
81 }
Paul Bakker89e80c92012-03-20 13:50:09 +000082
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010083 /* pack h as two 64-bits ints, big-endian */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010084 hi = MBEDTLS_GET_UINT32_BE(h, 0);
85 lo = MBEDTLS_GET_UINT32_BE(h, 4);
Paul Bakker89e80c92012-03-20 13:50:09 +000086 vh = (uint64_t) hi << 32 | lo;
87
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010088 hi = MBEDTLS_GET_UINT32_BE(h, 8);
89 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +000090 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020091
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010092 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000093 ctx->HL[8] = vl;
94 ctx->HH[8] = vh;
95
Gilles Peskine5511a342023-03-10 22:29:32 +010096#if defined(MBEDTLS_AESNI_HAVE_CODE)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010097 /* With CLMUL support, we need only h, not the rest of the table */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010098 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
99 return 0;
100 }
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100101#endif
102
103 /* 0 corresponds to 0 in GF(2^128) */
104 ctx->HH[0] = 0;
105 ctx->HL[0] = 0;
106
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100107 for (i = 4; i > 0; i >>= 1) {
108 uint32_t T = (vl & 1) * 0xe1000000U;
109 vl = (vh << 63) | (vl >> 1);
110 vh = (vh >> 1) ^ ((uint64_t) T << 32);
Paul Bakker89e80c92012-03-20 13:50:09 +0000111
112 ctx->HL[i] = vl;
113 ctx->HH[i] = vh;
114 }
115
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100116 for (i = 2; i <= 8; i *= 2) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000117 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
118 vh = *HiH;
119 vl = *HiL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100120 for (j = 1; j < i; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000121 HiH[j] = vh ^ ctx->HH[j];
122 HiL[j] = vl ^ ctx->HL[j];
123 }
124 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200125
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100126 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000127}
128
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100129int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
130 mbedtls_cipher_id_t cipher,
131 const unsigned char *key,
132 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000133{
Janos Follath24eed8d2019-11-22 13:21:35 +0000134 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000136
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100137 GCM_VALIDATE_RET(ctx != NULL);
138 GCM_VALIDATE_RET(key != NULL);
139 GCM_VALIDATE_RET(keybits == 128 || keybits == 192 || keybits == 256);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100140
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100141 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
142 MBEDTLS_MODE_ECB);
143 if (cipher_info == NULL) {
144 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200145 }
146
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100147 if (cipher_info->block_size != 16) {
148 return MBEDTLS_ERR_GCM_BAD_INPUT;
149 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000150
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 mbedtls_cipher_free(&ctx->cipher_ctx);
152
153 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
154 return ret;
155 }
156
157 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
158 MBEDTLS_ENCRYPT)) != 0) {
159 return ret;
160 }
161
162 if ((ret = gcm_gen_table(ctx)) != 0) {
163 return ret;
164 }
165
166 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000167}
168
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100169/*
170 * Shoup's method for multiplication use this table with
171 * last4[x] = x times P^128
172 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
173 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000174static const uint64_t last4[16] =
175{
176 0x0000, 0x1c20, 0x3840, 0x2460,
177 0x7080, 0x6ca0, 0x48c0, 0x54e0,
178 0xe100, 0xfd20, 0xd940, 0xc560,
179 0x9180, 0x8da0, 0xa9c0, 0xb5e0
180};
181
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100182/*
183 * Sets output to x times H using the precomputed tables.
184 * x and output are seen as elements of GF(2^128) as in [MGV].
185 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100186static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
187 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000188{
189 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000190 unsigned char lo, hi, rem;
191 uint64_t zh, zl;
192
Gilles Peskine5511a342023-03-10 22:29:32 +0100193#if defined(MBEDTLS_AESNI_HAVE_CODE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100195 unsigned char h[16];
196
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100197 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
198 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
199 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
200 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100201
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100202 mbedtls_aesni_gcm_mult(output, x, h);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100203 return;
204 }
Gilles Peskine5511a342023-03-10 22:29:32 +0100205#endif /* MBEDTLS_AESNI_HAVE_CODE */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100206
Paul Bakker89e80c92012-03-20 13:50:09 +0000207 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000208
209 zh = ctx->HH[lo];
210 zl = ctx->HL[lo];
211
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100212 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000213 lo = x[i] & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100214 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000215
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100216 if (i != 15) {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000217 rem = (unsigned char) zl & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100218 zl = (zh << 60) | (zl >> 4);
219 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000220 zh ^= (uint64_t) last4[rem] << 48;
221 zh ^= ctx->HH[lo];
222 zl ^= ctx->HL[lo];
223
224 }
225
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000226 rem = (unsigned char) zl & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100227 zl = (zh << 60) | (zl >> 4);
228 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000229 zh ^= (uint64_t) last4[rem] << 48;
230 zh ^= ctx->HH[hi];
231 zl ^= ctx->HL[hi];
232 }
233
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234 MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
235 MBEDTLS_PUT_UINT32_BE(zh, output, 4);
236 MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
237 MBEDTLS_PUT_UINT32_BE(zl, output, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000238}
239
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100240int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
241 int mode,
242 const unsigned char *iv,
243 size_t iv_len,
244 const unsigned char *add,
245 size_t add_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000246{
Janos Follath24eed8d2019-11-22 13:21:35 +0000247 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000248 unsigned char work_buf[16];
249 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000250 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200251 size_t use_len, olen = 0;
openluopworld5d5f5202021-11-05 00:13:43 +0800252 uint64_t iv_bits;
Paul Bakker89e80c92012-03-20 13:50:09 +0000253
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100254 GCM_VALIDATE_RET(ctx != NULL);
255 GCM_VALIDATE_RET(iv != NULL);
256 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100257
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200258 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200259 /* IV is not allowed to be zero length */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100260 if (iv_len == 0 ||
261 ((uint64_t) iv_len) >> 61 != 0 ||
262 ((uint64_t) add_len) >> 61 != 0) {
263 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200264 }
265
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266 memset(ctx->y, 0x00, sizeof(ctx->y));
267 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200268
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200269 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200270 ctx->len = 0;
271 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000272
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100273 if (iv_len == 12) {
274 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200275 ctx->y[15] = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100276 } else {
277 memset(work_buf, 0x00, 16);
278 iv_bits = (uint64_t) iv_len * 8;
279 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000280
281 p = iv;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100282 while (iv_len > 0) {
283 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000284
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100285 for (i = 0; i < use_len; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200286 ctx->y[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100287 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200288
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100289 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000290
291 iv_len -= use_len;
292 p += use_len;
293 }
294
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100295 for (i = 0; i < 16; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200296 ctx->y[i] ^= work_buf[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000298
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100299 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000300 }
301
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100302 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
303 ctx->base_ectr, &olen)) != 0) {
304 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200305 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000306
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200307 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000308 p = add;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309 while (add_len > 0) {
310 use_len = (add_len < 16) ? add_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000311
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100312 for (i = 0; i < use_len; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200313 ctx->buf[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100314 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200315
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100316 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000317
318 add_len -= use_len;
319 p += use_len;
320 }
321
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100322 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200323}
324
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100325int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
326 size_t length,
327 const unsigned char *input,
328 unsigned char *output)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200329{
Janos Follath24eed8d2019-11-22 13:21:35 +0000330 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200331 unsigned char ectr[16];
332 size_t i;
333 const unsigned char *p;
334 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200335 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200336
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100337 GCM_VALIDATE_RET(ctx != NULL);
338 GCM_VALIDATE_RET(length == 0 || input != NULL);
339 GCM_VALIDATE_RET(length == 0 || output != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100340
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100341 if (output > input && (size_t) (output - input) < length) {
342 return MBEDTLS_ERR_GCM_BAD_INPUT;
343 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200344
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200345 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
346 * Also check for possible overflow */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347 if (ctx->len + length < ctx->len ||
348 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull) {
349 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200350 }
351
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200352 ctx->len += length;
353
Paul Bakker89e80c92012-03-20 13:50:09 +0000354 p = input;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100355 while (length > 0) {
356 use_len = (length < 16) ? length : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000357
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100358 for (i = 16; i > 12; i--) {
359 if (++ctx->y[i - 1] != 0) {
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000360 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100361 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200362 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000363
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100364 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
365 &olen)) != 0) {
366 return ret;
367 }
368
369 for (i = 0; i < use_len; i++) {
370 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200371 ctx->buf[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100372 }
Paul Bakker67f9d532012-10-23 11:49:05 +0000373 out_p[i] = ectr[i] ^ p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100374 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200375 ctx->buf[i] ^= out_p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100376 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000377 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200378
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100379 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker169b7f42013-06-25 14:58:00 +0200380
Paul Bakker89e80c92012-03-20 13:50:09 +0000381 length -= use_len;
382 p += use_len;
383 out_p += use_len;
384 }
385
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100386 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200387}
388
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100389int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
390 unsigned char *tag,
391 size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200392{
393 unsigned char work_buf[16];
394 size_t i;
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100395 uint64_t orig_len;
396 uint64_t orig_add_len;
397
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100398 GCM_VALIDATE_RET(ctx != NULL);
399 GCM_VALIDATE_RET(tag != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100400
401 orig_len = ctx->len * 8;
402 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200403
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100404 if (tag_len > 16 || tag_len < 4) {
405 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000406 }
407
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100408 memcpy(tag, ctx->base_ectr, tag_len);
409
410 if (orig_len || orig_add_len) {
411 memset(work_buf, 0x00, 16);
412
413 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
414 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
415 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
416 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
417
418 for (i = 0; i < 16; i++) {
419 ctx->buf[i] ^= work_buf[i];
420 }
421
422 gcm_mult(ctx, ctx->buf, ctx->buf);
423
424 for (i = 0; i < tag_len; i++) {
425 tag[i] ^= ctx->buf[i];
426 }
427 }
428
429 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000430}
431
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100432int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
433 int mode,
434 size_t length,
435 const unsigned char *iv,
436 size_t iv_len,
437 const unsigned char *add,
438 size_t add_len,
439 const unsigned char *input,
440 unsigned char *output,
441 size_t tag_len,
442 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200443{
Janos Follath24eed8d2019-11-22 13:21:35 +0000444 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200445
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100446 GCM_VALIDATE_RET(ctx != NULL);
447 GCM_VALIDATE_RET(iv != NULL);
448 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
449 GCM_VALIDATE_RET(length == 0 || input != NULL);
450 GCM_VALIDATE_RET(length == 0 || output != NULL);
451 GCM_VALIDATE_RET(tag != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100452
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100453 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len, add, add_len)) != 0) {
454 return ret;
455 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200456
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100457 if ((ret = mbedtls_gcm_update(ctx, length, input, output)) != 0) {
458 return ret;
459 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200460
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100461 if ((ret = mbedtls_gcm_finish(ctx, tag, tag_len)) != 0) {
462 return ret;
463 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200464
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100465 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200466}
467
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100468int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
469 size_t length,
470 const unsigned char *iv,
471 size_t iv_len,
472 const unsigned char *add,
473 size_t add_len,
474 const unsigned char *tag,
475 size_t tag_len,
476 const unsigned char *input,
477 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000478{
Janos Follath24eed8d2019-11-22 13:21:35 +0000479 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000480 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200481 size_t i;
482 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000483
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100484 GCM_VALIDATE_RET(ctx != NULL);
485 GCM_VALIDATE_RET(iv != NULL);
486 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
487 GCM_VALIDATE_RET(tag != NULL);
488 GCM_VALIDATE_RET(length == 0 || input != NULL);
489 GCM_VALIDATE_RET(length == 0 || output != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100490
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100491 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
492 iv, iv_len, add, add_len,
493 input, output, tag_len, check_tag)) != 0) {
494 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100495 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000496
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200497 /* Check tag in "constant-time" */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100498 for (diff = 0, i = 0; i < tag_len; i++) {
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200499 diff |= tag[i] ^ check_tag[i];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200500 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000501
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100502 if (diff != 0) {
503 mbedtls_platform_zeroize(output, length);
504 return MBEDTLS_ERR_GCM_AUTH_FAILED;
505 }
506
507 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000508}
509
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100510void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200511{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100512 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100513 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100514 }
515 mbedtls_cipher_free(&ctx->cipher_ctx);
516 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200517}
518
Jaeden Amero15263302017-09-21 12:53:48 +0100519#endif /* !MBEDTLS_GCM_ALT */
520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000522/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200523 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000524 *
525 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
526 */
527#define MAX_TESTS 6
528
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100529static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100530{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000531
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100532static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000533{
534 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
538 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
539 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
540 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200541 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000542};
543
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100544static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100545{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000546
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100547static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100548{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000549
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100550static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000551{
552 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00 },
554 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
555 0xde, 0xca, 0xf8, 0x88 },
556 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200557 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000558 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200559 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000560 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200561 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000562 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200563 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000564};
565
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100566static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100567{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000568
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100569static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100570{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000571
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100572static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000573{
574 { 0x00 },
575 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200576 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000577 0xab, 0xad, 0xda, 0xd2 },
578};
579
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100580static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100581{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000582
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100583static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100584{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000585
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100586static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000587{
588 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
590 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
591 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
592 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
593 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
594 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
595 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
596 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
597 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
598};
599
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100600static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000601{
602 { 0x00 },
603 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
604 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
605 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200610 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
612 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
613 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200614 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000615 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200618 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000619 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
620 0x3d, 0x58, 0xe0, 0x91 },
621 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200622 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000623 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200624 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000625 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200626 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000627 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
628 0xc2, 0x3f, 0x45, 0x98 },
629 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200630 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000631 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200632 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000633 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200634 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000635 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
636 0x4c, 0x34, 0xae, 0xe5 },
637 { 0x00 },
638 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200639 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000640 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200641 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
647 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
648 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
652 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
653 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000664 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200665 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000666 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200667 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000668 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200669 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000670 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200671 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000672 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200673 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
674 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
675 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
676 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
677 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
678 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
679 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
680 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
681 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
682 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
683 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
684 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
685 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
686 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
687 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
688 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
689 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
690 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200694 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000695 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200696 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000697 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200698 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000699 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200700 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000701 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200702 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000703 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200704 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000705 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200706 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000707};
708
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100709static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000710{
711 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
712 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
713 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
714 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
715 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
718 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
719 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
720 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
721 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
722 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
723 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
724 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
725 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
728 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
729 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000735 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200736 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000737 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000739 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200740 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000741 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200742 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000743 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200744 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000745 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200746 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000747};
748
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100749int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000750{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000752 unsigned char buf[64];
753 unsigned char tag_buf[16];
754 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000756
Gilles Peskinede345782023-03-16 13:06:14 +0100757 if (verbose != 0) {
Gilles Peskine2c8ad942023-03-10 22:35:24 +0100758#if defined(MBEDTLS_GCM_ALT)
759 mbedtls_printf(" GCM note: alternative implementation.\n");
760#else /* MBEDTLS_GCM_ALT */
761#if defined(MBEDTLS_AESNI_HAVE_CODE)
762 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Tom Cosgrove640b7612023-03-19 15:07:06 +0000763 mbedtls_printf(" GCM note: using AESNI via ");
764#if MBEDTLS_AESNI_HAVE_CODE == 1
765 mbedtls_printf("assembly");
766#elif MBEDTLS_AESNI_HAVE_CODE == 2
767 mbedtls_printf("intrinsics");
768#else
769 mbedtls_printf("(unknown)");
770#endif
771 mbedtls_printf(".\n");
Gilles Peskine2c8ad942023-03-10 22:35:24 +0100772 } else
773#endif
774 mbedtls_printf(" GCM note: built-in implementation.\n");
775#endif /* MBEDTLS_GCM_ALT */
776 }
777
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100778 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000779 int key_len = 128 + 64 * j;
780
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100781 for (i = 0; i < MAX_TESTS; i++) {
782 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100783
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100784 if (verbose != 0) {
785 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
786 key_len, i, "enc");
787 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200788
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100789 ret = mbedtls_gcm_setkey(&ctx, cipher,
790 key_test_data[key_index_test_data[i]],
791 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100792 /*
793 * AES-192 is an optional feature that may be unavailable when
794 * there is an alternative underlying implementation i.e. when
795 * MBEDTLS_AES_ALT is defined.
796 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100797 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
798 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100799 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100800 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100801 goto exit;
802 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000803
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100804 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
805 pt_len_test_data[i],
806 iv_test_data[iv_index_test_data[i]],
807 iv_len_test_data[i],
808 additional_test_data[add_index_test_data[i]],
809 add_len_test_data[i],
810 pt_test_data[pt_index_test_data[i]],
811 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100812#if defined(MBEDTLS_GCM_ALT)
813 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100814 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
815 iv_len_test_data[i] != 12) {
816 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100817 break;
818 }
819#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100820 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100821 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100822 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000823
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100824 if (memcmp(buf, ct_test_data[j * 6 + i],
825 pt_len_test_data[i]) != 0 ||
826 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100827 ret = 1;
828 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000829 }
830
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100831 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200832
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100833 if (verbose != 0) {
834 mbedtls_printf("passed\n");
835 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000836
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100837 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100838
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100839 if (verbose != 0) {
840 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
841 key_len, i, "dec");
842 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200843
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100844 ret = mbedtls_gcm_setkey(&ctx, cipher,
845 key_test_data[key_index_test_data[i]],
846 key_len);
847 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100848 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100849 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000850
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100851 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
852 pt_len_test_data[i],
853 iv_test_data[iv_index_test_data[i]],
854 iv_len_test_data[i],
855 additional_test_data[add_index_test_data[i]],
856 add_len_test_data[i],
857 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000858
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100859 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100860 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100861 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100862
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100863 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
864 pt_len_test_data[i]) != 0 ||
865 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100866 ret = 1;
867 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000868 }
869
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100870 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200871
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100872 if (verbose != 0) {
873 mbedtls_printf("passed\n");
874 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200875
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100876 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100877
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100878 if (verbose != 0) {
879 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
880 key_len, i, "enc");
881 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200882
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100883 ret = mbedtls_gcm_setkey(&ctx, cipher,
884 key_test_data[key_index_test_data[i]],
885 key_len);
886 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100887 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100888 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200889
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100890 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
891 iv_test_data[iv_index_test_data[i]],
892 iv_len_test_data[i],
893 additional_test_data[add_index_test_data[i]],
894 add_len_test_data[i]);
895 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100896 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100897 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200898
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100899 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100900 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100901 ret = mbedtls_gcm_update(&ctx, 32,
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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100908 ret = mbedtls_gcm_update(&ctx, rest_len,
909 pt_test_data[pt_index_test_data[i]] + 32,
910 buf + 32);
911 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100912 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100913 }
914 } else {
915 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
916 pt_test_data[pt_index_test_data[i]],
917 buf);
918 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100919 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100920 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200921 }
922
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100923 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
924 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100925 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100926 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100927
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100928 if (memcmp(buf, ct_test_data[j * 6 + i],
929 pt_len_test_data[i]) != 0 ||
930 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100931 ret = 1;
932 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200933 }
934
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100935 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200936
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100937 if (verbose != 0) {
938 mbedtls_printf("passed\n");
939 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200940
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100941 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100942
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100943 if (verbose != 0) {
944 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
945 key_len, i, "dec");
946 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200947
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100948 ret = mbedtls_gcm_setkey(&ctx, cipher,
949 key_test_data[key_index_test_data[i]],
950 key_len);
951 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100952 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100953 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200954
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100955 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
956 iv_test_data[iv_index_test_data[i]],
957 iv_len_test_data[i],
958 additional_test_data[add_index_test_data[i]],
959 add_len_test_data[i]);
960 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100961 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100962 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200963
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100964 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100965 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100966 ret = mbedtls_gcm_update(&ctx, 32, 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100972 ret = mbedtls_gcm_update(&ctx, rest_len,
973 ct_test_data[j * 6 + i] + 32,
974 buf + 32);
975 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100976 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100977 }
978 } else {
979 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
980 ct_test_data[j * 6 + i],
981 buf);
982 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100983 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100984 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200985 }
986
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100987 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
988 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100989 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100990 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100991
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100992 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
993 pt_len_test_data[i]) != 0 ||
994 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100995 ret = 1;
996 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200997 }
998
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100999 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001000
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001001 if (verbose != 0) {
1002 mbedtls_printf("passed\n");
1003 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001004 }
1005 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001006
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001007 if (verbose != 0) {
1008 mbedtls_printf("\n");
1009 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001010
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001011 ret = 0;
1012
1013exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001014 if (ret != 0) {
1015 if (verbose != 0) {
1016 mbedtls_printf("failed\n");
1017 }
1018 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001019 }
1020
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001021 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001022}
1023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026#endif /* MBEDTLS_GCM_C */