blob: 4e8ec088150b11c044d233d41221bfb90829f0fa [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
Gilles Peskine9af58cd2023-03-10 22:29:32 +010089#if defined(MBEDTLS_AESNI_HAVE_CODE)
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
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100186#if defined(MBEDTLS_AESNI_HAVE_CODE)
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 }
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100198#endif /* MBEDTLS_AESNI_HAVE_CODE */
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 Peskine7e67bd52023-03-10 22:35:24 +0100848 if (verbose != 0)
849 {
850#if defined(MBEDTLS_GCM_ALT)
851 mbedtls_printf(" GCM note: alternative implementation.\n");
852#else /* MBEDTLS_GCM_ALT */
853#if defined(MBEDTLS_AESNI_HAVE_CODE)
854 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
855 mbedtls_printf(" GCM note: using AESNI.\n");
856 } else
857#endif
858 mbedtls_printf(" GCM note: built-in implementation.\n");
859#endif /* MBEDTLS_GCM_ALT */
860 }
861
Gilles Peskine449bd832023-01-11 14:50:10 +0100862 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000863 int key_len = 128 + 64 * j;
864
Gilles Peskine449bd832023-01-11 14:50:10 +0100865 for (i = 0; i < MAX_TESTS; i++) {
866 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100867
Gilles Peskine449bd832023-01-11 14:50:10 +0100868 if (verbose != 0) {
869 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
870 key_len, i, "enc");
871 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200872
Gilles Peskine449bd832023-01-11 14:50:10 +0100873 ret = mbedtls_gcm_setkey(&ctx, cipher,
874 key_test_data[key_index_test_data[i]],
875 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100876 /*
877 * AES-192 is an optional feature that may be unavailable when
878 * there is an alternative underlying implementation i.e. when
879 * MBEDTLS_AES_ALT is defined.
880 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100881 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
882 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100883 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100884 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100885 goto exit;
886 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000887
Gilles Peskine449bd832023-01-11 14:50:10 +0100888 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
889 pt_len_test_data[i],
890 iv_test_data[iv_index_test_data[i]],
891 iv_len_test_data[i],
892 additional_test_data[add_index_test_data[i]],
893 add_len_test_data[i],
894 pt_test_data[pt_index_test_data[i]],
895 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100896#if defined(MBEDTLS_GCM_ALT)
897 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100898 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
899 iv_len_test_data[i] != 12) {
900 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100901 break;
902 }
903#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100904 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100905 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100906 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000907
Gilles Peskine449bd832023-01-11 14:50:10 +0100908 if (memcmp(buf, ct_test_data[j * 6 + i],
909 pt_len_test_data[i]) != 0 ||
910 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100911 ret = 1;
912 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000913 }
914
Gilles Peskine449bd832023-01-11 14:50:10 +0100915 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200916
Gilles Peskine449bd832023-01-11 14:50:10 +0100917 if (verbose != 0) {
918 mbedtls_printf("passed\n");
919 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000920
Gilles Peskine449bd832023-01-11 14:50:10 +0100921 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100922
Gilles Peskine449bd832023-01-11 14:50:10 +0100923 if (verbose != 0) {
924 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
925 key_len, i, "dec");
926 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200927
Gilles Peskine449bd832023-01-11 14:50:10 +0100928 ret = mbedtls_gcm_setkey(&ctx, cipher,
929 key_test_data[key_index_test_data[i]],
930 key_len);
931 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100932 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100933 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000934
Gilles Peskine449bd832023-01-11 14:50:10 +0100935 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
936 pt_len_test_data[i],
937 iv_test_data[iv_index_test_data[i]],
938 iv_len_test_data[i],
939 additional_test_data[add_index_test_data[i]],
940 add_len_test_data[i],
941 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000942
Gilles Peskine449bd832023-01-11 14:50:10 +0100943 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100944 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100945 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100946
Gilles Peskine449bd832023-01-11 14:50:10 +0100947 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
948 pt_len_test_data[i]) != 0 ||
949 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100950 ret = 1;
951 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000952 }
953
Gilles Peskine449bd832023-01-11 14:50:10 +0100954 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200955
Gilles Peskine449bd832023-01-11 14:50:10 +0100956 if (verbose != 0) {
957 mbedtls_printf("passed\n");
958 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200959
Gilles Peskine449bd832023-01-11 14:50:10 +0100960 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100961
Gilles Peskine449bd832023-01-11 14:50:10 +0100962 if (verbose != 0) {
963 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
964 key_len, i, "enc");
965 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200966
Gilles Peskine449bd832023-01-11 14:50:10 +0100967 ret = mbedtls_gcm_setkey(&ctx, cipher,
968 key_test_data[key_index_test_data[i]],
969 key_len);
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 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
975 iv_test_data[iv_index_test_data[i]],
976 iv_len_test_data[i]);
977 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +0200978 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100979 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200980
Gilles Peskine449bd832023-01-11 14:50:10 +0100981 ret = mbedtls_gcm_update_ad(&ctx,
982 additional_test_data[add_index_test_data[i]],
983 add_len_test_data[i]);
984 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100985 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100986 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200987
Gilles Peskine449bd832023-01-11 14:50:10 +0100988 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100989 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +0100990 ret = mbedtls_gcm_update(&ctx,
991 pt_test_data[pt_index_test_data[i]],
992 32,
993 buf, sizeof(buf), &olen);
994 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100995 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100996 }
997 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200998 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100999 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001000
Gilles Peskine449bd832023-01-11 14:50:10 +01001001 ret = mbedtls_gcm_update(&ctx,
1002 pt_test_data[pt_index_test_data[i]] + 32,
1003 rest_len,
1004 buf + 32, sizeof(buf) - 32, &olen);
1005 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001006 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001007 }
1008 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001009 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 }
1011 } else {
1012 ret = mbedtls_gcm_update(&ctx,
1013 pt_test_data[pt_index_test_data[i]],
1014 pt_len_test_data[i],
1015 buf, sizeof(buf), &olen);
1016 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001017 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001018 }
1019 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001020 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001021 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001022 }
1023
Gilles Peskine449bd832023-01-11 14:50:10 +01001024 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1025 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001026 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001027 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001028
Gilles Peskine449bd832023-01-11 14:50:10 +01001029 if (memcmp(buf, ct_test_data[j * 6 + i],
1030 pt_len_test_data[i]) != 0 ||
1031 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001032 ret = 1;
1033 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001034 }
1035
Gilles Peskine449bd832023-01-11 14:50:10 +01001036 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001037
Gilles Peskine449bd832023-01-11 14:50:10 +01001038 if (verbose != 0) {
1039 mbedtls_printf("passed\n");
1040 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001041
Gilles Peskine449bd832023-01-11 14:50:10 +01001042 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001043
Gilles Peskine449bd832023-01-11 14:50:10 +01001044 if (verbose != 0) {
1045 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1046 key_len, i, "dec");
1047 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001048
Gilles Peskine449bd832023-01-11 14:50:10 +01001049 ret = mbedtls_gcm_setkey(&ctx, cipher,
1050 key_test_data[key_index_test_data[i]],
1051 key_len);
1052 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001053 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001054 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001055
Gilles Peskine449bd832023-01-11 14:50:10 +01001056 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1057 iv_test_data[iv_index_test_data[i]],
1058 iv_len_test_data[i]);
1059 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001060 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001061 }
1062 ret = mbedtls_gcm_update_ad(&ctx,
1063 additional_test_data[add_index_test_data[i]],
1064 add_len_test_data[i]);
1065 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001066 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001067 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001068
Gilles Peskine449bd832023-01-11 14:50:10 +01001069 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001070 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001071 ret = mbedtls_gcm_update(&ctx,
1072 ct_test_data[j * 6 + i], 32,
1073 buf, sizeof(buf), &olen);
1074 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001075 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001076 }
1077 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001078 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001080
Gilles Peskine449bd832023-01-11 14:50:10 +01001081 ret = mbedtls_gcm_update(&ctx,
1082 ct_test_data[j * 6 + i] + 32,
1083 rest_len,
1084 buf + 32, sizeof(buf) - 32, &olen);
1085 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001086 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001087 }
1088 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001089 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001090 }
1091 } else {
1092 ret = mbedtls_gcm_update(&ctx,
1093 ct_test_data[j * 6 + i],
1094 pt_len_test_data[i],
1095 buf, sizeof(buf), &olen);
1096 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001097 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001098 }
1099 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001100 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001101 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001102 }
1103
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1105 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001106 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001107 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001108
Gilles Peskine449bd832023-01-11 14:50:10 +01001109 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1110 pt_len_test_data[i]) != 0 ||
1111 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001112 ret = 1;
1113 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001114 }
1115
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001117
Gilles Peskine449bd832023-01-11 14:50:10 +01001118 if (verbose != 0) {
1119 mbedtls_printf("passed\n");
1120 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001121 }
1122 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001123
Gilles Peskine449bd832023-01-11 14:50:10 +01001124 if (verbose != 0) {
1125 mbedtls_printf("\n");
1126 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001127
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001128 ret = 0;
1129
1130exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001131 if (ret != 0) {
1132 if (verbose != 0) {
1133 mbedtls_printf("failed\n");
1134 }
1135 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001136 }
1137
Gilles Peskine449bd832023-01-11 14:50:10 +01001138 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001139}
1140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143#endif /* MBEDTLS_GCM_C */