blob: 6d4495fd39431a3085e9acd4a6015538482342af [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker89e80c92012-03-20 13:50:09 +000018 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010019
Paul Bakker89e80c92012-03-20 13:50:09 +000020/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010021 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
22 *
23 * See also:
24 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
25 *
26 * We use the algorithm described as Shoup's method with 4-bit tables in
27 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000028 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010029
Gilles Peskinedb09ef62020-06-03 01:43:33 +020030#include "common.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/gcm.h"
Gilles Peskineed1c7f42022-09-15 20:14:22 +020035#include "mbedtls/platform.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050036#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000037#include "mbedtls/error.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_AESNI_C)
Chris Jones187782f2021-03-09 17:28:35 +000042#include "aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010043#endif
44
Jaeden Amero15263302017-09-21 12:53:48 +010045#if !defined(MBEDTLS_GCM_ALT)
46
Paul Bakker89e80c92012-03-20 13:50:09 +000047/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020048 * Initialize a context
49 */
David Horstmann71159f42023-01-03 12:51:59 +000050void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020051{
David Horstmann71159f42023-01-03 12:51:59 +000052 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 */
David Horstmann71159f42023-01-03 12:51:59 +000063static 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
David Horstmann71159f42023-01-03 12:51:59 +000071 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 */
David Horstmann71159f42023-01-03 12:51:59 +000077 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
David Horstmann71159f42023-01-03 12:51:59 +000081 hi = MBEDTLS_GET_UINT32_BE(h, 8);
82 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +000083 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020084
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010085 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000086 ctx->HL[8] = vl;
87 ctx->HH[8] = vh;
88
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010090 /* With CLMUL support, we need only h, not the rest of the table */
David Horstmann71159f42023-01-03 12:51:59 +000091 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
David Horstmann71159f42023-01-03 12:51:59 +0000100 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
David Horstmann71159f42023-01-03 12:51:59 +0000109 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;
David Horstmann71159f42023-01-03 12:51:59 +0000113 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
David Horstmann71159f42023-01-03 12:51:59 +0000119 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000120}
121
David Horstmann71159f42023-01-03 12:51:59 +0000122int 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
David Horstmann71159f42023-01-03 12:51:59 +0000130 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
David Horstmann71159f42023-01-03 12:51:59 +0000134 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
David Horstmann71159f42023-01-03 12:51:59 +0000140 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 */
David Horstmann71159f42023-01-03 12:51:59 +0000179static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
180 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000181{
182 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000183 unsigned char lo, hi, rem;
184 uint64_t zh, zl;
185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
David Horstmann71159f42023-01-03 12:51:59 +0000187 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100188 unsigned char h[16];
189
David Horstmann71159f42023-01-03 12:51:59 +0000190 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
David Horstmann71159f42023-01-03 12:51:59 +0000195 mbedtls_aesni_gcm_mult(output, x, h);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100196 return;
197 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100199
Paul Bakker89e80c92012-03-20 13:50:09 +0000200 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000201
202 zh = ctx->HH[lo];
203 zl = ctx->HL[lo];
204
David Horstmann71159f42023-01-03 12:51:59 +0000205 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000206 lo = x[i] & 0xf;
David Horstmann71159f42023-01-03 12:51:59 +0000207 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000208
David Horstmann71159f42023-01-03 12:51:59 +0000209 if (i != 15) {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000210 rem = (unsigned char) zl & 0xf;
David Horstmann71159f42023-01-03 12:51:59 +0000211 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;
David Horstmann71159f42023-01-03 12:51:59 +0000220 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
David Horstmann71159f42023-01-03 12:51:59 +0000227 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
David Horstmann71159f42023-01-03 12:51:59 +0000233int 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 */
David Horstmann71159f42023-01-03 12:51:59 +0000245 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
David Horstmann71159f42023-01-03 12:51:59 +0000249 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
David Horstmann71159f42023-01-03 12:51:59 +0000256 if (iv_len == 12) {
257 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200258 ctx->y[15] = 1;
David Horstmann71159f42023-01-03 12:51:59 +0000259 } 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;
David Horstmann71159f42023-01-03 12:51:59 +0000265 while (iv_len > 0) {
266 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000267
David Horstmann71159f42023-01-03 12:51:59 +0000268 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200269
David Horstmann71159f42023-01-03 12:51:59 +0000270 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
David Horstmann71159f42023-01-03 12:51:59 +0000276 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000277
David Horstmann71159f42023-01-03 12:51:59 +0000278 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000279 }
280
David Horstmann71159f42023-01-03 12:51:59 +0000281 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
David Horstmann71159f42023-01-03 12:51:59 +0000286 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 */
David Horstmann71159f42023-01-03 12:51:59 +0000306int 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 */
David Horstmann71159f42023-01-03 12:51:59 +0000313 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
David Horstmann71159f42023-01-03 12:51:59 +0000320 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200321 use_len = 16 - offset;
David Horstmann71159f42023-01-03 12:51:59 +0000322 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200323 use_len = add_len;
David Horstmann71159f42023-01-03 12:51:59 +0000324 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200325
David Horstmann71159f42023-01-03 12:51:59 +0000326 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200327
David Horstmann71159f42023-01-03 12:51:59 +0000328 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
David Horstmann71159f42023-01-03 12:51:59 +0000339 while (add_len >= 16) {
340 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200341
David Horstmann71159f42023-01-03 12:51:59 +0000342 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
David Horstmann71159f42023-01-03 12:51:59 +0000348 if (add_len > 0) {
349 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200350 }
351
David Horstmann71159f42023-01-03 12:51:59 +0000352 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200353}
354
Gilles Peskine58fc2722021-04-13 15:58:27 +0200355/* Increment the counter. */
David Horstmann71159f42023-01-03 12:51:59 +0000356static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200357{
358 size_t i;
David Horstmann71159f42023-01-03 12:51:59 +0000359 for (i = 16; i > 12; i--) {
360 if (++y[i - 1] != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200361 break;
David Horstmann71159f42023-01-03 12:51:59 +0000362 }
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. */
David Horstmann71159f42023-01-03 12:51:59 +0000368static 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
David Horstmann71159f42023-01-03 12:51:59 +0000377 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
David Horstmann71159f42023-01-03 12:51:59 +0000383 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
David Horstmann71159f42023-01-03 12:51:59 +0000391 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200392}
393
David Horstmann71159f42023-01-03 12:51:59 +0000394int 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;
David Horstmann71159f42023-01-03 12:51:59 +0000403 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200404
David Horstmann71159f42023-01-03 12:51:59 +0000405 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 */
David Horstmann71159f42023-01-03 12:51:59 +0000414 if (input_length == 0) {
415 return 0;
416 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200417
David Horstmann71159f42023-01-03 12:51:59 +0000418 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 */
David Horstmann71159f42023-01-03 12:51:59 +0000424 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
David Horstmann71159f42023-01-03 12:51:59 +0000429 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;
David Horstmann71159f42023-01-03 12:51:59 +0000434 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200435 size_t use_len = 16 - offset;
David Horstmann71159f42023-01-03 12:51:59 +0000436 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200437 use_len = input_length;
David Horstmann71159f42023-01-03 12:51:59 +0000438 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000439
David Horstmann71159f42023-01-03 12:51:59 +0000440 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
David Horstmann71159f42023-01-03 12:51:59 +0000444 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
David Horstmann71159f42023-01-03 12:51:59 +0000456 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
David Horstmann71159f42023-01-03 12:51:59 +0000462 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
David Horstmann71159f42023-01-03 12:51:59 +0000469 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
David Horstmann71159f42023-01-03 12:51:59 +0000476 mbedtls_platform_zeroize(ectr, sizeof(ectr));
477 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200478}
479
David Horstmann71159f42023-01-03 12:51:59 +0000480int 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
David Horstmann71159f42023-01-03 12:51:59 +0000498 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
David Horstmann71159f42023-01-03 12:51:59 +0000502 if (tag_len > 16 || tag_len < 4) {
503 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000504 }
505
David Horstmann71159f42023-01-03 12:51:59 +0000506 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
David Horstmann71159f42023-01-03 12:51:59 +0000530int 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
David Horstmann71159f42023-01-03 12:51:59 +0000545 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
546 return ret;
547 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200548
David Horstmann71159f42023-01-03 12:51:59 +0000549 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
550 return ret;
551 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200552
David Horstmann71159f42023-01-03 12:51:59 +0000553 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
David Horstmann71159f42023-01-03 12:51:59 +0000558 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
David Horstmann71159f42023-01-03 12:51:59 +0000562 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200563}
564
David Horstmann71159f42023-01-03 12:51:59 +0000565int 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
David Horstmann71159f42023-01-03 12:51:59 +0000581 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" */
David Horstmann71159f42023-01-03 12:51:59 +0000588 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
David Horstmann71159f42023-01-03 12:51:59 +0000592 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
David Horstmann71159f42023-01-03 12:51:59 +0000600void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200601{
David Horstmann71159f42023-01-03 12:51:59 +0000602 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100603 return;
David Horstmann71159f42023-01-03 12:51:59 +0000604 }
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] =
David Horstmann71159f42023-01-03 12:51:59 +0000620{ 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] =
David Horstmann71159f42023-01-03 12:51:59 +0000635{ 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] =
David Horstmann71159f42023-01-03 12:51:59 +0000638{ 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] =
David Horstmann71159f42023-01-03 12:51:59 +0000657{ 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] =
David Horstmann71159f42023-01-03 12:51:59 +0000660{ 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] =
David Horstmann71159f42023-01-03 12:51:59 +0000671{ 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] =
David Horstmann71159f42023-01-03 12:51:59 +0000674{ 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
David Horstmann71159f42023-01-03 12:51:59 +0000839int 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
David Horstmann71159f42023-01-03 12:51:59 +0000848 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000849 int key_len = 128 + 64 * j;
850
David Horstmann71159f42023-01-03 12:51:59 +0000851 for (i = 0; i < MAX_TESTS; i++) {
852 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100853
David Horstmann71159f42023-01-03 12:51:59 +0000854 if (verbose != 0) {
855 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
856 key_len, i, "enc");
857 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200858
David Horstmann71159f42023-01-03 12:51:59 +0000859 ret = mbedtls_gcm_setkey(&ctx, cipher,
860 key_test_data[key_index_test_data[i]],
861 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100862 /*
863 * AES-192 is an optional feature that may be unavailable when
864 * there is an alternative underlying implementation i.e. when
865 * MBEDTLS_AES_ALT is defined.
866 */
David Horstmann71159f42023-01-03 12:51:59 +0000867 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
868 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100869 break;
David Horstmann71159f42023-01-03 12:51:59 +0000870 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100871 goto exit;
872 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000873
David Horstmann71159f42023-01-03 12:51:59 +0000874 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
875 pt_len_test_data[i],
876 iv_test_data[iv_index_test_data[i]],
877 iv_len_test_data[i],
878 additional_test_data[add_index_test_data[i]],
879 add_len_test_data[i],
880 pt_test_data[pt_index_test_data[i]],
881 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100882#if defined(MBEDTLS_GCM_ALT)
883 /* Allow alternative implementations to only support 12-byte nonces. */
David Horstmann71159f42023-01-03 12:51:59 +0000884 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
885 iv_len_test_data[i] != 12) {
886 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100887 break;
888 }
889#endif /* defined(MBEDTLS_GCM_ALT) */
David Horstmann71159f42023-01-03 12:51:59 +0000890 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100891 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000892 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000893
David Horstmann71159f42023-01-03 12:51:59 +0000894 if (memcmp(buf, ct_test_data[j * 6 + i],
895 pt_len_test_data[i]) != 0 ||
896 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100897 ret = 1;
898 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000899 }
900
David Horstmann71159f42023-01-03 12:51:59 +0000901 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200902
David Horstmann71159f42023-01-03 12:51:59 +0000903 if (verbose != 0) {
904 mbedtls_printf("passed\n");
905 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000906
David Horstmann71159f42023-01-03 12:51:59 +0000907 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100908
David Horstmann71159f42023-01-03 12:51:59 +0000909 if (verbose != 0) {
910 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
911 key_len, i, "dec");
912 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200913
David Horstmann71159f42023-01-03 12:51:59 +0000914 ret = mbedtls_gcm_setkey(&ctx, cipher,
915 key_test_data[key_index_test_data[i]],
916 key_len);
917 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100918 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000919 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000920
David Horstmann71159f42023-01-03 12:51:59 +0000921 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
922 pt_len_test_data[i],
923 iv_test_data[iv_index_test_data[i]],
924 iv_len_test_data[i],
925 additional_test_data[add_index_test_data[i]],
926 add_len_test_data[i],
927 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000928
David Horstmann71159f42023-01-03 12:51:59 +0000929 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100930 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000931 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100932
David Horstmann71159f42023-01-03 12:51:59 +0000933 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
934 pt_len_test_data[i]) != 0 ||
935 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100936 ret = 1;
937 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000938 }
939
David Horstmann71159f42023-01-03 12:51:59 +0000940 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200941
David Horstmann71159f42023-01-03 12:51:59 +0000942 if (verbose != 0) {
943 mbedtls_printf("passed\n");
944 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200945
David Horstmann71159f42023-01-03 12:51:59 +0000946 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100947
David Horstmann71159f42023-01-03 12:51:59 +0000948 if (verbose != 0) {
949 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
950 key_len, i, "enc");
951 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200952
David Horstmann71159f42023-01-03 12:51:59 +0000953 ret = mbedtls_gcm_setkey(&ctx, cipher,
954 key_test_data[key_index_test_data[i]],
955 key_len);
956 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100957 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000958 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200959
David Horstmann71159f42023-01-03 12:51:59 +0000960 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
961 iv_test_data[iv_index_test_data[i]],
962 iv_len_test_data[i]);
963 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +0200964 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000965 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200966
David Horstmann71159f42023-01-03 12:51:59 +0000967 ret = mbedtls_gcm_update_ad(&ctx,
968 additional_test_data[add_index_test_data[i]],
969 add_len_test_data[i]);
970 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100971 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000972 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200973
David Horstmann71159f42023-01-03 12:51:59 +0000974 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100975 size_t rest_len = pt_len_test_data[i] - 32;
David Horstmann71159f42023-01-03 12:51:59 +0000976 ret = mbedtls_gcm_update(&ctx,
977 pt_test_data[pt_index_test_data[i]],
978 32,
979 buf, sizeof(buf), &olen);
980 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100981 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000982 }
983 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200984 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000985 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200986
David Horstmann71159f42023-01-03 12:51:59 +0000987 ret = mbedtls_gcm_update(&ctx,
988 pt_test_data[pt_index_test_data[i]] + 32,
989 rest_len,
990 buf + 32, sizeof(buf) - 32, &olen);
991 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100992 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000993 }
994 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200995 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +0000996 }
997 } else {
998 ret = mbedtls_gcm_update(&ctx,
999 pt_test_data[pt_index_test_data[i]],
1000 pt_len_test_data[i],
1001 buf, sizeof(buf), &olen);
1002 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001003 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001004 }
1005 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001006 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001007 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001008 }
1009
David Horstmann71159f42023-01-03 12:51:59 +00001010 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1011 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001012 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001013 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001014
David Horstmann71159f42023-01-03 12:51:59 +00001015 if (memcmp(buf, ct_test_data[j * 6 + i],
1016 pt_len_test_data[i]) != 0 ||
1017 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001018 ret = 1;
1019 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001020 }
1021
David Horstmann71159f42023-01-03 12:51:59 +00001022 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001023
David Horstmann71159f42023-01-03 12:51:59 +00001024 if (verbose != 0) {
1025 mbedtls_printf("passed\n");
1026 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001027
David Horstmann71159f42023-01-03 12:51:59 +00001028 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001029
David Horstmann71159f42023-01-03 12:51:59 +00001030 if (verbose != 0) {
1031 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1032 key_len, i, "dec");
1033 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001034
David Horstmann71159f42023-01-03 12:51:59 +00001035 ret = mbedtls_gcm_setkey(&ctx, cipher,
1036 key_test_data[key_index_test_data[i]],
1037 key_len);
1038 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001039 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001040 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001041
David Horstmann71159f42023-01-03 12:51:59 +00001042 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1043 iv_test_data[iv_index_test_data[i]],
1044 iv_len_test_data[i]);
1045 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001046 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001047 }
1048 ret = mbedtls_gcm_update_ad(&ctx,
1049 additional_test_data[add_index_test_data[i]],
1050 add_len_test_data[i]);
1051 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001052 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001053 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001054
David Horstmann71159f42023-01-03 12:51:59 +00001055 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001056 size_t rest_len = pt_len_test_data[i] - 32;
David Horstmann71159f42023-01-03 12:51:59 +00001057 ret = mbedtls_gcm_update(&ctx,
1058 ct_test_data[j * 6 + i], 32,
1059 buf, sizeof(buf), &olen);
1060 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001061 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001062 }
1063 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001064 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001065 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001066
David Horstmann71159f42023-01-03 12:51:59 +00001067 ret = mbedtls_gcm_update(&ctx,
1068 ct_test_data[j * 6 + i] + 32,
1069 rest_len,
1070 buf + 32, sizeof(buf) - 32, &olen);
1071 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001072 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001073 }
1074 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001075 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001076 }
1077 } else {
1078 ret = mbedtls_gcm_update(&ctx,
1079 ct_test_data[j * 6 + i],
1080 pt_len_test_data[i],
1081 buf, sizeof(buf), &olen);
1082 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001083 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001084 }
1085 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001086 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001087 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001088 }
1089
David Horstmann71159f42023-01-03 12:51:59 +00001090 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1091 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001092 goto exit;
David Horstmann71159f42023-01-03 12:51:59 +00001093 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001094
David Horstmann71159f42023-01-03 12:51:59 +00001095 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1096 pt_len_test_data[i]) != 0 ||
1097 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001098 ret = 1;
1099 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001100 }
1101
David Horstmann71159f42023-01-03 12:51:59 +00001102 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001103
David Horstmann71159f42023-01-03 12:51:59 +00001104 if (verbose != 0) {
1105 mbedtls_printf("passed\n");
1106 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001107 }
1108 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001109
David Horstmann71159f42023-01-03 12:51:59 +00001110 if (verbose != 0) {
1111 mbedtls_printf("\n");
1112 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001113
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001114 ret = 0;
1115
1116exit:
David Horstmann71159f42023-01-03 12:51:59 +00001117 if (ret != 0) {
1118 if (verbose != 0) {
1119 mbedtls_printf("failed\n");
1120 }
1121 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001122 }
1123
David Horstmann71159f42023-01-03 12:51:59 +00001124 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001125}
1126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129#endif /* MBEDTLS_GCM_C */