blob: 42fd020780d0d24c4c72d20cde94497d20b9a1f4 [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
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker89e80c92012-03-20 13:50:09 +00006 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +01007
Paul Bakker89e80c92012-03-20 13:50:09 +00008/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +01009 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
10 *
11 * See also:
12 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
13 *
14 * We use the algorithm described as Shoup's method with 4-bit tables in
15 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000016 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010017
Gilles Peskinedb09ef62020-06-03 01:43:33 +020018#include "common.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020020#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000021
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000022#include "mbedtls/gcm.h"
Gilles Peskineed1c7f42022-09-15 20:14:22 +020023#include "mbedtls/platform.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050024#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000025#include "mbedtls/error.h"
Dave Rodgmand26a3d62023-09-11 18:25:16 +010026#include "mbedtls/constant_time.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000027
Rich Evans00ab4702015-02-06 13:43:58 +000028#include <string.h>
29
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if defined(MBEDTLS_AESNI_C)
Chris Jones187782f2021-03-09 17:28:35 +000031#include "aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010032#endif
33
Jerry Yudf87a122023-01-10 18:17:15 +080034#if defined(MBEDTLS_AESCE_C)
35#include "aesce.h"
36#endif
37
Jaeden Amero15263302017-09-21 12:53:48 +010038#if !defined(MBEDTLS_GCM_ALT)
39
Paul Bakker89e80c92012-03-20 13:50:09 +000040/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020041 * Initialize a context
42 */
Gilles Peskine449bd832023-01-11 14:50:10 +010043void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020044{
Gilles Peskine449bd832023-01-11 14:50:10 +010045 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020046}
47
48/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010049 * Precompute small multiples of H, that is set
50 * HH[i] || HL[i] = H times i,
51 * where i is seen as a field element as in [MGV], ie high-order bits
52 * correspond to low powers of P. The result is stored in the same way, that
53 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
54 * corresponds to P^127.
55 */
Gilles Peskine449bd832023-01-11 14:50:10 +010056static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000057{
Paul Bakker43aff2a2013-09-09 00:10:27 +020058 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000059 uint64_t hi, lo;
60 uint64_t vl, vh;
61 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020062 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020063
Gilles Peskine449bd832023-01-11 14:50:10 +010064 memset(h, 0, 16);
65 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
66 return ret;
67 }
Paul Bakker89e80c92012-03-20 13:50:09 +000068
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010069 /* pack h as two 64-bits ints, big-endian */
Gilles Peskine449bd832023-01-11 14:50:10 +010070 hi = MBEDTLS_GET_UINT32_BE(h, 0);
71 lo = MBEDTLS_GET_UINT32_BE(h, 4);
Paul Bakker89e80c92012-03-20 13:50:09 +000072 vh = (uint64_t) hi << 32 | lo;
73
Gilles Peskine449bd832023-01-11 14:50:10 +010074 hi = MBEDTLS_GET_UINT32_BE(h, 8);
75 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +000076 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020077
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010078 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000079 ctx->HL[8] = vl;
80 ctx->HH[8] = vh;
81
Gilles Peskine9af58cd2023-03-10 22:29:32 +010082#if defined(MBEDTLS_AESNI_HAVE_CODE)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010083 /* With CLMUL support, we need only h, not the rest of the table */
Gilles Peskine449bd832023-01-11 14:50:10 +010084 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
85 return 0;
86 }
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010087#endif
88
Jerry Yu72fd0bd2023-08-18 16:31:01 +080089#if defined(MBEDTLS_AESCE_HAVE_CODE)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +010090 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yudf87a122023-01-10 18:17:15 +080091 return 0;
92 }
93#endif
94
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010095 /* 0 corresponds to 0 in GF(2^128) */
96 ctx->HH[0] = 0;
97 ctx->HL[0] = 0;
98
Gilles Peskine449bd832023-01-11 14:50:10 +010099 for (i = 4; i > 0; i >>= 1) {
100 uint32_t T = (vl & 1) * 0xe1000000U;
101 vl = (vh << 63) | (vl >> 1);
102 vh = (vh >> 1) ^ ((uint64_t) T << 32);
Paul Bakker89e80c92012-03-20 13:50:09 +0000103
104 ctx->HL[i] = vl;
105 ctx->HH[i] = vh;
106 }
107
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 for (i = 2; i <= 8; i *= 2) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000109 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
110 vh = *HiH;
111 vl = *HiL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 for (j = 1; j < i; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000113 HiH[j] = vh ^ ctx->HH[j];
114 HiL[j] = vl ^ ctx->HL[j];
115 }
116 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200117
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000119}
120
Gilles Peskine449bd832023-01-11 14:50:10 +0100121int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
122 mbedtls_cipher_id_t cipher,
123 const unsigned char *key,
124 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000125{
Janos Follath24eed8d2019-11-22 13:21:35 +0000126 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 if (keybits != 128 && keybits != 192 && keybits != 256) {
Tuvshinzaya Erdenekhuuc6b8a672022-08-05 15:31:57 +0100130 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200131 }
132
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
134 MBEDTLS_MODE_ECB);
135 if (cipher_info == NULL) {
136 return MBEDTLS_ERR_GCM_BAD_INPUT;
137 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000138
Dave Rodgman85a88132023-06-24 11:41:50 +0100139 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 return MBEDTLS_ERR_GCM_BAD_INPUT;
141 }
142
143 mbedtls_cipher_free(&ctx->cipher_ctx);
144
145 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
146 return ret;
147 }
148
149 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
150 MBEDTLS_ENCRYPT)) != 0) {
151 return ret;
152 }
153
154 if ((ret = gcm_gen_table(ctx)) != 0) {
155 return ret;
156 }
157
158 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000159}
160
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100161/*
162 * Shoup's method for multiplication use this table with
163 * last4[x] = x times P^128
164 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
165 */
Dave Rodgman5ff02452023-07-13 15:55:21 +0100166static const uint16_t last4[16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000167{
168 0x0000, 0x1c20, 0x3840, 0x2460,
169 0x7080, 0x6ca0, 0x48c0, 0x54e0,
170 0xe100, 0xfd20, 0xd940, 0xc560,
171 0x9180, 0x8da0, 0xa9c0, 0xb5e0
172};
173
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100174/*
175 * Sets output to x times H using the precomputed tables.
176 * x and output are seen as elements of GF(2^128) as in [MGV].
177 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100178static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
179 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000180{
181 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000182 unsigned char lo, hi, rem;
183 uint64_t zh, zl;
184
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100185#if defined(MBEDTLS_AESNI_HAVE_CODE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100187 unsigned char h[16];
188
Jerry Yu1ac7f6b2023-03-07 15:44:59 +0800189 /* mbedtls_aesni_gcm_mult needs big-endian input */
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
Jerry Yu72fd0bd2023-08-18 16:31:01 +0800200#if defined(MBEDTLS_AESCE_HAVE_CODE)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +0100201 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yudf87a122023-01-10 18:17:15 +0800202 unsigned char h[16];
203
Jerry Yu1ac7f6b2023-03-07 15:44:59 +0800204 /* mbedtls_aesce_gcm_mult needs big-endian input */
Jerry Yudf87a122023-01-10 18:17:15 +0800205 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
206 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
207 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
208 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
209
210 mbedtls_aesce_gcm_mult(output, x, h);
211 return;
212 }
213#endif
214
Paul Bakker89e80c92012-03-20 13:50:09 +0000215 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000216
217 zh = ctx->HH[lo];
218 zl = ctx->HL[lo];
219
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000221 lo = x[i] & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000223
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 if (i != 15) {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000225 rem = (unsigned char) zl & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 zl = (zh << 60) | (zl >> 4);
227 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000228 zh ^= (uint64_t) last4[rem] << 48;
229 zh ^= ctx->HH[lo];
230 zl ^= ctx->HL[lo];
231
232 }
233
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000234 rem = (unsigned char) zl & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 zl = (zh << 60) | (zl >> 4);
236 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000237 zh ^= (uint64_t) last4[rem] << 48;
238 zh ^= ctx->HH[hi];
239 zl ^= ctx->HL[hi];
240 }
241
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
243 MBEDTLS_PUT_UINT32_BE(zh, output, 4);
244 MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
245 MBEDTLS_PUT_UINT32_BE(zl, output, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000246}
247
Gilles Peskine449bd832023-01-11 14:50:10 +0100248int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
249 int mode,
250 const unsigned char *iv, size_t iv_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000251{
Janos Follath24eed8d2019-11-22 13:21:35 +0000252 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000253 unsigned char work_buf[16];
Paul Bakker89e80c92012-03-20 13:50:09 +0000254 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200255 size_t use_len, olen = 0;
openluopworldeab65ac2021-09-22 23:59:42 +0800256 uint64_t iv_bits;
Paul Bakker89e80c92012-03-20 13:50:09 +0000257
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200258 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200259 /* IV is not allowed to be zero length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
261 return MBEDTLS_ERR_GCM_BAD_INPUT;
262 }
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200263
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 memset(ctx->y, 0x00, sizeof(ctx->y));
265 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200266
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200267 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200268 ctx->len = 0;
269 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 if (iv_len == 12) {
272 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200273 ctx->y[15] = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 } else {
275 memset(work_buf, 0x00, 16);
276 iv_bits = (uint64_t) iv_len * 8;
277 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000278
279 p = iv;
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 while (iv_len > 0) {
281 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000282
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200284
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000286
287 iv_len -= use_len;
288 p += use_len;
289 }
290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000292
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000294 }
295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
297 ctx->base_ectr, &olen)) != 0) {
298 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200299 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000300
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200302}
303
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200304/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200305 * mbedtls_gcm_context::buf contains the partial state of the computation of
306 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200307 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
308 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200309 * * len == 0 && add_len == 0: initial state
310 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
311 * a partial block of AD that has been
312 * xored in but not yet multiplied in.
313 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
314 * the data ends now.
315 * * len % 16 != 0: the first `len % 16` bytes have
316 * a partial block of ciphertext that has
317 * been xored in but not yet multiplied in.
318 * * len > 0 && len % 16 == 0: the authentication tag is correct if
319 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200320 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100321int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
322 const unsigned char *add, size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200323{
324 const unsigned char *p;
Dave Rodgmand22fb732022-11-22 16:53:25 +0000325 size_t use_len, offset;
Gilles Peskine295fc132021-04-15 18:32:23 +0200326
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200327 /* IV is limited to 2^64 bits, so 2^61 bytes */
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 if ((uint64_t) add_len >> 61 != 0) {
329 return MBEDTLS_ERR_GCM_BAD_INPUT;
330 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200331
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200332 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000333 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200334
Gilles Peskine449bd832023-01-11 14:50:10 +0100335 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200336 use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200338 use_len = add_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200340
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200342
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 if (offset + use_len == 16) {
344 gcm_mult(ctx, ctx->buf, ctx->buf);
345 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200346
347 ctx->add_len += use_len;
348 add_len -= use_len;
349 p += use_len;
350 }
351
352 ctx->add_len += add_len;
353
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 while (add_len >= 16) {
355 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200356
Gilles Peskine449bd832023-01-11 14:50:10 +0100357 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000358
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200359 add_len -= 16;
360 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000361 }
362
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 if (add_len > 0) {
364 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200365 }
366
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200368}
369
Gilles Peskine58fc2722021-04-13 15:58:27 +0200370/* Increment the counter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100371static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200372{
373 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 for (i = 16; i > 12; i--) {
375 if (++y[i - 1] != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200376 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 }
378 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200379}
380
381/* Calculate and apply the encryption mask. Process use_len bytes of data,
382 * starting at position offset in the mask block. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100383static int gcm_mask(mbedtls_gcm_context *ctx,
384 unsigned char ectr[16],
385 size_t offset, size_t use_len,
386 const unsigned char *input,
387 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200388{
Gilles Peskine58fc2722021-04-13 15:58:27 +0200389 size_t olen = 0;
390 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
391
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
393 &olen)) != 0) {
394 mbedtls_platform_zeroize(ectr, 16);
395 return ret;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200396 }
397
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
399 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
400 }
401 mbedtls_xor(output, ectr + offset, input, use_len);
402 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
403 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
404 }
Dave Rodgmand22fb732022-11-22 16:53:25 +0000405
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200407}
408
Gilles Peskine449bd832023-01-11 14:50:10 +0100409int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
410 const unsigned char *input, size_t input_length,
411 unsigned char *output, size_t output_size,
412 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200413{
Janos Follath24eed8d2019-11-22 13:21:35 +0000414 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200415 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200416 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200417 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200419
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 if (output_size < input_length) {
421 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
422 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200423 *output_length = input_length;
424
425 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200426 * on a potentially null pointer.
427 * Returning early also means that the last partial block of AD remains
428 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 if (input_length == 0) {
430 return 0;
431 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200432
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 if (output > input && (size_t) (output - input) < input_length) {
434 return MBEDTLS_ERR_GCM_BAD_INPUT;
435 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200436
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200437 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
438 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 if (ctx->len + input_length < ctx->len ||
440 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
441 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200442 }
443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
445 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200446 }
447
Gilles Peskine58fc2722021-04-13 15:58:27 +0200448 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200450 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200452 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100453 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
456 return ret;
457 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 if (offset + use_len == 16) {
460 gcm_mult(ctx, ctx->buf, ctx->buf);
461 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200462
Gilles Peskine58fc2722021-04-13 15:58:27 +0200463 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200464 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000465 p += use_len;
466 out_p += use_len;
467 }
468
Gilles Peskinea56c4482021-04-15 17:22:35 +0200469 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200470
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 while (input_length >= 16) {
472 gcm_incr(ctx->y);
473 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
474 return ret;
475 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200476
Gilles Peskine449bd832023-01-11 14:50:10 +0100477 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200478
Gilles Peskinea56c4482021-04-15 17:22:35 +0200479 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200480 p += 16;
481 out_p += 16;
482 }
483
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 if (input_length > 0) {
485 gcm_incr(ctx->y);
486 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
487 return ret;
488 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200489 }
490
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 mbedtls_platform_zeroize(ectr, sizeof(ectr));
492 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200493}
494
Gilles Peskine449bd832023-01-11 14:50:10 +0100495int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
496 unsigned char *output, size_t output_size,
497 size_t *output_length,
498 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200499{
500 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100501 uint64_t orig_len;
502 uint64_t orig_add_len;
503
Gilles Peskine9461e452021-04-15 16:48:32 +0200504 /* We never pass any output in finish(). The output parameter exists only
505 * for the sake of alternative implementations. */
506 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200507 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200508 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200509
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100510 orig_len = ctx->len * 8;
511 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200512
Gilles Peskine449bd832023-01-11 14:50:10 +0100513 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
514 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200515 }
516
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 if (tag_len > 16 || tag_len < 4) {
518 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000519 }
520
Gilles Peskine449bd832023-01-11 14:50:10 +0100521 if (ctx->len % 16 != 0) {
522 gcm_mult(ctx, ctx->buf, ctx->buf);
523 }
524
525 memcpy(tag, ctx->base_ectr, tag_len);
526
527 if (orig_len || orig_add_len) {
528 memset(work_buf, 0x00, 16);
529
530 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
531 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
532 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
533 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
534
535 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
536
537 gcm_mult(ctx, ctx->buf, ctx->buf);
538
539 mbedtls_xor(tag, tag, ctx->buf, tag_len);
540 }
541
542 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000543}
544
Gilles Peskine449bd832023-01-11 14:50:10 +0100545int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
546 int mode,
547 size_t length,
548 const unsigned char *iv,
549 size_t iv_len,
550 const unsigned char *add,
551 size_t add_len,
552 const unsigned char *input,
553 unsigned char *output,
554 size_t tag_len,
555 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200556{
Janos Follath24eed8d2019-11-22 13:21:35 +0000557 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200558 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200559
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
561 return ret;
562 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200563
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
565 return ret;
566 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200567
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 if ((ret = mbedtls_gcm_update(ctx, input, length,
569 output, length, &olen)) != 0) {
570 return ret;
571 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200572
Gilles Peskine449bd832023-01-11 14:50:10 +0100573 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
574 return ret;
575 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200576
Gilles Peskine449bd832023-01-11 14:50:10 +0100577 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200578}
579
Gilles Peskine449bd832023-01-11 14:50:10 +0100580int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
581 size_t length,
582 const unsigned char *iv,
583 size_t iv_len,
584 const unsigned char *add,
585 size_t add_len,
586 const unsigned char *tag,
587 size_t tag_len,
588 const unsigned char *input,
589 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000590{
Janos Follath24eed8d2019-11-22 13:21:35 +0000591 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000592 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200593 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000594
Gilles Peskine449bd832023-01-11 14:50:10 +0100595 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
596 iv, iv_len, add, add_len,
597 input, output, tag_len, check_tag)) != 0) {
598 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100599 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000600
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200601 /* Check tag in "constant-time" */
Dave Rodgmand26a3d62023-09-11 18:25:16 +0100602 diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
Paul Bakker89e80c92012-03-20 13:50:09 +0000603
Gilles Peskine449bd832023-01-11 14:50:10 +0100604 if (diff != 0) {
605 mbedtls_platform_zeroize(output, length);
606 return MBEDTLS_ERR_GCM_AUTH_FAILED;
607 }
608
609 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000610}
611
Gilles Peskine449bd832023-01-11 14:50:10 +0100612void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200613{
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100615 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 }
617 mbedtls_cipher_free(&ctx->cipher_ctx);
618 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200619}
620
Jaeden Amero15263302017-09-21 12:53:48 +0100621#endif /* !MBEDTLS_GCM_ALT */
622
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000624/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200625 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000626 *
627 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
628 */
629#define MAX_TESTS 6
630
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100631static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100632{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000633
Yanray Wang93533b52023-05-11 16:45:59 +0800634static const unsigned char key_test_data[][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000635{
636 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
640 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
641 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
642 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000644};
645
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100646static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100647{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000648
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100649static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100650{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000651
Yanray Wang93533b52023-05-11 16:45:59 +0800652static const unsigned char iv_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000653{
654 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00 },
656 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
657 0xde, 0xca, 0xf8, 0x88 },
658 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000664 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200665 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000666};
667
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100668static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100669{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000670
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100671static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100672{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000673
Yanray Wang93533b52023-05-11 16:45:59 +0800674static const unsigned char additional_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000675{
676 { 0x00 },
677 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200678 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000679 0xab, 0xad, 0xda, 0xd2 },
680};
681
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100682static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100683{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000684
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100685static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100686{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000687
Yanray Wang93533b52023-05-11 16:45:59 +0800688static const unsigned char pt_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000689{
690 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
692 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
693 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
694 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
695 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
696 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
697 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
698 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
699 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
700};
701
Yanray Wangd329c692023-05-11 16:40:57 +0800702static const unsigned char ct_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000703{
704 { 0x00 },
705 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
706 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
707 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200708 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000709 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200710 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000711 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200712 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000713 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
714 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
715 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
722 0x3d, 0x58, 0xe0, 0x91 },
723 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
730 0xc2, 0x3f, 0x45, 0x98 },
731 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000735 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200736 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000737 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
738 0x4c, 0x34, 0xae, 0xe5 },
Yanray Wangd329c692023-05-11 16:40:57 +0800739#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000740 { 0x00 },
741 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200742 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000743 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200744 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000745 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200746 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000747 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200748 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000749 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
750 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
751 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200752 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000753 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200754 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
755 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
756 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000757 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200758 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000759 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200760 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000761 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200762 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000763 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200764 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000765 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200766 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000767 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200768 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000769 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200770 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000771 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200772 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000773 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200774 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000775 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200776 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
777 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
778 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
779 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
780 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
781 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
782 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
783 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
784 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
785 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
786 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
787 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
788 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
789 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
790 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
791 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
792 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
793 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000794 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200795 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000796 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200797 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000798 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200799 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000800 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200801 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000802 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200803 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000804 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200805 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000806 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200807 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000808 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200809 0x44, 0xae, 0x7e, 0x3f },
Yanray Wangd329c692023-05-11 16:40:57 +0800810#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000811};
812
Yanray Wangd329c692023-05-11 16:40:57 +0800813static const unsigned char tag_test_data[][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000814{
815 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
816 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
817 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
818 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
819 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200820 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000821 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
822 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
823 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
824 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
825 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
826 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
Yanray Wangd329c692023-05-11 16:40:57 +0800827#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000828 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
829 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
830 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200831 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000832 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
833 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
834 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200835 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000836 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200837 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000838 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200839 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000840 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200841 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000842 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200843 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000844 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200845 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000846 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200847 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000848 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200849 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000850 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200851 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Yanray Wangd329c692023-05-11 16:40:57 +0800852#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000853};
854
Gilles Peskine449bd832023-01-11 14:50:10 +0100855int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000856{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000858 unsigned char buf[64];
859 unsigned char tag_buf[16];
860 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200862 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +0000863
Gilles Peskine0cd9ab72023-03-16 13:06:14 +0100864 if (verbose != 0) {
Gilles Peskine7e67bd52023-03-10 22:35:24 +0100865#if defined(MBEDTLS_GCM_ALT)
866 mbedtls_printf(" GCM note: alternative implementation.\n");
867#else /* MBEDTLS_GCM_ALT */
868#if defined(MBEDTLS_AESNI_HAVE_CODE)
869 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
870 mbedtls_printf(" GCM note: using AESNI.\n");
871 } else
872#endif
Jerry Yu2f26a592023-03-31 15:06:33 +0800873
Jerry Yu72fd0bd2023-08-18 16:31:01 +0800874#if defined(MBEDTLS_AESCE_HAVE_CODE)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +0100875 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yu2f26a592023-03-31 15:06:33 +0800876 mbedtls_printf(" GCM note: using AESCE.\n");
877 } else
878#endif
879
Gilles Peskine7e67bd52023-03-10 22:35:24 +0100880 mbedtls_printf(" GCM note: built-in implementation.\n");
881#endif /* MBEDTLS_GCM_ALT */
882 }
883
Yanray Wangd329c692023-05-11 16:40:57 +0800884 static const int loop_limit =
885 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
886
887 for (j = 0; j < loop_limit; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000888 int key_len = 128 + 64 * j;
889
Gilles Peskine449bd832023-01-11 14:50:10 +0100890 for (i = 0; i < MAX_TESTS; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100891 if (verbose != 0) {
892 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
893 key_len, i, "enc");
894 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200895
Arto Kinnunen0f066182023-04-20 10:02:46 +0800896 mbedtls_gcm_init(&ctx);
897
Gilles Peskine449bd832023-01-11 14:50:10 +0100898 ret = mbedtls_gcm_setkey(&ctx, cipher,
899 key_test_data[key_index_test_data[i]],
900 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100901 /*
902 * AES-192 is an optional feature that may be unavailable when
903 * there is an alternative underlying implementation i.e. when
904 * MBEDTLS_AES_ALT is defined.
905 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100906 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
907 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100908 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100909 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100910 goto exit;
911 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000912
Gilles Peskine449bd832023-01-11 14:50:10 +0100913 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
914 pt_len_test_data[i],
915 iv_test_data[iv_index_test_data[i]],
916 iv_len_test_data[i],
917 additional_test_data[add_index_test_data[i]],
918 add_len_test_data[i],
919 pt_test_data[pt_index_test_data[i]],
920 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100921#if defined(MBEDTLS_GCM_ALT)
922 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100923 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
924 iv_len_test_data[i] != 12) {
925 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100926 break;
927 }
928#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100929 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100930 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100931 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000932
Gilles Peskine449bd832023-01-11 14:50:10 +0100933 if (memcmp(buf, ct_test_data[j * 6 + i],
934 pt_len_test_data[i]) != 0 ||
935 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100936 ret = 1;
937 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000938 }
939
Gilles Peskine449bd832023-01-11 14:50:10 +0100940 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200941
Gilles Peskine449bd832023-01-11 14:50:10 +0100942 if (verbose != 0) {
943 mbedtls_printf("passed\n");
944 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000945
Gilles Peskine449bd832023-01-11 14:50:10 +0100946 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100947
Gilles Peskine449bd832023-01-11 14:50:10 +0100948 if (verbose != 0) {
949 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
950 key_len, i, "dec");
951 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200952
Gilles Peskine449bd832023-01-11 14:50:10 +0100953 ret = mbedtls_gcm_setkey(&ctx, cipher,
954 key_test_data[key_index_test_data[i]],
955 key_len);
956 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100957 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100958 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000959
Gilles Peskine449bd832023-01-11 14:50:10 +0100960 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
961 pt_len_test_data[i],
962 iv_test_data[iv_index_test_data[i]],
963 iv_len_test_data[i],
964 additional_test_data[add_index_test_data[i]],
965 add_len_test_data[i],
966 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000967
Gilles Peskine449bd832023-01-11 14:50:10 +0100968 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100969 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100970 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100971
Gilles Peskine449bd832023-01-11 14:50:10 +0100972 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
973 pt_len_test_data[i]) != 0 ||
974 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100975 ret = 1;
976 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000977 }
978
Gilles Peskine449bd832023-01-11 14:50:10 +0100979 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200980
Gilles Peskine449bd832023-01-11 14:50:10 +0100981 if (verbose != 0) {
982 mbedtls_printf("passed\n");
983 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200984
Gilles Peskine449bd832023-01-11 14:50:10 +0100985 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100986
Gilles Peskine449bd832023-01-11 14:50:10 +0100987 if (verbose != 0) {
988 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
989 key_len, i, "enc");
990 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200991
Gilles Peskine449bd832023-01-11 14:50:10 +0100992 ret = mbedtls_gcm_setkey(&ctx, cipher,
993 key_test_data[key_index_test_data[i]],
994 key_len);
995 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100996 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100997 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200998
Gilles Peskine449bd832023-01-11 14:50:10 +0100999 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1000 iv_test_data[iv_index_test_data[i]],
1001 iv_len_test_data[i]);
1002 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001003 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001004 }
Gilles Peskine295fc132021-04-15 18:32:23 +02001005
Gilles Peskine449bd832023-01-11 14:50:10 +01001006 ret = mbedtls_gcm_update_ad(&ctx,
1007 additional_test_data[add_index_test_data[i]],
1008 add_len_test_data[i]);
1009 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001010 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001011 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001012
Gilles Peskine449bd832023-01-11 14:50:10 +01001013 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001014 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001015 ret = mbedtls_gcm_update(&ctx,
1016 pt_test_data[pt_index_test_data[i]],
1017 32,
1018 buf, sizeof(buf), &olen);
1019 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001020 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001021 }
1022 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001023 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001024 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001025
Gilles Peskine449bd832023-01-11 14:50:10 +01001026 ret = mbedtls_gcm_update(&ctx,
1027 pt_test_data[pt_index_test_data[i]] + 32,
1028 rest_len,
1029 buf + 32, sizeof(buf) - 32, &olen);
1030 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001031 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001032 }
1033 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001034 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001035 }
1036 } else {
1037 ret = mbedtls_gcm_update(&ctx,
1038 pt_test_data[pt_index_test_data[i]],
1039 pt_len_test_data[i],
1040 buf, sizeof(buf), &olen);
1041 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001042 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 }
1044 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001045 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001046 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001047 }
1048
Gilles Peskine449bd832023-01-11 14:50:10 +01001049 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1050 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001051 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001052 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001053
Gilles Peskine449bd832023-01-11 14:50:10 +01001054 if (memcmp(buf, ct_test_data[j * 6 + i],
1055 pt_len_test_data[i]) != 0 ||
1056 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001057 ret = 1;
1058 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001059 }
1060
Gilles Peskine449bd832023-01-11 14:50:10 +01001061 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001062
Gilles Peskine449bd832023-01-11 14:50:10 +01001063 if (verbose != 0) {
1064 mbedtls_printf("passed\n");
1065 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001066
Gilles Peskine449bd832023-01-11 14:50:10 +01001067 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001068
Gilles Peskine449bd832023-01-11 14:50:10 +01001069 if (verbose != 0) {
1070 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1071 key_len, i, "dec");
1072 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001073
Gilles Peskine449bd832023-01-11 14:50:10 +01001074 ret = mbedtls_gcm_setkey(&ctx, cipher,
1075 key_test_data[key_index_test_data[i]],
1076 key_len);
1077 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001078 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001080
Gilles Peskine449bd832023-01-11 14:50:10 +01001081 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1082 iv_test_data[iv_index_test_data[i]],
1083 iv_len_test_data[i]);
1084 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001085 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 }
1087 ret = mbedtls_gcm_update_ad(&ctx,
1088 additional_test_data[add_index_test_data[i]],
1089 add_len_test_data[i]);
1090 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001091 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001092 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001093
Gilles Peskine449bd832023-01-11 14:50:10 +01001094 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001095 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001096 ret = mbedtls_gcm_update(&ctx,
1097 ct_test_data[j * 6 + i], 32,
1098 buf, sizeof(buf), &olen);
1099 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001100 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001101 }
1102 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001103 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 ret = mbedtls_gcm_update(&ctx,
1107 ct_test_data[j * 6 + i] + 32,
1108 rest_len,
1109 buf + 32, sizeof(buf) - 32, &olen);
1110 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001111 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001112 }
1113 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001114 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001115 }
1116 } else {
1117 ret = mbedtls_gcm_update(&ctx,
1118 ct_test_data[j * 6 + i],
1119 pt_len_test_data[i],
1120 buf, sizeof(buf), &olen);
1121 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001122 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001123 }
1124 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001125 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001126 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001127 }
1128
Gilles Peskine449bd832023-01-11 14:50:10 +01001129 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1130 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001131 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001132 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1135 pt_len_test_data[i]) != 0 ||
1136 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001137 ret = 1;
1138 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001139 }
1140
Gilles Peskine449bd832023-01-11 14:50:10 +01001141 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001142
Gilles Peskine449bd832023-01-11 14:50:10 +01001143 if (verbose != 0) {
1144 mbedtls_printf("passed\n");
1145 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001146 }
1147 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001148
Gilles Peskine449bd832023-01-11 14:50:10 +01001149 if (verbose != 0) {
1150 mbedtls_printf("\n");
1151 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001152
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001153 ret = 0;
1154
1155exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001156 if (ret != 0) {
1157 if (verbose != 0) {
1158 mbedtls_printf("failed\n");
1159 }
1160 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001161 }
1162
Gilles Peskine449bd832023-01-11 14:50:10 +01001163 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001164}
1165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168#endif /* MBEDTLS_GCM_C */