blob: 6d4495fd39431a3085e9acd4a6015538482342af [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
Jaeden Amero15263302017-09-21 12:53:48 +010045#if !defined(MBEDTLS_GCM_ALT)
46
Paul Bakker89e80c92012-03-20 13:50:09 +000047/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020048 * Initialize a context
49 */
Gilles Peskine449bd832023-01-11 14:50:10 +010050void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020051{
Gilles Peskine449bd832023-01-11 14:50:10 +010052 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020053}
54
55/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010056 * Precompute small multiples of H, that is set
57 * HH[i] || HL[i] = H times i,
58 * where i is seen as a field element as in [MGV], ie high-order bits
59 * correspond to low powers of P. The result is stored in the same way, that
60 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
61 * corresponds to P^127.
62 */
Gilles Peskine449bd832023-01-11 14:50:10 +010063static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000064{
Paul Bakker43aff2a2013-09-09 00:10:27 +020065 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000066 uint64_t hi, lo;
67 uint64_t vl, vh;
68 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020069 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020070
Gilles Peskine449bd832023-01-11 14:50:10 +010071 memset(h, 0, 16);
72 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
73 return ret;
74 }
Paul Bakker89e80c92012-03-20 13:50:09 +000075
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010076 /* pack h as two 64-bits ints, big-endian */
Gilles Peskine449bd832023-01-11 14:50:10 +010077 hi = MBEDTLS_GET_UINT32_BE(h, 0);
78 lo = MBEDTLS_GET_UINT32_BE(h, 4);
Paul Bakker89e80c92012-03-20 13:50:09 +000079 vh = (uint64_t) hi << 32 | lo;
80
Gilles Peskine449bd832023-01-11 14:50:10 +010081 hi = MBEDTLS_GET_UINT32_BE(h, 8);
82 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +000083 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020084
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010085 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000086 ctx->HL[8] = vl;
87 ctx->HH[8] = vh;
88
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010090 /* With CLMUL support, we need only h, not the rest of the table */
Gilles Peskine449bd832023-01-11 14:50:10 +010091 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
92 return 0;
93 }
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010094#endif
95
96 /* 0 corresponds to 0 in GF(2^128) */
97 ctx->HH[0] = 0;
98 ctx->HL[0] = 0;
99
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 for (i = 4; i > 0; i >>= 1) {
101 uint32_t T = (vl & 1) * 0xe1000000U;
102 vl = (vh << 63) | (vl >> 1);
103 vh = (vh >> 1) ^ ((uint64_t) T << 32);
Paul Bakker89e80c92012-03-20 13:50:09 +0000104
105 ctx->HL[i] = vl;
106 ctx->HH[i] = vh;
107 }
108
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 for (i = 2; i <= 8; i *= 2) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000110 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
111 vh = *HiH;
112 vl = *HiL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 for (j = 1; j < i; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000114 HiH[j] = vh ^ ctx->HH[j];
115 HiL[j] = vl ^ ctx->HL[j];
116 }
117 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200118
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000120}
121
Gilles Peskine449bd832023-01-11 14:50:10 +0100122int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
123 mbedtls_cipher_id_t cipher,
124 const unsigned char *key,
125 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000126{
Janos Follath24eed8d2019-11-22 13:21:35 +0000127 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000129
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 if (keybits != 128 && keybits != 192 && keybits != 256) {
Tuvshinzaya Erdenekhuuc6b8a672022-08-05 15:31:57 +0100131 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200132 }
133
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
135 MBEDTLS_MODE_ECB);
136 if (cipher_info == NULL) {
137 return MBEDTLS_ERR_GCM_BAD_INPUT;
138 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000139
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 if (cipher_info->block_size != 16) {
141 return MBEDTLS_ERR_GCM_BAD_INPUT;
142 }
143
144 mbedtls_cipher_free(&ctx->cipher_ctx);
145
146 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
147 return ret;
148 }
149
150 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
151 MBEDTLS_ENCRYPT)) != 0) {
152 return ret;
153 }
154
155 if ((ret = gcm_gen_table(ctx)) != 0) {
156 return ret;
157 }
158
159 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000160}
161
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100162/*
163 * Shoup's method for multiplication use this table with
164 * last4[x] = x times P^128
165 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
166 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000167static const uint64_t last4[16] =
168{
169 0x0000, 0x1c20, 0x3840, 0x2460,
170 0x7080, 0x6ca0, 0x48c0, 0x54e0,
171 0xe100, 0xfd20, 0xd940, 0xc560,
172 0x9180, 0x8da0, 0xa9c0, 0xb5e0
173};
174
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100175/*
176 * Sets output to x times H using the precomputed tables.
177 * x and output are seen as elements of GF(2^128) as in [MGV].
178 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100179static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
180 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000181{
182 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000183 unsigned char lo, hi, rem;
184 uint64_t zh, zl;
185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100188 unsigned char h[16];
189
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
191 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
192 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
193 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100194
Gilles Peskine449bd832023-01-11 14:50:10 +0100195 mbedtls_aesni_gcm_mult(output, x, h);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100196 return;
197 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100199
Paul Bakker89e80c92012-03-20 13:50:09 +0000200 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000201
202 zh = ctx->HH[lo];
203 zl = ctx->HL[lo];
204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000206 lo = x[i] & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000208
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 if (i != 15) {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000210 rem = (unsigned char) zl & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 zl = (zh << 60) | (zl >> 4);
212 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000213 zh ^= (uint64_t) last4[rem] << 48;
214 zh ^= ctx->HH[lo];
215 zl ^= ctx->HL[lo];
216
217 }
218
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000219 rem = (unsigned char) zl & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 zl = (zh << 60) | (zl >> 4);
221 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000222 zh ^= (uint64_t) last4[rem] << 48;
223 zh ^= ctx->HH[hi];
224 zl ^= ctx->HL[hi];
225 }
226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
228 MBEDTLS_PUT_UINT32_BE(zh, output, 4);
229 MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
230 MBEDTLS_PUT_UINT32_BE(zl, output, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000231}
232
Gilles Peskine449bd832023-01-11 14:50:10 +0100233int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
234 int mode,
235 const unsigned char *iv, size_t iv_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000236{
Janos Follath24eed8d2019-11-22 13:21:35 +0000237 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000238 unsigned char work_buf[16];
Paul Bakker89e80c92012-03-20 13:50:09 +0000239 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200240 size_t use_len, olen = 0;
openluopworldeab65ac2021-09-22 23:59:42 +0800241 uint64_t iv_bits;
Paul Bakker89e80c92012-03-20 13:50:09 +0000242
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200243 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200244 /* IV is not allowed to be zero length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
246 return MBEDTLS_ERR_GCM_BAD_INPUT;
247 }
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 memset(ctx->y, 0x00, sizeof(ctx->y));
250 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200251
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200252 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200253 ctx->len = 0;
254 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000255
Gilles Peskine449bd832023-01-11 14:50:10 +0100256 if (iv_len == 12) {
257 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200258 ctx->y[15] = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 } else {
260 memset(work_buf, 0x00, 16);
261 iv_bits = (uint64_t) iv_len * 8;
262 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000263
264 p = iv;
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 while (iv_len > 0) {
266 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000267
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200269
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000271
272 iv_len -= use_len;
273 p += use_len;
274 }
275
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000277
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000279 }
280
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
282 ctx->base_ectr, &olen)) != 0) {
283 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200284 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000285
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200287}
288
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200289/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200290 * mbedtls_gcm_context::buf contains the partial state of the computation of
291 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200292 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
293 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200294 * * len == 0 && add_len == 0: initial state
295 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
296 * a partial block of AD that has been
297 * xored in but not yet multiplied in.
298 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
299 * the data ends now.
300 * * len % 16 != 0: the first `len % 16` bytes have
301 * a partial block of ciphertext that has
302 * been xored in but not yet multiplied in.
303 * * len > 0 && len % 16 == 0: the authentication tag is correct if
304 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200305 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100306int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
307 const unsigned char *add, size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200308{
309 const unsigned char *p;
Dave Rodgmand22fb732022-11-22 16:53:25 +0000310 size_t use_len, offset;
Gilles Peskine295fc132021-04-15 18:32:23 +0200311
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200312 /* IV is limited to 2^64 bits, so 2^61 bytes */
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 if ((uint64_t) add_len >> 61 != 0) {
314 return MBEDTLS_ERR_GCM_BAD_INPUT;
315 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200316
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200317 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000318 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200319
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200321 use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100322 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200323 use_len = add_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200325
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200327
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 if (offset + use_len == 16) {
329 gcm_mult(ctx, ctx->buf, ctx->buf);
330 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200331
332 ctx->add_len += use_len;
333 add_len -= use_len;
334 p += use_len;
335 }
336
337 ctx->add_len += add_len;
338
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 while (add_len >= 16) {
340 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200341
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000343
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200344 add_len -= 16;
345 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000346 }
347
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 if (add_len > 0) {
349 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200350 }
351
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200353}
354
Gilles Peskine58fc2722021-04-13 15:58:27 +0200355/* Increment the counter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100356static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200357{
358 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 for (i = 16; i > 12; i--) {
360 if (++y[i - 1] != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200361 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 }
363 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200364}
365
366/* Calculate and apply the encryption mask. Process use_len bytes of data,
367 * starting at position offset in the mask block. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100368static int gcm_mask(mbedtls_gcm_context *ctx,
369 unsigned char ectr[16],
370 size_t offset, size_t use_len,
371 const unsigned char *input,
372 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200373{
Gilles Peskine58fc2722021-04-13 15:58:27 +0200374 size_t olen = 0;
375 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
376
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
378 &olen)) != 0) {
379 mbedtls_platform_zeroize(ectr, 16);
380 return ret;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200381 }
382
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
384 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
385 }
386 mbedtls_xor(output, ectr + offset, input, use_len);
387 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
388 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
389 }
Dave Rodgmand22fb732022-11-22 16:53:25 +0000390
Gilles Peskine449bd832023-01-11 14:50:10 +0100391 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200392}
393
Gilles Peskine449bd832023-01-11 14:50:10 +0100394int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
395 const unsigned char *input, size_t input_length,
396 unsigned char *output, size_t output_size,
397 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200398{
Janos Follath24eed8d2019-11-22 13:21:35 +0000399 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200400 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200401 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200402 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 if (output_size < input_length) {
406 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
407 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200408 *output_length = input_length;
409
410 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200411 * on a potentially null pointer.
412 * Returning early also means that the last partial block of AD remains
413 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 if (input_length == 0) {
415 return 0;
416 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200417
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 if (output > input && (size_t) (output - input) < input_length) {
419 return MBEDTLS_ERR_GCM_BAD_INPUT;
420 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200421
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200422 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
423 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 if (ctx->len + input_length < ctx->len ||
425 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
426 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200427 }
428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
430 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200431 }
432
Gilles Peskine58fc2722021-04-13 15:58:27 +0200433 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200435 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200437 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
441 return ret;
442 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 if (offset + use_len == 16) {
445 gcm_mult(ctx, ctx->buf, ctx->buf);
446 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200447
Gilles Peskine58fc2722021-04-13 15:58:27 +0200448 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200449 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000450 p += use_len;
451 out_p += use_len;
452 }
453
Gilles Peskinea56c4482021-04-15 17:22:35 +0200454 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 while (input_length >= 16) {
457 gcm_incr(ctx->y);
458 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
459 return ret;
460 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200461
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200463
Gilles Peskinea56c4482021-04-15 17:22:35 +0200464 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200465 p += 16;
466 out_p += 16;
467 }
468
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 if (input_length > 0) {
470 gcm_incr(ctx->y);
471 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
472 return ret;
473 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200474 }
475
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 mbedtls_platform_zeroize(ectr, sizeof(ectr));
477 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200478}
479
Gilles Peskine449bd832023-01-11 14:50:10 +0100480int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
481 unsigned char *output, size_t output_size,
482 size_t *output_length,
483 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200484{
485 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100486 uint64_t orig_len;
487 uint64_t orig_add_len;
488
Gilles Peskine9461e452021-04-15 16:48:32 +0200489 /* We never pass any output in finish(). The output parameter exists only
490 * for the sake of alternative implementations. */
491 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200492 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200493 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200494
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100495 orig_len = ctx->len * 8;
496 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200497
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
499 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200500 }
501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 if (tag_len > 16 || tag_len < 4) {
503 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000504 }
505
Gilles Peskine449bd832023-01-11 14:50:10 +0100506 if (ctx->len % 16 != 0) {
507 gcm_mult(ctx, ctx->buf, ctx->buf);
508 }
509
510 memcpy(tag, ctx->base_ectr, tag_len);
511
512 if (orig_len || orig_add_len) {
513 memset(work_buf, 0x00, 16);
514
515 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
516 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
517 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
518 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
519
520 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
521
522 gcm_mult(ctx, ctx->buf, ctx->buf);
523
524 mbedtls_xor(tag, tag, ctx->buf, tag_len);
525 }
526
527 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000528}
529
Gilles Peskine449bd832023-01-11 14:50:10 +0100530int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
531 int mode,
532 size_t length,
533 const unsigned char *iv,
534 size_t iv_len,
535 const unsigned char *add,
536 size_t add_len,
537 const unsigned char *input,
538 unsigned char *output,
539 size_t tag_len,
540 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200541{
Janos Follath24eed8d2019-11-22 13:21:35 +0000542 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200543 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200544
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
546 return ret;
547 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200548
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
550 return ret;
551 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200552
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 if ((ret = mbedtls_gcm_update(ctx, input, length,
554 output, length, &olen)) != 0) {
555 return ret;
556 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200557
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
559 return ret;
560 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200561
Gilles Peskine449bd832023-01-11 14:50:10 +0100562 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200563}
564
Gilles Peskine449bd832023-01-11 14:50:10 +0100565int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
566 size_t length,
567 const unsigned char *iv,
568 size_t iv_len,
569 const unsigned char *add,
570 size_t add_len,
571 const unsigned char *tag,
572 size_t tag_len,
573 const unsigned char *input,
574 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000575{
Janos Follath24eed8d2019-11-22 13:21:35 +0000576 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000577 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200578 size_t i;
579 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000580
Gilles Peskine449bd832023-01-11 14:50:10 +0100581 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
582 iv, iv_len, add, add_len,
583 input, output, tag_len, check_tag)) != 0) {
584 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100585 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000586
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200587 /* Check tag in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 for (diff = 0, i = 0; i < tag_len; i++) {
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200589 diff |= tag[i] ^ check_tag[i];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200590 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000591
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 if (diff != 0) {
593 mbedtls_platform_zeroize(output, length);
594 return MBEDTLS_ERR_GCM_AUTH_FAILED;
595 }
596
597 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000598}
599
Gilles Peskine449bd832023-01-11 14:50:10 +0100600void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200601{
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100603 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100604 }
605 mbedtls_cipher_free(&ctx->cipher_ctx);
606 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200607}
608
Jaeden Amero15263302017-09-21 12:53:48 +0100609#endif /* !MBEDTLS_GCM_ALT */
610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000612/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200613 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000614 *
615 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
616 */
617#define MAX_TESTS 6
618
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100619static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100620{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000621
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100622static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000623{
624 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
628 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
629 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
630 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200631 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000632};
633
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100634static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100635{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000636
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100637static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100638{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000639
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100640static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000641{
642 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00 },
644 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
645 0xde, 0xca, 0xf8, 0x88 },
646 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000654};
655
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100656static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100657{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000658
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100659static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100660{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000661
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100662static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000663{
664 { 0x00 },
665 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200666 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000667 0xab, 0xad, 0xda, 0xd2 },
668};
669
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100670static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100671{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000672
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100673static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100674{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000675
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100676static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000677{
678 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
680 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
681 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
682 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
683 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
684 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
685 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
686 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
687 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
688};
689
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100690static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000691{
692 { 0x00 },
693 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
694 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
695 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200696 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000697 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200698 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000699 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200700 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000701 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
702 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
703 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200704 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000705 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200706 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000707 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200708 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000709 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
710 0x3d, 0x58, 0xe0, 0x91 },
711 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200712 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000713 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200714 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000715 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
718 0xc2, 0x3f, 0x45, 0x98 },
719 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
726 0x4c, 0x34, 0xae, 0xe5 },
727 { 0x00 },
728 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200729 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000730 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200731 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000732 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200733 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000734 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200735 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000736 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
737 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
738 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200739 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000740 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200741 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
742 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
743 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000744 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200745 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000746 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200747 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000748 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200749 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000750 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200751 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000752 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200753 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000754 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200755 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000756 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200757 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000758 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200759 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000760 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200761 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000762 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200763 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
764 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
765 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
766 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
767 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
768 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
769 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
770 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
771 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
772 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
773 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
774 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
775 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
776 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
777 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
778 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
779 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
780 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000781 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200782 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000783 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200784 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000785 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200786 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000787 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200788 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000789 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200790 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000791 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200792 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000793 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200794 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000795 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200796 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000797};
798
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100799static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000800{
801 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
802 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
803 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
804 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
805 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200806 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000807 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
808 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
809 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
810 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
811 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
812 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
813 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
814 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
815 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200816 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000817 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
818 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
819 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200820 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000821 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200822 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000823 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200824 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000825 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200826 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000827 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200828 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000829 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200830 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000831 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200832 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000833 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200834 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000835 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200836 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000837};
838
Gilles Peskine449bd832023-01-11 14:50:10 +0100839int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000840{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000842 unsigned char buf[64];
843 unsigned char tag_buf[16];
844 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200845 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200846 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +0000847
Gilles Peskine449bd832023-01-11 14:50:10 +0100848 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000849 int key_len = 128 + 64 * j;
850
Gilles Peskine449bd832023-01-11 14:50:10 +0100851 for (i = 0; i < MAX_TESTS; i++) {
852 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100853
Gilles Peskine449bd832023-01-11 14:50:10 +0100854 if (verbose != 0) {
855 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
856 key_len, i, "enc");
857 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200858
Gilles Peskine449bd832023-01-11 14:50:10 +0100859 ret = mbedtls_gcm_setkey(&ctx, cipher,
860 key_test_data[key_index_test_data[i]],
861 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100862 /*
863 * AES-192 is an optional feature that may be unavailable when
864 * there is an alternative underlying implementation i.e. when
865 * MBEDTLS_AES_ALT is defined.
866 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100867 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
868 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100869 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100870 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100871 goto exit;
872 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000873
Gilles Peskine449bd832023-01-11 14:50:10 +0100874 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
875 pt_len_test_data[i],
876 iv_test_data[iv_index_test_data[i]],
877 iv_len_test_data[i],
878 additional_test_data[add_index_test_data[i]],
879 add_len_test_data[i],
880 pt_test_data[pt_index_test_data[i]],
881 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100882#if defined(MBEDTLS_GCM_ALT)
883 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100884 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
885 iv_len_test_data[i] != 12) {
886 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100887 break;
888 }
889#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100890 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100891 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100892 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000893
Gilles Peskine449bd832023-01-11 14:50:10 +0100894 if (memcmp(buf, ct_test_data[j * 6 + i],
895 pt_len_test_data[i]) != 0 ||
896 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100897 ret = 1;
898 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000899 }
900
Gilles Peskine449bd832023-01-11 14:50:10 +0100901 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200902
Gilles Peskine449bd832023-01-11 14:50:10 +0100903 if (verbose != 0) {
904 mbedtls_printf("passed\n");
905 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000906
Gilles Peskine449bd832023-01-11 14:50:10 +0100907 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100908
Gilles Peskine449bd832023-01-11 14:50:10 +0100909 if (verbose != 0) {
910 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
911 key_len, i, "dec");
912 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200913
Gilles Peskine449bd832023-01-11 14:50:10 +0100914 ret = mbedtls_gcm_setkey(&ctx, cipher,
915 key_test_data[key_index_test_data[i]],
916 key_len);
917 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100918 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100919 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000920
Gilles Peskine449bd832023-01-11 14:50:10 +0100921 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
922 pt_len_test_data[i],
923 iv_test_data[iv_index_test_data[i]],
924 iv_len_test_data[i],
925 additional_test_data[add_index_test_data[i]],
926 add_len_test_data[i],
927 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000928
Gilles Peskine449bd832023-01-11 14:50:10 +0100929 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100930 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100931 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100932
Gilles Peskine449bd832023-01-11 14:50:10 +0100933 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
934 pt_len_test_data[i]) != 0 ||
935 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100936 ret = 1;
937 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000938 }
939
Gilles Peskine449bd832023-01-11 14:50:10 +0100940 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200941
Gilles Peskine449bd832023-01-11 14:50:10 +0100942 if (verbose != 0) {
943 mbedtls_printf("passed\n");
944 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200945
Gilles Peskine449bd832023-01-11 14:50:10 +0100946 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100947
Gilles Peskine449bd832023-01-11 14:50:10 +0100948 if (verbose != 0) {
949 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
950 key_len, i, "enc");
951 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200952
Gilles Peskine449bd832023-01-11 14:50:10 +0100953 ret = mbedtls_gcm_setkey(&ctx, cipher,
954 key_test_data[key_index_test_data[i]],
955 key_len);
956 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100957 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100958 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200959
Gilles Peskine449bd832023-01-11 14:50:10 +0100960 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
961 iv_test_data[iv_index_test_data[i]],
962 iv_len_test_data[i]);
963 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +0200964 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100965 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200966
Gilles Peskine449bd832023-01-11 14:50:10 +0100967 ret = mbedtls_gcm_update_ad(&ctx,
968 additional_test_data[add_index_test_data[i]],
969 add_len_test_data[i]);
970 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100971 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100972 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200973
Gilles Peskine449bd832023-01-11 14:50:10 +0100974 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100975 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +0100976 ret = mbedtls_gcm_update(&ctx,
977 pt_test_data[pt_index_test_data[i]],
978 32,
979 buf, sizeof(buf), &olen);
980 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100981 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100982 }
983 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200984 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100985 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200986
Gilles Peskine449bd832023-01-11 14:50:10 +0100987 ret = mbedtls_gcm_update(&ctx,
988 pt_test_data[pt_index_test_data[i]] + 32,
989 rest_len,
990 buf + 32, sizeof(buf) - 32, &olen);
991 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100992 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100993 }
994 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200995 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100996 }
997 } else {
998 ret = mbedtls_gcm_update(&ctx,
999 pt_test_data[pt_index_test_data[i]],
1000 pt_len_test_data[i],
1001 buf, sizeof(buf), &olen);
1002 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001003 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001004 }
1005 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001006 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001007 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001008 }
1009
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1011 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001012 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001013 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001014
Gilles Peskine449bd832023-01-11 14:50:10 +01001015 if (memcmp(buf, ct_test_data[j * 6 + i],
1016 pt_len_test_data[i]) != 0 ||
1017 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001018 ret = 1;
1019 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001020 }
1021
Gilles Peskine449bd832023-01-11 14:50:10 +01001022 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001023
Gilles Peskine449bd832023-01-11 14:50:10 +01001024 if (verbose != 0) {
1025 mbedtls_printf("passed\n");
1026 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001027
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001029
Gilles Peskine449bd832023-01-11 14:50:10 +01001030 if (verbose != 0) {
1031 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1032 key_len, i, "dec");
1033 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001034
Gilles Peskine449bd832023-01-11 14:50:10 +01001035 ret = mbedtls_gcm_setkey(&ctx, cipher,
1036 key_test_data[key_index_test_data[i]],
1037 key_len);
1038 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001039 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001040 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001041
Gilles Peskine449bd832023-01-11 14:50:10 +01001042 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1043 iv_test_data[iv_index_test_data[i]],
1044 iv_len_test_data[i]);
1045 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001046 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001047 }
1048 ret = mbedtls_gcm_update_ad(&ctx,
1049 additional_test_data[add_index_test_data[i]],
1050 add_len_test_data[i]);
1051 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001052 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001053 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001054
Gilles Peskine449bd832023-01-11 14:50:10 +01001055 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001056 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001057 ret = mbedtls_gcm_update(&ctx,
1058 ct_test_data[j * 6 + i], 32,
1059 buf, sizeof(buf), &olen);
1060 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001061 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001062 }
1063 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001064 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001065 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001066
Gilles Peskine449bd832023-01-11 14:50:10 +01001067 ret = mbedtls_gcm_update(&ctx,
1068 ct_test_data[j * 6 + i] + 32,
1069 rest_len,
1070 buf + 32, sizeof(buf) - 32, &olen);
1071 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001072 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001073 }
1074 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001075 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001076 }
1077 } else {
1078 ret = mbedtls_gcm_update(&ctx,
1079 ct_test_data[j * 6 + i],
1080 pt_len_test_data[i],
1081 buf, sizeof(buf), &olen);
1082 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001083 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001084 }
1085 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001086 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001087 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001088 }
1089
Gilles Peskine449bd832023-01-11 14:50:10 +01001090 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1091 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001092 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001093 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001094
Gilles Peskine449bd832023-01-11 14:50:10 +01001095 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1096 pt_len_test_data[i]) != 0 ||
1097 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001098 ret = 1;
1099 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001100 }
1101
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001103
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 if (verbose != 0) {
1105 mbedtls_printf("passed\n");
1106 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001107 }
1108 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001109
Gilles Peskine449bd832023-01-11 14:50:10 +01001110 if (verbose != 0) {
1111 mbedtls_printf("\n");
1112 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001113
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001114 ret = 0;
1115
1116exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001117 if (ret != 0) {
1118 if (verbose != 0) {
1119 mbedtls_printf("failed\n");
1120 }
1121 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001122 }
1123
Gilles Peskine449bd832023-01-11 14:50:10 +01001124 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001125}
1126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129#endif /* MBEDTLS_GCM_C */