blob: 968e7175fbe2e99488356b0d39f3d957494b4033 [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 Peskine0cd9ab72023-03-16 13:06:14 +0100848 if (verbose != 0) {
Gilles Peskine7e67bd52023-03-10 22:35:24 +0100849#if defined(MBEDTLS_GCM_ALT)
850 mbedtls_printf(" GCM note: alternative implementation.\n");
851#else /* MBEDTLS_GCM_ALT */
852#if defined(MBEDTLS_AESNI_HAVE_CODE)
853 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
854 mbedtls_printf(" GCM note: using AESNI.\n");
855 } else
856#endif
857 mbedtls_printf(" GCM note: built-in implementation.\n");
858#endif /* MBEDTLS_GCM_ALT */
859 }
860
Gilles Peskine449bd832023-01-11 14:50:10 +0100861 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000862 int key_len = 128 + 64 * j;
863
Gilles Peskine449bd832023-01-11 14:50:10 +0100864 for (i = 0; i < MAX_TESTS; i++) {
865 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100866
Gilles Peskine449bd832023-01-11 14:50:10 +0100867 if (verbose != 0) {
868 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
869 key_len, i, "enc");
870 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200871
Gilles Peskine449bd832023-01-11 14:50:10 +0100872 ret = mbedtls_gcm_setkey(&ctx, cipher,
873 key_test_data[key_index_test_data[i]],
874 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100875 /*
876 * AES-192 is an optional feature that may be unavailable when
877 * there is an alternative underlying implementation i.e. when
878 * MBEDTLS_AES_ALT is defined.
879 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100880 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
881 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100882 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100883 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100884 goto exit;
885 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000886
Gilles Peskine449bd832023-01-11 14:50:10 +0100887 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
888 pt_len_test_data[i],
889 iv_test_data[iv_index_test_data[i]],
890 iv_len_test_data[i],
891 additional_test_data[add_index_test_data[i]],
892 add_len_test_data[i],
893 pt_test_data[pt_index_test_data[i]],
894 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100895#if defined(MBEDTLS_GCM_ALT)
896 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100897 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
898 iv_len_test_data[i] != 12) {
899 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100900 break;
901 }
902#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100903 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100904 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100905 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000906
Gilles Peskine449bd832023-01-11 14:50:10 +0100907 if (memcmp(buf, ct_test_data[j * 6 + i],
908 pt_len_test_data[i]) != 0 ||
909 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100910 ret = 1;
911 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000912 }
913
Gilles Peskine449bd832023-01-11 14:50:10 +0100914 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200915
Gilles Peskine449bd832023-01-11 14:50:10 +0100916 if (verbose != 0) {
917 mbedtls_printf("passed\n");
918 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000919
Gilles Peskine449bd832023-01-11 14:50:10 +0100920 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100921
Gilles Peskine449bd832023-01-11 14:50:10 +0100922 if (verbose != 0) {
923 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
924 key_len, i, "dec");
925 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200926
Gilles Peskine449bd832023-01-11 14:50:10 +0100927 ret = mbedtls_gcm_setkey(&ctx, cipher,
928 key_test_data[key_index_test_data[i]],
929 key_len);
930 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100931 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100932 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000933
Gilles Peskine449bd832023-01-11 14:50:10 +0100934 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
935 pt_len_test_data[i],
936 iv_test_data[iv_index_test_data[i]],
937 iv_len_test_data[i],
938 additional_test_data[add_index_test_data[i]],
939 add_len_test_data[i],
940 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000941
Gilles Peskine449bd832023-01-11 14:50:10 +0100942 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100943 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100944 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100945
Gilles Peskine449bd832023-01-11 14:50:10 +0100946 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
947 pt_len_test_data[i]) != 0 ||
948 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100949 ret = 1;
950 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000951 }
952
Gilles Peskine449bd832023-01-11 14:50:10 +0100953 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200954
Gilles Peskine449bd832023-01-11 14:50:10 +0100955 if (verbose != 0) {
956 mbedtls_printf("passed\n");
957 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200958
Gilles Peskine449bd832023-01-11 14:50:10 +0100959 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100960
Gilles Peskine449bd832023-01-11 14:50:10 +0100961 if (verbose != 0) {
962 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
963 key_len, i, "enc");
964 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200965
Gilles Peskine449bd832023-01-11 14:50:10 +0100966 ret = mbedtls_gcm_setkey(&ctx, cipher,
967 key_test_data[key_index_test_data[i]],
968 key_len);
969 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100970 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100971 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200972
Gilles Peskine449bd832023-01-11 14:50:10 +0100973 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
974 iv_test_data[iv_index_test_data[i]],
975 iv_len_test_data[i]);
976 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +0200977 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100978 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200979
Gilles Peskine449bd832023-01-11 14:50:10 +0100980 ret = mbedtls_gcm_update_ad(&ctx,
981 additional_test_data[add_index_test_data[i]],
982 add_len_test_data[i]);
983 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100984 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 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100988 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +0100989 ret = mbedtls_gcm_update(&ctx,
990 pt_test_data[pt_index_test_data[i]],
991 32,
992 buf, sizeof(buf), &olen);
993 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100994 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100995 }
996 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200997 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100998 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200999
Gilles Peskine449bd832023-01-11 14:50:10 +01001000 ret = mbedtls_gcm_update(&ctx,
1001 pt_test_data[pt_index_test_data[i]] + 32,
1002 rest_len,
1003 buf + 32, sizeof(buf) - 32, &olen);
1004 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001005 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001006 }
1007 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001008 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001009 }
1010 } else {
1011 ret = mbedtls_gcm_update(&ctx,
1012 pt_test_data[pt_index_test_data[i]],
1013 pt_len_test_data[i],
1014 buf, sizeof(buf), &olen);
1015 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001016 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001017 }
1018 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001019 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001020 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001021 }
1022
Gilles Peskine449bd832023-01-11 14:50:10 +01001023 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1024 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001025 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001026 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001027
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 if (memcmp(buf, ct_test_data[j * 6 + i],
1029 pt_len_test_data[i]) != 0 ||
1030 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001031 ret = 1;
1032 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001033 }
1034
Gilles Peskine449bd832023-01-11 14:50:10 +01001035 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001036
Gilles Peskine449bd832023-01-11 14:50:10 +01001037 if (verbose != 0) {
1038 mbedtls_printf("passed\n");
1039 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001040
Gilles Peskine449bd832023-01-11 14:50:10 +01001041 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001042
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 if (verbose != 0) {
1044 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1045 key_len, i, "dec");
1046 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001047
Gilles Peskine449bd832023-01-11 14:50:10 +01001048 ret = mbedtls_gcm_setkey(&ctx, cipher,
1049 key_test_data[key_index_test_data[i]],
1050 key_len);
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 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1056 iv_test_data[iv_index_test_data[i]],
1057 iv_len_test_data[i]);
1058 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001059 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 }
1061 ret = mbedtls_gcm_update_ad(&ctx,
1062 additional_test_data[add_index_test_data[i]],
1063 add_len_test_data[i]);
1064 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001065 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001066 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001067
Gilles Peskine449bd832023-01-11 14:50:10 +01001068 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001069 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001070 ret = mbedtls_gcm_update(&ctx,
1071 ct_test_data[j * 6 + i], 32,
1072 buf, sizeof(buf), &olen);
1073 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001074 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001075 }
1076 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001077 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001078 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001079
Gilles Peskine449bd832023-01-11 14:50:10 +01001080 ret = mbedtls_gcm_update(&ctx,
1081 ct_test_data[j * 6 + i] + 32,
1082 rest_len,
1083 buf + 32, sizeof(buf) - 32, &olen);
1084 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001085 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 }
1087 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001088 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001089 }
1090 } else {
1091 ret = mbedtls_gcm_update(&ctx,
1092 ct_test_data[j * 6 + i],
1093 pt_len_test_data[i],
1094 buf, sizeof(buf), &olen);
1095 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001096 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001097 }
1098 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001099 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001100 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001101 }
1102
Gilles Peskine449bd832023-01-11 14:50:10 +01001103 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1104 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001105 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001107
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1109 pt_len_test_data[i]) != 0 ||
1110 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001111 ret = 1;
1112 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001113 }
1114
Gilles Peskine449bd832023-01-11 14:50:10 +01001115 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001116
Gilles Peskine449bd832023-01-11 14:50:10 +01001117 if (verbose != 0) {
1118 mbedtls_printf("passed\n");
1119 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001120 }
1121 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001122
Gilles Peskine449bd832023-01-11 14:50:10 +01001123 if (verbose != 0) {
1124 mbedtls_printf("\n");
1125 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001126
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001127 ret = 0;
1128
1129exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001130 if (ret != 0) {
1131 if (verbose != 0) {
1132 mbedtls_printf("failed\n");
1133 }
1134 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001135 }
1136
Gilles Peskine449bd832023-01-11 14:50:10 +01001137 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001138}
1139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001140#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001142#endif /* MBEDTLS_GCM_C */