blob: 0fa0008e38d6793decbd93320885bd6245c6d394 [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 Peskineed1c7f42022-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)
Chris Jones187782f2021-03-09 17:28:35 +000042#include "aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010043#endif
44
Jerry Yudf87a122023-01-10 18:17:15 +080045#if defined(MBEDTLS_AESCE_C)
46#include "aesce.h"
47#endif
48
Jaeden Amero15263302017-09-21 12:53:48 +010049#if !defined(MBEDTLS_GCM_ALT)
50
Paul Bakker89e80c92012-03-20 13:50:09 +000051/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020052 * Initialize a context
53 */
Gilles Peskine449bd832023-01-11 14:50:10 +010054void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020055{
Gilles Peskine449bd832023-01-11 14:50:10 +010056 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020057}
58
59/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010060 * Precompute small multiples of H, that is set
61 * HH[i] || HL[i] = H times i,
62 * where i is seen as a field element as in [MGV], ie high-order bits
63 * correspond to low powers of P. The result is stored in the same way, that
64 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
65 * corresponds to P^127.
66 */
Gilles Peskine449bd832023-01-11 14:50:10 +010067static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000068{
Paul Bakker43aff2a2013-09-09 00:10:27 +020069 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000070 uint64_t hi, lo;
71 uint64_t vl, vh;
72 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020073 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020074
Gilles Peskine449bd832023-01-11 14:50:10 +010075 memset(h, 0, 16);
76 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
77 return ret;
78 }
Paul Bakker89e80c92012-03-20 13:50:09 +000079
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010080 /* pack h as two 64-bits ints, big-endian */
Gilles Peskine449bd832023-01-11 14:50:10 +010081 hi = MBEDTLS_GET_UINT32_BE(h, 0);
82 lo = MBEDTLS_GET_UINT32_BE(h, 4);
Paul Bakker89e80c92012-03-20 13:50:09 +000083 vh = (uint64_t) hi << 32 | lo;
84
Gilles Peskine449bd832023-01-11 14:50:10 +010085 hi = MBEDTLS_GET_UINT32_BE(h, 8);
86 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +000087 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020088
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010089 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000090 ctx->HL[8] = vl;
91 ctx->HH[8] = vh;
92
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010094 /* With CLMUL support, we need only h, not the rest of the table */
Gilles Peskine449bd832023-01-11 14:50:10 +010095 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
96 return 0;
97 }
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010098#endif
99
Jerry Yudf87a122023-01-10 18:17:15 +0800100#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
101 if (mbedtls_aesce_has_support()) {
102 return 0;
103 }
104#endif
105
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100106 /* 0 corresponds to 0 in GF(2^128) */
107 ctx->HH[0] = 0;
108 ctx->HL[0] = 0;
109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 for (i = 4; i > 0; i >>= 1) {
111 uint32_t T = (vl & 1) * 0xe1000000U;
112 vl = (vh << 63) | (vl >> 1);
113 vh = (vh >> 1) ^ ((uint64_t) T << 32);
Paul Bakker89e80c92012-03-20 13:50:09 +0000114
115 ctx->HL[i] = vl;
116 ctx->HH[i] = vh;
117 }
118
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 for (i = 2; i <= 8; i *= 2) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000120 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
121 vh = *HiH;
122 vl = *HiL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100123 for (j = 1; j < i; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000124 HiH[j] = vh ^ ctx->HH[j];
125 HiL[j] = vl ^ ctx->HL[j];
126 }
127 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000130}
131
Gilles Peskine449bd832023-01-11 14:50:10 +0100132int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
133 mbedtls_cipher_id_t cipher,
134 const unsigned char *key,
135 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000136{
Janos Follath24eed8d2019-11-22 13:21:35 +0000137 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000139
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 if (keybits != 128 && keybits != 192 && keybits != 256) {
Tuvshinzaya Erdenekhuuc6b8a672022-08-05 15:31:57 +0100141 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200142 }
143
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
145 MBEDTLS_MODE_ECB);
146 if (cipher_info == NULL) {
147 return MBEDTLS_ERR_GCM_BAD_INPUT;
148 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000149
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 if (cipher_info->block_size != 16) {
151 return MBEDTLS_ERR_GCM_BAD_INPUT;
152 }
153
154 mbedtls_cipher_free(&ctx->cipher_ctx);
155
156 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
157 return ret;
158 }
159
160 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
161 MBEDTLS_ENCRYPT)) != 0) {
162 return ret;
163 }
164
165 if ((ret = gcm_gen_table(ctx)) != 0) {
166 return ret;
167 }
168
169 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000170}
171
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100172/*
173 * Shoup's method for multiplication use this table with
174 * last4[x] = x times P^128
175 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
176 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000177static const uint64_t last4[16] =
178{
179 0x0000, 0x1c20, 0x3840, 0x2460,
180 0x7080, 0x6ca0, 0x48c0, 0x54e0,
181 0xe100, 0xfd20, 0xd940, 0xc560,
182 0x9180, 0x8da0, 0xa9c0, 0xb5e0
183};
184
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100185/*
186 * Sets output to x times H using the precomputed tables.
187 * x and output are seen as elements of GF(2^128) as in [MGV].
188 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100189static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
190 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000191{
192 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000193 unsigned char lo, hi, rem;
194 uint64_t zh, zl;
195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100198 unsigned char h[16];
199
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
201 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
202 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
203 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 mbedtls_aesni_gcm_mult(output, x, h);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100206 return;
207 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100209
Jerry Yudf87a122023-01-10 18:17:15 +0800210#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
211 if (mbedtls_aesce_has_support()) {
212 unsigned char h[16];
213
214 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
215 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
216 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
217 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
218
219 mbedtls_aesce_gcm_mult(output, x, h);
220 return;
221 }
222#endif
223
Paul Bakker89e80c92012-03-20 13:50:09 +0000224 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000225
226 zh = ctx->HH[lo];
227 zl = ctx->HL[lo];
228
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000230 lo = x[i] & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000232
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 if (i != 15) {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000234 rem = (unsigned char) zl & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 zl = (zh << 60) | (zl >> 4);
236 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000237 zh ^= (uint64_t) last4[rem] << 48;
238 zh ^= ctx->HH[lo];
239 zl ^= ctx->HL[lo];
240
241 }
242
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000243 rem = (unsigned char) zl & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 zl = (zh << 60) | (zl >> 4);
245 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000246 zh ^= (uint64_t) last4[rem] << 48;
247 zh ^= ctx->HH[hi];
248 zl ^= ctx->HL[hi];
249 }
250
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
252 MBEDTLS_PUT_UINT32_BE(zh, output, 4);
253 MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
254 MBEDTLS_PUT_UINT32_BE(zl, output, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000255}
256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
258 int mode,
259 const unsigned char *iv, size_t iv_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000260{
Janos Follath24eed8d2019-11-22 13:21:35 +0000261 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000262 unsigned char work_buf[16];
Paul Bakker89e80c92012-03-20 13:50:09 +0000263 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200264 size_t use_len, olen = 0;
openluopworldeab65ac2021-09-22 23:59:42 +0800265 uint64_t iv_bits;
Paul Bakker89e80c92012-03-20 13:50:09 +0000266
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200267 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200268 /* IV is not allowed to be zero length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
270 return MBEDTLS_ERR_GCM_BAD_INPUT;
271 }
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200272
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 memset(ctx->y, 0x00, sizeof(ctx->y));
274 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200275
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200276 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200277 ctx->len = 0;
278 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000279
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 if (iv_len == 12) {
281 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200282 ctx->y[15] = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 } else {
284 memset(work_buf, 0x00, 16);
285 iv_bits = (uint64_t) iv_len * 8;
286 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000287
288 p = iv;
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 while (iv_len > 0) {
290 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000291
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200293
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000295
296 iv_len -= use_len;
297 p += use_len;
298 }
299
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000301
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000303 }
304
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
306 ctx->base_ectr, &olen)) != 0) {
307 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200308 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000309
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200311}
312
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200313/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200314 * mbedtls_gcm_context::buf contains the partial state of the computation of
315 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200316 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
317 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200318 * * len == 0 && add_len == 0: initial state
319 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
320 * a partial block of AD that has been
321 * xored in but not yet multiplied in.
322 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
323 * the data ends now.
324 * * len % 16 != 0: the first `len % 16` bytes have
325 * a partial block of ciphertext that has
326 * been xored in but not yet multiplied in.
327 * * len > 0 && len % 16 == 0: the authentication tag is correct if
328 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200329 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100330int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
331 const unsigned char *add, size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200332{
333 const unsigned char *p;
Dave Rodgmand22fb732022-11-22 16:53:25 +0000334 size_t use_len, offset;
Gilles Peskine295fc132021-04-15 18:32:23 +0200335
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200336 /* IV is limited to 2^64 bits, so 2^61 bytes */
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 if ((uint64_t) add_len >> 61 != 0) {
338 return MBEDTLS_ERR_GCM_BAD_INPUT;
339 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200340
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200341 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000342 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200343
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200345 use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200347 use_len = add_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200351
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 if (offset + use_len == 16) {
353 gcm_mult(ctx, ctx->buf, ctx->buf);
354 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200355
356 ctx->add_len += use_len;
357 add_len -= use_len;
358 p += use_len;
359 }
360
361 ctx->add_len += add_len;
362
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 while (add_len >= 16) {
364 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000367
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200368 add_len -= 16;
369 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000370 }
371
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 if (add_len > 0) {
373 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200374 }
375
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200377}
378
Gilles Peskine58fc2722021-04-13 15:58:27 +0200379/* Increment the counter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100380static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200381{
382 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 for (i = 16; i > 12; i--) {
384 if (++y[i - 1] != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200385 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 }
387 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200388}
389
390/* Calculate and apply the encryption mask. Process use_len bytes of data,
391 * starting at position offset in the mask block. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100392static int gcm_mask(mbedtls_gcm_context *ctx,
393 unsigned char ectr[16],
394 size_t offset, size_t use_len,
395 const unsigned char *input,
396 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200397{
Gilles Peskine58fc2722021-04-13 15:58:27 +0200398 size_t olen = 0;
399 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
400
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
402 &olen)) != 0) {
403 mbedtls_platform_zeroize(ectr, 16);
404 return ret;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200405 }
406
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
408 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
409 }
410 mbedtls_xor(output, ectr + offset, input, use_len);
411 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
412 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
413 }
Dave Rodgmand22fb732022-11-22 16:53:25 +0000414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200416}
417
Gilles Peskine449bd832023-01-11 14:50:10 +0100418int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
419 const unsigned char *input, size_t input_length,
420 unsigned char *output, size_t output_size,
421 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200422{
Janos Follath24eed8d2019-11-22 13:21:35 +0000423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200424 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200425 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200426 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 if (output_size < input_length) {
430 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
431 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200432 *output_length = input_length;
433
434 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200435 * on a potentially null pointer.
436 * Returning early also means that the last partial block of AD remains
437 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 if (input_length == 0) {
439 return 0;
440 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 if (output > input && (size_t) (output - input) < input_length) {
443 return MBEDTLS_ERR_GCM_BAD_INPUT;
444 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200445
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200446 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
447 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 if (ctx->len + input_length < ctx->len ||
449 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
450 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200451 }
452
Gilles Peskine449bd832023-01-11 14:50:10 +0100453 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
454 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200455 }
456
Gilles Peskine58fc2722021-04-13 15:58:27 +0200457 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200459 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200461 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000463
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
465 return ret;
466 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000467
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 if (offset + use_len == 16) {
469 gcm_mult(ctx, ctx->buf, ctx->buf);
470 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200471
Gilles Peskine58fc2722021-04-13 15:58:27 +0200472 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200473 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000474 p += use_len;
475 out_p += use_len;
476 }
477
Gilles Peskinea56c4482021-04-15 17:22:35 +0200478 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200479
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 while (input_length >= 16) {
481 gcm_incr(ctx->y);
482 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
483 return ret;
484 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200485
Gilles Peskine449bd832023-01-11 14:50:10 +0100486 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200487
Gilles Peskinea56c4482021-04-15 17:22:35 +0200488 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200489 p += 16;
490 out_p += 16;
491 }
492
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 if (input_length > 0) {
494 gcm_incr(ctx->y);
495 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
496 return ret;
497 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200498 }
499
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 mbedtls_platform_zeroize(ectr, sizeof(ectr));
501 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200502}
503
Gilles Peskine449bd832023-01-11 14:50:10 +0100504int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
505 unsigned char *output, size_t output_size,
506 size_t *output_length,
507 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200508{
509 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100510 uint64_t orig_len;
511 uint64_t orig_add_len;
512
Gilles Peskine9461e452021-04-15 16:48:32 +0200513 /* We never pass any output in finish(). The output parameter exists only
514 * for the sake of alternative implementations. */
515 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200516 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200517 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200518
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100519 orig_len = ctx->len * 8;
520 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200521
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
523 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200524 }
525
Gilles Peskine449bd832023-01-11 14:50:10 +0100526 if (tag_len > 16 || tag_len < 4) {
527 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000528 }
529
Gilles Peskine449bd832023-01-11 14:50:10 +0100530 if (ctx->len % 16 != 0) {
531 gcm_mult(ctx, ctx->buf, ctx->buf);
532 }
533
534 memcpy(tag, ctx->base_ectr, tag_len);
535
536 if (orig_len || orig_add_len) {
537 memset(work_buf, 0x00, 16);
538
539 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
540 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
541 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
542 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
543
544 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
545
546 gcm_mult(ctx, ctx->buf, ctx->buf);
547
548 mbedtls_xor(tag, tag, ctx->buf, tag_len);
549 }
550
551 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000552}
553
Gilles Peskine449bd832023-01-11 14:50:10 +0100554int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
555 int mode,
556 size_t length,
557 const unsigned char *iv,
558 size_t iv_len,
559 const unsigned char *add,
560 size_t add_len,
561 const unsigned char *input,
562 unsigned char *output,
563 size_t tag_len,
564 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200565{
Janos Follath24eed8d2019-11-22 13:21:35 +0000566 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200567 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200568
Gilles Peskine449bd832023-01-11 14:50:10 +0100569 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
570 return ret;
571 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200572
Gilles Peskine449bd832023-01-11 14:50:10 +0100573 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
574 return ret;
575 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200576
Gilles Peskine449bd832023-01-11 14:50:10 +0100577 if ((ret = mbedtls_gcm_update(ctx, input, length,
578 output, length, &olen)) != 0) {
579 return ret;
580 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200581
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
583 return ret;
584 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200585
Gilles Peskine449bd832023-01-11 14:50:10 +0100586 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200587}
588
Gilles Peskine449bd832023-01-11 14:50:10 +0100589int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
590 size_t length,
591 const unsigned char *iv,
592 size_t iv_len,
593 const unsigned char *add,
594 size_t add_len,
595 const unsigned char *tag,
596 size_t tag_len,
597 const unsigned char *input,
598 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000599{
Janos Follath24eed8d2019-11-22 13:21:35 +0000600 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000601 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200602 size_t i;
603 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000604
Gilles Peskine449bd832023-01-11 14:50:10 +0100605 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
606 iv, iv_len, add, add_len,
607 input, output, tag_len, check_tag)) != 0) {
608 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100609 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000610
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200611 /* Check tag in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 for (diff = 0, i = 0; i < tag_len; i++) {
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200613 diff |= tag[i] ^ check_tag[i];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200614 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000615
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 if (diff != 0) {
617 mbedtls_platform_zeroize(output, length);
618 return MBEDTLS_ERR_GCM_AUTH_FAILED;
619 }
620
621 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000622}
623
Gilles Peskine449bd832023-01-11 14:50:10 +0100624void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200625{
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100627 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 }
629 mbedtls_cipher_free(&ctx->cipher_ctx);
630 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200631}
632
Jaeden Amero15263302017-09-21 12:53:48 +0100633#endif /* !MBEDTLS_GCM_ALT */
634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000636/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200637 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 *
639 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
640 */
641#define MAX_TESTS 6
642
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100643static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100644{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000645
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100646static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000647{
648 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
652 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
653 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
654 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000656};
657
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100658static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100659{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000660
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100661static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100662{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000663
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100664static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000665{
666 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00 },
668 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
669 0xde, 0xca, 0xf8, 0x88 },
670 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200671 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000672 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200673 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000674 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200675 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000676 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200677 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000678};
679
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100680static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100681{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000682
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100683static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100684{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000685
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100686static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000687{
688 { 0x00 },
689 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 0xab, 0xad, 0xda, 0xd2 },
692};
693
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100694static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100695{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000696
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100697static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100698{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000699
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100700static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000701{
702 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
704 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
705 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
706 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
707 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
708 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
709 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
710 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
711 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
712};
713
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100714static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000715{
716 { 0x00 },
717 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
718 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
719 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
726 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
727 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
734 0x3d, 0x58, 0xe0, 0x91 },
735 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200736 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000737 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000739 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200740 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000741 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
742 0xc2, 0x3f, 0x45, 0x98 },
743 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200744 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000745 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200746 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000747 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200748 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000749 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
750 0x4c, 0x34, 0xae, 0xe5 },
751 { 0x00 },
752 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200753 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000754 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200755 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000756 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200757 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000758 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200759 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000760 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
761 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
762 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200763 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000764 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200765 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
766 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
767 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000768 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200769 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000770 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200771 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000772 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200773 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000774 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200775 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000776 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200777 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000778 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200779 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000780 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200781 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000782 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200783 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000784 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200785 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000786 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200787 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
788 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
789 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
790 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
791 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
792 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
793 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
794 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
795 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
796 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
797 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
798 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
799 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
800 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
801 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
802 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
803 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
804 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000805 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200806 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000807 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200808 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000809 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200810 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000811 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200812 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000813 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200814 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000815 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200816 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000817 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200818 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000819 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200820 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000821};
822
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100823static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000824{
825 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
826 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
827 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
828 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
829 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200830 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000831 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
832 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
833 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
834 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
835 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
836 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
837 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
838 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
839 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200840 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000841 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
842 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
843 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200844 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000845 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200846 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000847 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200848 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000849 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200850 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000851 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200852 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000853 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200854 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000855 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200856 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000857 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200858 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000859 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200860 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000861};
862
Gilles Peskine449bd832023-01-11 14:50:10 +0100863int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000864{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000866 unsigned char buf[64];
867 unsigned char tag_buf[16];
868 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200870 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +0000871
Gilles Peskine449bd832023-01-11 14:50:10 +0100872 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000873 int key_len = 128 + 64 * j;
874
Gilles Peskine449bd832023-01-11 14:50:10 +0100875 for (i = 0; i < MAX_TESTS; i++) {
876 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100877
Gilles Peskine449bd832023-01-11 14:50:10 +0100878 if (verbose != 0) {
879 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
880 key_len, i, "enc");
881 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200882
Gilles Peskine449bd832023-01-11 14:50:10 +0100883 ret = mbedtls_gcm_setkey(&ctx, cipher,
884 key_test_data[key_index_test_data[i]],
885 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100886 /*
887 * AES-192 is an optional feature that may be unavailable when
888 * there is an alternative underlying implementation i.e. when
889 * MBEDTLS_AES_ALT is defined.
890 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100891 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
892 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100893 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100894 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100895 goto exit;
896 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000897
Gilles Peskine449bd832023-01-11 14:50:10 +0100898 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
899 pt_len_test_data[i],
900 iv_test_data[iv_index_test_data[i]],
901 iv_len_test_data[i],
902 additional_test_data[add_index_test_data[i]],
903 add_len_test_data[i],
904 pt_test_data[pt_index_test_data[i]],
905 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100906#if defined(MBEDTLS_GCM_ALT)
907 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100908 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
909 iv_len_test_data[i] != 12) {
910 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100911 break;
912 }
913#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100914 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100915 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100916 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000917
Gilles Peskine449bd832023-01-11 14:50:10 +0100918 if (memcmp(buf, ct_test_data[j * 6 + i],
919 pt_len_test_data[i]) != 0 ||
920 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100921 ret = 1;
922 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000923 }
924
Gilles Peskine449bd832023-01-11 14:50:10 +0100925 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200926
Gilles Peskine449bd832023-01-11 14:50:10 +0100927 if (verbose != 0) {
928 mbedtls_printf("passed\n");
929 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000930
Gilles Peskine449bd832023-01-11 14:50:10 +0100931 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100932
Gilles Peskine449bd832023-01-11 14:50:10 +0100933 if (verbose != 0) {
934 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
935 key_len, i, "dec");
936 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200937
Gilles Peskine449bd832023-01-11 14:50:10 +0100938 ret = mbedtls_gcm_setkey(&ctx, cipher,
939 key_test_data[key_index_test_data[i]],
940 key_len);
941 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100942 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100943 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000944
Gilles Peskine449bd832023-01-11 14:50:10 +0100945 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
946 pt_len_test_data[i],
947 iv_test_data[iv_index_test_data[i]],
948 iv_len_test_data[i],
949 additional_test_data[add_index_test_data[i]],
950 add_len_test_data[i],
951 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000952
Gilles Peskine449bd832023-01-11 14:50:10 +0100953 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100954 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100955 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100956
Gilles Peskine449bd832023-01-11 14:50:10 +0100957 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
958 pt_len_test_data[i]) != 0 ||
959 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100960 ret = 1;
961 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000962 }
963
Gilles Peskine449bd832023-01-11 14:50:10 +0100964 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200965
Gilles Peskine449bd832023-01-11 14:50:10 +0100966 if (verbose != 0) {
967 mbedtls_printf("passed\n");
968 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200969
Gilles Peskine449bd832023-01-11 14:50:10 +0100970 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100971
Gilles Peskine449bd832023-01-11 14:50:10 +0100972 if (verbose != 0) {
973 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
974 key_len, i, "enc");
975 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200976
Gilles Peskine449bd832023-01-11 14:50:10 +0100977 ret = mbedtls_gcm_setkey(&ctx, cipher,
978 key_test_data[key_index_test_data[i]],
979 key_len);
980 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100981 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100982 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200983
Gilles Peskine449bd832023-01-11 14:50:10 +0100984 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
985 iv_test_data[iv_index_test_data[i]],
986 iv_len_test_data[i]);
987 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +0200988 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100989 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200990
Gilles Peskine449bd832023-01-11 14:50:10 +0100991 ret = mbedtls_gcm_update_ad(&ctx,
992 additional_test_data[add_index_test_data[i]],
993 add_len_test_data[i]);
994 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100995 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100996 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200997
Gilles Peskine449bd832023-01-11 14:50:10 +0100998 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100999 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001000 ret = mbedtls_gcm_update(&ctx,
1001 pt_test_data[pt_index_test_data[i]],
1002 32,
1003 buf, sizeof(buf), &olen);
1004 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001005 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001006 }
1007 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001008 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001009 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001010
Gilles Peskine449bd832023-01-11 14:50:10 +01001011 ret = mbedtls_gcm_update(&ctx,
1012 pt_test_data[pt_index_test_data[i]] + 32,
1013 rest_len,
1014 buf + 32, sizeof(buf) - 32, &olen);
1015 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001016 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001017 }
1018 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001019 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001020 }
1021 } else {
1022 ret = mbedtls_gcm_update(&ctx,
1023 pt_test_data[pt_index_test_data[i]],
1024 pt_len_test_data[i],
1025 buf, sizeof(buf), &olen);
1026 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001027 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 }
1029 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001030 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001031 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001032 }
1033
Gilles Peskine449bd832023-01-11 14:50:10 +01001034 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1035 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001036 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001037 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001038
Gilles Peskine449bd832023-01-11 14:50:10 +01001039 if (memcmp(buf, ct_test_data[j * 6 + i],
1040 pt_len_test_data[i]) != 0 ||
1041 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001042 ret = 1;
1043 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001044 }
1045
Gilles Peskine449bd832023-01-11 14:50:10 +01001046 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001047
Gilles Peskine449bd832023-01-11 14:50:10 +01001048 if (verbose != 0) {
1049 mbedtls_printf("passed\n");
1050 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001051
Gilles Peskine449bd832023-01-11 14:50:10 +01001052 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001053
Gilles Peskine449bd832023-01-11 14:50:10 +01001054 if (verbose != 0) {
1055 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1056 key_len, i, "dec");
1057 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001058
Gilles Peskine449bd832023-01-11 14:50:10 +01001059 ret = mbedtls_gcm_setkey(&ctx, cipher,
1060 key_test_data[key_index_test_data[i]],
1061 key_len);
1062 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001063 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001064 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001065
Gilles Peskine449bd832023-01-11 14:50:10 +01001066 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1067 iv_test_data[iv_index_test_data[i]],
1068 iv_len_test_data[i]);
1069 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001070 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001071 }
1072 ret = mbedtls_gcm_update_ad(&ctx,
1073 additional_test_data[add_index_test_data[i]],
1074 add_len_test_data[i]);
1075 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001076 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001077 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001078
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001080 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001081 ret = mbedtls_gcm_update(&ctx,
1082 ct_test_data[j * 6 + i], 32,
1083 buf, sizeof(buf), &olen);
1084 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001085 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 }
1087 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001088 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001089 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001090
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 ret = mbedtls_gcm_update(&ctx,
1092 ct_test_data[j * 6 + i] + 32,
1093 rest_len,
1094 buf + 32, sizeof(buf) - 32, &olen);
1095 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001096 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001097 }
1098 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001099 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001100 }
1101 } else {
1102 ret = mbedtls_gcm_update(&ctx,
1103 ct_test_data[j * 6 + i],
1104 pt_len_test_data[i],
1105 buf, sizeof(buf), &olen);
1106 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001107 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 }
1109 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001110 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001111 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001112 }
1113
Gilles Peskine449bd832023-01-11 14:50:10 +01001114 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1115 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001116 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001117 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001118
Gilles Peskine449bd832023-01-11 14:50:10 +01001119 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1120 pt_len_test_data[i]) != 0 ||
1121 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001122 ret = 1;
1123 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001124 }
1125
Gilles Peskine449bd832023-01-11 14:50:10 +01001126 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001127
Gilles Peskine449bd832023-01-11 14:50:10 +01001128 if (verbose != 0) {
1129 mbedtls_printf("passed\n");
1130 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001131 }
1132 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 if (verbose != 0) {
1135 mbedtls_printf("\n");
1136 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001137
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001138 ret = 0;
1139
1140exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001141 if (ret != 0) {
1142 if (verbose != 0) {
1143 mbedtls_printf("failed\n");
1144 }
1145 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001146 }
1147
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001149}
1150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153#endif /* MBEDTLS_GCM_C */