blob: 5994cf6e057c56ea9687d31fe5a0c336b96ae483 [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)) {
763 mbedtls_printf(" GCM note: using AESNI.\n");
764 } else
765#endif
766 mbedtls_printf(" GCM note: built-in implementation.\n");
767#endif /* MBEDTLS_GCM_ALT */
768 }
769
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100770 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000771 int key_len = 128 + 64 * j;
772
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100773 for (i = 0; i < MAX_TESTS; i++) {
774 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100775
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100776 if (verbose != 0) {
777 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
778 key_len, i, "enc");
779 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200780
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100781 ret = mbedtls_gcm_setkey(&ctx, cipher,
782 key_test_data[key_index_test_data[i]],
783 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100784 /*
785 * AES-192 is an optional feature that may be unavailable when
786 * there is an alternative underlying implementation i.e. when
787 * MBEDTLS_AES_ALT is defined.
788 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100789 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
790 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100791 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100792 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100793 goto exit;
794 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000795
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100796 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
797 pt_len_test_data[i],
798 iv_test_data[iv_index_test_data[i]],
799 iv_len_test_data[i],
800 additional_test_data[add_index_test_data[i]],
801 add_len_test_data[i],
802 pt_test_data[pt_index_test_data[i]],
803 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100804#if defined(MBEDTLS_GCM_ALT)
805 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100806 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
807 iv_len_test_data[i] != 12) {
808 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100809 break;
810 }
811#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100812 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100813 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100814 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000815
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100816 if (memcmp(buf, ct_test_data[j * 6 + i],
817 pt_len_test_data[i]) != 0 ||
818 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100819 ret = 1;
820 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000821 }
822
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100823 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200824
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100825 if (verbose != 0) {
826 mbedtls_printf("passed\n");
827 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000828
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100829 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100830
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100831 if (verbose != 0) {
832 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
833 key_len, i, "dec");
834 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200835
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100836 ret = mbedtls_gcm_setkey(&ctx, cipher,
837 key_test_data[key_index_test_data[i]],
838 key_len);
839 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100840 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100841 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000842
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100843 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
844 pt_len_test_data[i],
845 iv_test_data[iv_index_test_data[i]],
846 iv_len_test_data[i],
847 additional_test_data[add_index_test_data[i]],
848 add_len_test_data[i],
849 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000850
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100851 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100852 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100853 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100854
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100855 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
856 pt_len_test_data[i]) != 0 ||
857 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100858 ret = 1;
859 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000860 }
861
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100862 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200863
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100864 if (verbose != 0) {
865 mbedtls_printf("passed\n");
866 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200867
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100868 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100869
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100870 if (verbose != 0) {
871 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
872 key_len, i, "enc");
873 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200874
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100875 ret = mbedtls_gcm_setkey(&ctx, cipher,
876 key_test_data[key_index_test_data[i]],
877 key_len);
878 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100879 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100880 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200881
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100882 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
883 iv_test_data[iv_index_test_data[i]],
884 iv_len_test_data[i],
885 additional_test_data[add_index_test_data[i]],
886 add_len_test_data[i]);
887 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100888 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100889 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200890
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100891 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100892 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100893 ret = mbedtls_gcm_update(&ctx, 32,
894 pt_test_data[pt_index_test_data[i]],
895 buf);
896 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100897 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100898 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200899
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100900 ret = mbedtls_gcm_update(&ctx, rest_len,
901 pt_test_data[pt_index_test_data[i]] + 32,
902 buf + 32);
903 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100904 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100905 }
906 } else {
907 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
908 pt_test_data[pt_index_test_data[i]],
909 buf);
910 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100911 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100912 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200913 }
914
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100915 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
916 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100917 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100918 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100919
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100920 if (memcmp(buf, ct_test_data[j * 6 + i],
921 pt_len_test_data[i]) != 0 ||
922 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100923 ret = 1;
924 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200925 }
926
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100927 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200928
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100929 if (verbose != 0) {
930 mbedtls_printf("passed\n");
931 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200932
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100933 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100934
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100935 if (verbose != 0) {
936 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
937 key_len, i, "dec");
938 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200939
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100940 ret = mbedtls_gcm_setkey(&ctx, cipher,
941 key_test_data[key_index_test_data[i]],
942 key_len);
943 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100944 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100945 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200946
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100947 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
948 iv_test_data[iv_index_test_data[i]],
949 iv_len_test_data[i],
950 additional_test_data[add_index_test_data[i]],
951 add_len_test_data[i]);
952 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100953 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100954 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200955
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100956 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100957 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100958 ret = mbedtls_gcm_update(&ctx, 32, ct_test_data[j * 6 + i],
959 buf);
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 ret = mbedtls_gcm_update(&ctx, rest_len,
965 ct_test_data[j * 6 + i] + 32,
966 buf + 32);
967 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100968 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100969 }
970 } else {
971 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
972 ct_test_data[j * 6 + i],
973 buf);
974 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100975 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100976 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200977 }
978
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100979 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
980 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100981 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100982 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100983
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100984 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
985 pt_len_test_data[i]) != 0 ||
986 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100987 ret = 1;
988 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200989 }
990
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100991 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200992
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100993 if (verbose != 0) {
994 mbedtls_printf("passed\n");
995 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000996 }
997 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200998
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100999 if (verbose != 0) {
1000 mbedtls_printf("\n");
1001 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001002
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001003 ret = 0;
1004
1005exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001006 if (ret != 0) {
1007 if (verbose != 0) {
1008 mbedtls_printf("failed\n");
1009 }
1010 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001011 }
1012
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001013 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001014}
1015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018#endif /* MBEDTLS_GCM_C */