blob: 463ef48fcf2671d4d450c4cefb13d8e8011c8c07 [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 Peskine2c8ad942023-03-10 22:35:24 +0100757 if (verbose != 0)
758 {
759#if defined(MBEDTLS_GCM_ALT)
760 mbedtls_printf(" GCM note: alternative implementation.\n");
761#else /* MBEDTLS_GCM_ALT */
762#if defined(MBEDTLS_AESNI_HAVE_CODE)
763 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
764 mbedtls_printf(" GCM note: using AESNI.\n");
765 } else
766#endif
767 mbedtls_printf(" GCM note: built-in implementation.\n");
768#endif /* MBEDTLS_GCM_ALT */
769 }
770
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100771 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000772 int key_len = 128 + 64 * j;
773
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100774 for (i = 0; i < MAX_TESTS; i++) {
775 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100776
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100777 if (verbose != 0) {
778 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
779 key_len, i, "enc");
780 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200781
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100782 ret = mbedtls_gcm_setkey(&ctx, cipher,
783 key_test_data[key_index_test_data[i]],
784 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100785 /*
786 * AES-192 is an optional feature that may be unavailable when
787 * there is an alternative underlying implementation i.e. when
788 * MBEDTLS_AES_ALT is defined.
789 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100790 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
791 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100792 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100793 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100794 goto exit;
795 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000796
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100797 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
798 pt_len_test_data[i],
799 iv_test_data[iv_index_test_data[i]],
800 iv_len_test_data[i],
801 additional_test_data[add_index_test_data[i]],
802 add_len_test_data[i],
803 pt_test_data[pt_index_test_data[i]],
804 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100805#if defined(MBEDTLS_GCM_ALT)
806 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100807 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
808 iv_len_test_data[i] != 12) {
809 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100810 break;
811 }
812#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100813 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100814 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100815 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000816
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100817 if (memcmp(buf, ct_test_data[j * 6 + i],
818 pt_len_test_data[i]) != 0 ||
819 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100820 ret = 1;
821 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000822 }
823
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100824 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200825
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100826 if (verbose != 0) {
827 mbedtls_printf("passed\n");
828 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000829
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100830 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100831
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100832 if (verbose != 0) {
833 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
834 key_len, i, "dec");
835 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200836
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100837 ret = mbedtls_gcm_setkey(&ctx, cipher,
838 key_test_data[key_index_test_data[i]],
839 key_len);
840 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100841 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100842 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000843
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100844 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
845 pt_len_test_data[i],
846 iv_test_data[iv_index_test_data[i]],
847 iv_len_test_data[i],
848 additional_test_data[add_index_test_data[i]],
849 add_len_test_data[i],
850 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000851
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100852 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100853 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100854 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100855
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100856 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
857 pt_len_test_data[i]) != 0 ||
858 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100859 ret = 1;
860 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000861 }
862
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100863 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200864
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100865 if (verbose != 0) {
866 mbedtls_printf("passed\n");
867 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200868
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100869 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100870
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100871 if (verbose != 0) {
872 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
873 key_len, i, "enc");
874 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200875
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100876 ret = mbedtls_gcm_setkey(&ctx, cipher,
877 key_test_data[key_index_test_data[i]],
878 key_len);
879 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100880 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100881 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200882
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100883 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
884 iv_test_data[iv_index_test_data[i]],
885 iv_len_test_data[i],
886 additional_test_data[add_index_test_data[i]],
887 add_len_test_data[i]);
888 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100889 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100890 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200891
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100892 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100893 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100894 ret = mbedtls_gcm_update(&ctx, 32,
895 pt_test_data[pt_index_test_data[i]],
896 buf);
897 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100898 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100899 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200900
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100901 ret = mbedtls_gcm_update(&ctx, rest_len,
902 pt_test_data[pt_index_test_data[i]] + 32,
903 buf + 32);
904 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100905 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100906 }
907 } else {
908 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
909 pt_test_data[pt_index_test_data[i]],
910 buf);
911 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100912 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100913 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200914 }
915
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100916 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
917 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100918 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100919 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100920
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100921 if (memcmp(buf, ct_test_data[j * 6 + i],
922 pt_len_test_data[i]) != 0 ||
923 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100924 ret = 1;
925 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200926 }
927
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100928 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200929
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100930 if (verbose != 0) {
931 mbedtls_printf("passed\n");
932 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200933
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100934 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100935
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100936 if (verbose != 0) {
937 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
938 key_len, i, "dec");
939 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200940
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100941 ret = mbedtls_gcm_setkey(&ctx, cipher,
942 key_test_data[key_index_test_data[i]],
943 key_len);
944 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100945 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100946 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200947
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100948 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
949 iv_test_data[iv_index_test_data[i]],
950 iv_len_test_data[i],
951 additional_test_data[add_index_test_data[i]],
952 add_len_test_data[i]);
953 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100954 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100955 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200956
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100957 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100958 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100959 ret = mbedtls_gcm_update(&ctx, 32, ct_test_data[j * 6 + i],
960 buf);
961 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100962 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100963 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200964
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100965 ret = mbedtls_gcm_update(&ctx, rest_len,
966 ct_test_data[j * 6 + i] + 32,
967 buf + 32);
968 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100969 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100970 }
971 } else {
972 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
973 ct_test_data[j * 6 + i],
974 buf);
975 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100976 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100977 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200978 }
979
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100980 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
981 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100982 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100983 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100984
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100985 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
986 pt_len_test_data[i]) != 0 ||
987 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100988 ret = 1;
989 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200990 }
991
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100992 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200993
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100994 if (verbose != 0) {
995 mbedtls_printf("passed\n");
996 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000997 }
998 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200999
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001000 if (verbose != 0) {
1001 mbedtls_printf("\n");
1002 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001003
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001004 ret = 0;
1005
1006exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001007 if (ret != 0) {
1008 if (verbose != 0) {
1009 mbedtls_printf("failed\n");
1010 }
1011 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001012 }
1013
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001014 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001015}
1016
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019#endif /* MBEDTLS_GCM_C */