blob: f7db0d42df7b57ecb7ea423c90d0831b89651ac1 [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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
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 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
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 Peskine1b6c09a2023-01-11 14:52:35 +0100757 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000758 int key_len = 128 + 64 * j;
759
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100760 for (i = 0; i < MAX_TESTS; i++) {
761 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100762
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100763 if (verbose != 0) {
764 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
765 key_len, i, "enc");
766 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200767
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100768 ret = mbedtls_gcm_setkey(&ctx, cipher,
769 key_test_data[key_index_test_data[i]],
770 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100771 /*
772 * AES-192 is an optional feature that may be unavailable when
773 * there is an alternative underlying implementation i.e. when
774 * MBEDTLS_AES_ALT is defined.
775 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100776 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
777 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100778 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100779 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100780 goto exit;
781 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000782
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100783 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
784 pt_len_test_data[i],
785 iv_test_data[iv_index_test_data[i]],
786 iv_len_test_data[i],
787 additional_test_data[add_index_test_data[i]],
788 add_len_test_data[i],
789 pt_test_data[pt_index_test_data[i]],
790 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100791#if defined(MBEDTLS_GCM_ALT)
792 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100793 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
794 iv_len_test_data[i] != 12) {
795 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100796 break;
797 }
798#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100799 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100800 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100801 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000802
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100803 if (memcmp(buf, ct_test_data[j * 6 + i],
804 pt_len_test_data[i]) != 0 ||
805 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100806 ret = 1;
807 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000808 }
809
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100810 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200811
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100812 if (verbose != 0) {
813 mbedtls_printf("passed\n");
814 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000815
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100816 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100817
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100818 if (verbose != 0) {
819 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
820 key_len, i, "dec");
821 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200822
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100823 ret = mbedtls_gcm_setkey(&ctx, cipher,
824 key_test_data[key_index_test_data[i]],
825 key_len);
826 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100827 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100828 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000829
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100830 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
831 pt_len_test_data[i],
832 iv_test_data[iv_index_test_data[i]],
833 iv_len_test_data[i],
834 additional_test_data[add_index_test_data[i]],
835 add_len_test_data[i],
836 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000837
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100838 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100839 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100840 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100841
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100842 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
843 pt_len_test_data[i]) != 0 ||
844 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100845 ret = 1;
846 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000847 }
848
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100849 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200850
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100851 if (verbose != 0) {
852 mbedtls_printf("passed\n");
853 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200854
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100855 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100856
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100857 if (verbose != 0) {
858 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
859 key_len, i, "enc");
860 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200861
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100862 ret = mbedtls_gcm_setkey(&ctx, cipher,
863 key_test_data[key_index_test_data[i]],
864 key_len);
865 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100866 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100867 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200868
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100869 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
870 iv_test_data[iv_index_test_data[i]],
871 iv_len_test_data[i],
872 additional_test_data[add_index_test_data[i]],
873 add_len_test_data[i]);
874 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100875 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100876 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200877
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100878 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100879 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100880 ret = mbedtls_gcm_update(&ctx, 32,
881 pt_test_data[pt_index_test_data[i]],
882 buf);
883 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100884 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100885 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200886
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100887 ret = mbedtls_gcm_update(&ctx, rest_len,
888 pt_test_data[pt_index_test_data[i]] + 32,
889 buf + 32);
890 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100891 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100892 }
893 } else {
894 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
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 }
901
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100902 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
903 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100904 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100905 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100906
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100907 if (memcmp(buf, ct_test_data[j * 6 + i],
908 pt_len_test_data[i]) != 0 ||
909 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100910 ret = 1;
911 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200912 }
913
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100914 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200915
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100916 if (verbose != 0) {
917 mbedtls_printf("passed\n");
918 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200919
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100920 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100921
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100922 if (verbose != 0) {
923 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
924 key_len, i, "dec");
925 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200926
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100927 ret = mbedtls_gcm_setkey(&ctx, cipher,
928 key_test_data[key_index_test_data[i]],
929 key_len);
930 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100931 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100932 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200933
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100934 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
935 iv_test_data[iv_index_test_data[i]],
936 iv_len_test_data[i],
937 additional_test_data[add_index_test_data[i]],
938 add_len_test_data[i]);
939 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100940 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100941 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200942
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100943 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100944 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100945 ret = mbedtls_gcm_update(&ctx, 32, ct_test_data[j * 6 + i],
946 buf);
947 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100948 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100949 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200950
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100951 ret = mbedtls_gcm_update(&ctx, rest_len,
952 ct_test_data[j * 6 + i] + 32,
953 buf + 32);
954 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100955 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100956 }
957 } else {
958 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
959 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 }
965
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100966 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
967 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100968 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100969 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100970
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100971 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
972 pt_len_test_data[i]) != 0 ||
973 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100974 ret = 1;
975 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200976 }
977
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100978 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200979
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100980 if (verbose != 0) {
981 mbedtls_printf("passed\n");
982 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000983 }
984 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200985
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100986 if (verbose != 0) {
987 mbedtls_printf("\n");
988 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000989
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100990 ret = 0;
991
992exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100993 if (ret != 0) {
994 if (verbose != 0) {
995 mbedtls_printf("failed\n");
996 }
997 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100998 }
999
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001000 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001001}
1002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001005#endif /* MBEDTLS_GCM_C */