blob: 786290f2f92ed8b3d08cd1c7c0943f420a7d161d [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
Jerry Yudf87a122023-01-10 18:17:15 +080045#if defined(MBEDTLS_AESCE_C)
46#include "aesce.h"
47#endif
48
Jaeden Amero15263302017-09-21 12:53:48 +010049#if !defined(MBEDTLS_GCM_ALT)
50
Paul Bakker89e80c92012-03-20 13:50:09 +000051/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020052 * Initialize a context
53 */
Gilles Peskine449bd832023-01-11 14:50:10 +010054void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020055{
Gilles Peskine449bd832023-01-11 14:50:10 +010056 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020057}
58
59/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010060 * Precompute small multiples of H, that is set
61 * HH[i] || HL[i] = H times i,
62 * where i is seen as a field element as in [MGV], ie high-order bits
63 * correspond to low powers of P. The result is stored in the same way, that
64 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
65 * corresponds to P^127.
66 */
Gilles Peskine449bd832023-01-11 14:50:10 +010067static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000068{
Paul Bakker43aff2a2013-09-09 00:10:27 +020069 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000070 uint64_t hi, lo;
71 uint64_t vl, vh;
72 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020073 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020074
Gilles Peskine449bd832023-01-11 14:50:10 +010075 memset(h, 0, 16);
76 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
77 return ret;
78 }
Paul Bakker89e80c92012-03-20 13:50:09 +000079
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010080 /* pack h as two 64-bits ints, big-endian */
Gilles Peskine449bd832023-01-11 14:50:10 +010081 hi = MBEDTLS_GET_UINT32_BE(h, 0);
82 lo = MBEDTLS_GET_UINT32_BE(h, 4);
Paul Bakker89e80c92012-03-20 13:50:09 +000083 vh = (uint64_t) hi << 32 | lo;
84
Gilles Peskine449bd832023-01-11 14:50:10 +010085 hi = MBEDTLS_GET_UINT32_BE(h, 8);
86 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +000087 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020088
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010089 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000090 ctx->HL[8] = vl;
91 ctx->HH[8] = vh;
92
Gilles Peskine9af58cd2023-03-10 22:29:32 +010093#if defined(MBEDTLS_AESNI_HAVE_CODE)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010094 /* With CLMUL support, we need only h, not the rest of the table */
Gilles Peskine449bd832023-01-11 14:50:10 +010095 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
96 return 0;
97 }
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010098#endif
99
Jerry Yudf87a122023-01-10 18:17:15 +0800100#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +0100101 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yudf87a122023-01-10 18:17:15 +0800102 return 0;
103 }
104#endif
105
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100106 /* 0 corresponds to 0 in GF(2^128) */
107 ctx->HH[0] = 0;
108 ctx->HL[0] = 0;
109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 for (i = 4; i > 0; i >>= 1) {
111 uint32_t T = (vl & 1) * 0xe1000000U;
112 vl = (vh << 63) | (vl >> 1);
113 vh = (vh >> 1) ^ ((uint64_t) T << 32);
Paul Bakker89e80c92012-03-20 13:50:09 +0000114
115 ctx->HL[i] = vl;
116 ctx->HH[i] = vh;
117 }
118
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 for (i = 2; i <= 8; i *= 2) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000120 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
121 vh = *HiH;
122 vl = *HiL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100123 for (j = 1; j < i; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000124 HiH[j] = vh ^ ctx->HH[j];
125 HiL[j] = vl ^ ctx->HL[j];
126 }
127 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000130}
131
Gilles Peskine449bd832023-01-11 14:50:10 +0100132int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
133 mbedtls_cipher_id_t cipher,
134 const unsigned char *key,
135 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000136{
Janos Follath24eed8d2019-11-22 13:21:35 +0000137 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000139
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 if (keybits != 128 && keybits != 192 && keybits != 256) {
Tuvshinzaya Erdenekhuuc6b8a672022-08-05 15:31:57 +0100141 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200142 }
143
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
145 MBEDTLS_MODE_ECB);
146 if (cipher_info == NULL) {
147 return MBEDTLS_ERR_GCM_BAD_INPUT;
148 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000149
Dave Rodgman85a88132023-06-24 11:41:50 +0100150 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 return MBEDTLS_ERR_GCM_BAD_INPUT;
152 }
153
154 mbedtls_cipher_free(&ctx->cipher_ctx);
155
156 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
157 return ret;
158 }
159
160 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
161 MBEDTLS_ENCRYPT)) != 0) {
162 return ret;
163 }
164
165 if ((ret = gcm_gen_table(ctx)) != 0) {
166 return ret;
167 }
168
169 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000170}
171
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100172/*
173 * Shoup's method for multiplication use this table with
174 * last4[x] = x times P^128
175 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
176 */
Dave Rodgman5ff02452023-07-13 15:55:21 +0100177static const uint16_t last4[16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000178{
179 0x0000, 0x1c20, 0x3840, 0x2460,
180 0x7080, 0x6ca0, 0x48c0, 0x54e0,
181 0xe100, 0xfd20, 0xd940, 0xc560,
182 0x9180, 0x8da0, 0xa9c0, 0xb5e0
183};
184
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100185/*
186 * Sets output to x times H using the precomputed tables.
187 * x and output are seen as elements of GF(2^128) as in [MGV].
188 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100189static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
190 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000191{
192 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000193 unsigned char lo, hi, rem;
194 uint64_t zh, zl;
195
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100196#if defined(MBEDTLS_AESNI_HAVE_CODE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100198 unsigned char h[16];
199
Jerry Yu1ac7f6b2023-03-07 15:44:59 +0800200 /* mbedtls_aesni_gcm_mult needs big-endian input */
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
202 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
203 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
204 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100205
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 mbedtls_aesni_gcm_mult(output, x, h);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100207 return;
208 }
Gilles Peskine9af58cd2023-03-10 22:29:32 +0100209#endif /* MBEDTLS_AESNI_HAVE_CODE */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100210
Jerry Yudf87a122023-01-10 18:17:15 +0800211#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +0100212 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yudf87a122023-01-10 18:17:15 +0800213 unsigned char h[16];
214
Jerry Yu1ac7f6b2023-03-07 15:44:59 +0800215 /* mbedtls_aesce_gcm_mult needs big-endian input */
Jerry Yudf87a122023-01-10 18:17:15 +0800216 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
217 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
218 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
219 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
220
221 mbedtls_aesce_gcm_mult(output, x, h);
222 return;
223 }
224#endif
225
Paul Bakker89e80c92012-03-20 13:50:09 +0000226 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000227
228 zh = ctx->HH[lo];
229 zl = ctx->HL[lo];
230
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000232 lo = x[i] & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000234
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 if (i != 15) {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000236 rem = (unsigned char) zl & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 zl = (zh << 60) | (zl >> 4);
238 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000239 zh ^= (uint64_t) last4[rem] << 48;
240 zh ^= ctx->HH[lo];
241 zl ^= ctx->HL[lo];
242
243 }
244
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000245 rem = (unsigned char) zl & 0xf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 zl = (zh << 60) | (zl >> 4);
247 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000248 zh ^= (uint64_t) last4[rem] << 48;
249 zh ^= ctx->HH[hi];
250 zl ^= ctx->HL[hi];
251 }
252
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
254 MBEDTLS_PUT_UINT32_BE(zh, output, 4);
255 MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
256 MBEDTLS_PUT_UINT32_BE(zl, output, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000257}
258
Gilles Peskine449bd832023-01-11 14:50:10 +0100259int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
260 int mode,
261 const unsigned char *iv, size_t iv_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000262{
Janos Follath24eed8d2019-11-22 13:21:35 +0000263 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000264 unsigned char work_buf[16];
Paul Bakker89e80c92012-03-20 13:50:09 +0000265 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200266 size_t use_len, olen = 0;
openluopworldeab65ac2021-09-22 23:59:42 +0800267 uint64_t iv_bits;
Paul Bakker89e80c92012-03-20 13:50:09 +0000268
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200269 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200270 /* IV is not allowed to be zero length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
272 return MBEDTLS_ERR_GCM_BAD_INPUT;
273 }
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200274
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 memset(ctx->y, 0x00, sizeof(ctx->y));
276 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200277
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200278 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200279 ctx->len = 0;
280 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000281
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 if (iv_len == 12) {
283 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200284 ctx->y[15] = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 } else {
286 memset(work_buf, 0x00, 16);
287 iv_bits = (uint64_t) iv_len * 8;
288 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000289
290 p = iv;
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 while (iv_len > 0) {
292 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000293
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Paul Bakker169b7f42013-06-25 14:58:00 +0200295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000297
298 iv_len -= use_len;
299 p += use_len;
300 }
301
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000303
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000305 }
306
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
308 ctx->base_ectr, &olen)) != 0) {
309 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200310 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000311
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200313}
314
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200315/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200316 * mbedtls_gcm_context::buf contains the partial state of the computation of
317 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200318 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
319 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200320 * * len == 0 && add_len == 0: initial state
321 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
322 * a partial block of AD that has been
323 * xored in but not yet multiplied in.
324 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
325 * the data ends now.
326 * * len % 16 != 0: the first `len % 16` bytes have
327 * a partial block of ciphertext that has
328 * been xored in but not yet multiplied in.
329 * * len > 0 && len % 16 == 0: the authentication tag is correct if
330 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200331 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100332int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
333 const unsigned char *add, size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200334{
335 const unsigned char *p;
Dave Rodgmand22fb732022-11-22 16:53:25 +0000336 size_t use_len, offset;
Gilles Peskine295fc132021-04-15 18:32:23 +0200337
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200338 /* IV is limited to 2^64 bits, so 2^61 bytes */
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 if ((uint64_t) add_len >> 61 != 0) {
340 return MBEDTLS_ERR_GCM_BAD_INPUT;
341 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200342
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200343 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000344 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200345
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200347 use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 if (use_len > add_len) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200349 use_len = add_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200351
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200353
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 if (offset + use_len == 16) {
355 gcm_mult(ctx, ctx->buf, ctx->buf);
356 }
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200357
358 ctx->add_len += use_len;
359 add_len -= use_len;
360 p += use_len;
361 }
362
363 ctx->add_len += add_len;
364
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 while (add_len >= 16) {
366 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
Paul Bakker169b7f42013-06-25 14:58:00 +0200367
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000369
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200370 add_len -= 16;
371 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000372 }
373
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 if (add_len > 0) {
375 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200376 }
377
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200379}
380
Gilles Peskine58fc2722021-04-13 15:58:27 +0200381/* Increment the counter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100382static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200383{
384 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100385 for (i = 16; i > 12; i--) {
386 if (++y[i - 1] != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200387 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 }
389 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200390}
391
392/* Calculate and apply the encryption mask. Process use_len bytes of data,
393 * starting at position offset in the mask block. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100394static int gcm_mask(mbedtls_gcm_context *ctx,
395 unsigned char ectr[16],
396 size_t offset, size_t use_len,
397 const unsigned char *input,
398 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200399{
Gilles Peskine58fc2722021-04-13 15:58:27 +0200400 size_t olen = 0;
401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
402
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
404 &olen)) != 0) {
405 mbedtls_platform_zeroize(ectr, 16);
406 return ret;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200407 }
408
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
410 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
411 }
412 mbedtls_xor(output, ectr + offset, input, use_len);
413 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
414 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
415 }
Dave Rodgmand22fb732022-11-22 16:53:25 +0000416
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200418}
419
Gilles Peskine449bd832023-01-11 14:50:10 +0100420int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
421 const unsigned char *input, size_t input_length,
422 unsigned char *output, size_t output_size,
423 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200424{
Janos Follath24eed8d2019-11-22 13:21:35 +0000425 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200426 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200427 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200428 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200430
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 if (output_size < input_length) {
432 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
433 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200434 *output_length = input_length;
435
436 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200437 * on a potentially null pointer.
438 * Returning early also means that the last partial block of AD remains
439 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 if (input_length == 0) {
441 return 0;
442 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 if (output > input && (size_t) (output - input) < input_length) {
445 return MBEDTLS_ERR_GCM_BAD_INPUT;
446 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200447
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200448 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
449 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 if (ctx->len + input_length < ctx->len ||
451 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
452 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200453 }
454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
456 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200457 }
458
Gilles Peskine58fc2722021-04-13 15:58:27 +0200459 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200461 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200463 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000465
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
467 return ret;
468 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000469
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 if (offset + use_len == 16) {
471 gcm_mult(ctx, ctx->buf, ctx->buf);
472 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200473
Gilles Peskine58fc2722021-04-13 15:58:27 +0200474 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200475 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000476 p += use_len;
477 out_p += use_len;
478 }
479
Gilles Peskinea56c4482021-04-15 17:22:35 +0200480 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200481
Gilles Peskine449bd832023-01-11 14:50:10 +0100482 while (input_length >= 16) {
483 gcm_incr(ctx->y);
484 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
485 return ret;
486 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200487
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200489
Gilles Peskinea56c4482021-04-15 17:22:35 +0200490 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200491 p += 16;
492 out_p += 16;
493 }
494
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 if (input_length > 0) {
496 gcm_incr(ctx->y);
497 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
498 return ret;
499 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200500 }
501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 mbedtls_platform_zeroize(ectr, sizeof(ectr));
503 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200504}
505
Gilles Peskine449bd832023-01-11 14:50:10 +0100506int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
507 unsigned char *output, size_t output_size,
508 size_t *output_length,
509 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200510{
511 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100512 uint64_t orig_len;
513 uint64_t orig_add_len;
514
Gilles Peskine9461e452021-04-15 16:48:32 +0200515 /* We never pass any output in finish(). The output parameter exists only
516 * for the sake of alternative implementations. */
517 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200518 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200519 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200520
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100521 orig_len = ctx->len * 8;
522 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200523
Gilles Peskine449bd832023-01-11 14:50:10 +0100524 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
525 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200526 }
527
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 if (tag_len > 16 || tag_len < 4) {
529 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000530 }
531
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 if (ctx->len % 16 != 0) {
533 gcm_mult(ctx, ctx->buf, ctx->buf);
534 }
535
536 memcpy(tag, ctx->base_ectr, tag_len);
537
538 if (orig_len || orig_add_len) {
539 memset(work_buf, 0x00, 16);
540
541 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
542 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
543 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
544 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
545
546 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
547
548 gcm_mult(ctx, ctx->buf, ctx->buf);
549
550 mbedtls_xor(tag, tag, ctx->buf, tag_len);
551 }
552
553 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000554}
555
Gilles Peskine449bd832023-01-11 14:50:10 +0100556int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
557 int mode,
558 size_t length,
559 const unsigned char *iv,
560 size_t iv_len,
561 const unsigned char *add,
562 size_t add_len,
563 const unsigned char *input,
564 unsigned char *output,
565 size_t tag_len,
566 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200567{
Janos Follath24eed8d2019-11-22 13:21:35 +0000568 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200569 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200570
Gilles Peskine449bd832023-01-11 14:50:10 +0100571 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
572 return ret;
573 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200574
Gilles Peskine449bd832023-01-11 14:50:10 +0100575 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
576 return ret;
577 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200578
Gilles Peskine449bd832023-01-11 14:50:10 +0100579 if ((ret = mbedtls_gcm_update(ctx, input, length,
580 output, length, &olen)) != 0) {
581 return ret;
582 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200583
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
585 return ret;
586 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200589}
590
Gilles Peskine449bd832023-01-11 14:50:10 +0100591int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
592 size_t length,
593 const unsigned char *iv,
594 size_t iv_len,
595 const unsigned char *add,
596 size_t add_len,
597 const unsigned char *tag,
598 size_t tag_len,
599 const unsigned char *input,
600 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000601{
Janos Follath24eed8d2019-11-22 13:21:35 +0000602 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000603 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200604 size_t i;
605 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000606
Gilles Peskine449bd832023-01-11 14:50:10 +0100607 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
608 iv, iv_len, add, add_len,
609 input, output, tag_len, check_tag)) != 0) {
610 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100611 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000612
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200613 /* Check tag in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 for (diff = 0, i = 0; i < tag_len; i++) {
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200615 diff |= tag[i] ^ check_tag[i];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200616 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000617
Gilles Peskine449bd832023-01-11 14:50:10 +0100618 if (diff != 0) {
619 mbedtls_platform_zeroize(output, length);
620 return MBEDTLS_ERR_GCM_AUTH_FAILED;
621 }
622
623 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000624}
625
Gilles Peskine449bd832023-01-11 14:50:10 +0100626void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200627{
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100629 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 }
631 mbedtls_cipher_free(&ctx->cipher_ctx);
632 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200633}
634
Jaeden Amero15263302017-09-21 12:53:48 +0100635#endif /* !MBEDTLS_GCM_ALT */
636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000638/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200639 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000640 *
641 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
642 */
643#define MAX_TESTS 6
644
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100645static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100646{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000647
Yanray Wang93533b52023-05-11 16:45:59 +0800648static const unsigned char key_test_data[][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000649{
650 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
654 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
655 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
656 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000658};
659
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100660static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100661{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000662
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100663static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100664{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000665
Yanray Wang93533b52023-05-11 16:45:59 +0800666static const unsigned char iv_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000667{
668 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00 },
670 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
671 0xde, 0xca, 0xf8, 0x88 },
672 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200673 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000674 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200675 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000676 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200677 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000678 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200679 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000680};
681
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100682static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100683{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000684
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100685static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100686{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000687
Yanray Wang93533b52023-05-11 16:45:59 +0800688static const unsigned char additional_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000689{
690 { 0x00 },
691 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 0xab, 0xad, 0xda, 0xd2 },
694};
695
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100696static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100697{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000698
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100699static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100700{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000701
Yanray Wang93533b52023-05-11 16:45:59 +0800702static const unsigned char pt_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000703{
704 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
706 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
707 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
708 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
709 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
710 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
711 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
712 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
713 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
714};
715
Yanray Wangd329c692023-05-11 16:40:57 +0800716static const unsigned char ct_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000717{
718 { 0x00 },
719 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
720 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
721 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
728 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
729 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000735 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
736 0x3d, 0x58, 0xe0, 0x91 },
737 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000739 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200740 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000741 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200742 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000743 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
744 0xc2, 0x3f, 0x45, 0x98 },
745 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200746 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000747 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200748 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000749 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200750 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000751 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
752 0x4c, 0x34, 0xae, 0xe5 },
Yanray Wangd329c692023-05-11 16:40:57 +0800753#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000754 { 0x00 },
755 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200756 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000757 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200758 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000759 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200760 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000761 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200762 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000763 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
764 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
765 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200766 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000767 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200768 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
769 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
770 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000771 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200772 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000773 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200774 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000775 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200776 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000777 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200778 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000779 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200780 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000781 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200782 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000783 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200784 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000785 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200786 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000787 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200788 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000789 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200790 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
791 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
792 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
793 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
794 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
795 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
796 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
797 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
798 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
799 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
800 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
801 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
802 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
803 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
804 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
805 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
806 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
807 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000808 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200809 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000810 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200811 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000812 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200813 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000814 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200815 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000816 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200817 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000818 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200819 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000820 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200821 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000822 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200823 0x44, 0xae, 0x7e, 0x3f },
Yanray Wangd329c692023-05-11 16:40:57 +0800824#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000825};
826
Yanray Wangd329c692023-05-11 16:40:57 +0800827static const unsigned char tag_test_data[][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000828{
829 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
830 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
831 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
832 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
833 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200834 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000835 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
836 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
837 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
838 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
839 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
840 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
Yanray Wangd329c692023-05-11 16:40:57 +0800841#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000842 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
843 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
844 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200845 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000846 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
847 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
848 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200849 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000850 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200851 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000852 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200853 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000854 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200855 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000856 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200857 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000858 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200859 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000860 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200861 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000862 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200863 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000864 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200865 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Yanray Wangd329c692023-05-11 16:40:57 +0800866#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000867};
868
Gilles Peskine449bd832023-01-11 14:50:10 +0100869int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000870{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000872 unsigned char buf[64];
873 unsigned char tag_buf[16];
874 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200876 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +0000877
Gilles Peskine0cd9ab72023-03-16 13:06:14 +0100878 if (verbose != 0) {
Gilles Peskine7e67bd52023-03-10 22:35:24 +0100879#if defined(MBEDTLS_GCM_ALT)
880 mbedtls_printf(" GCM note: alternative implementation.\n");
881#else /* MBEDTLS_GCM_ALT */
882#if defined(MBEDTLS_AESNI_HAVE_CODE)
883 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
884 mbedtls_printf(" GCM note: using AESNI.\n");
885 } else
886#endif
Jerry Yu2f26a592023-03-31 15:06:33 +0800887
888#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
Dave Rodgmanf2249ec2023-08-04 14:27:58 +0100889 if (MBEDTLS_AESCE_HAS_SUPPORT()) {
Jerry Yu2f26a592023-03-31 15:06:33 +0800890 mbedtls_printf(" GCM note: using AESCE.\n");
891 } else
892#endif
893
Gilles Peskine7e67bd52023-03-10 22:35:24 +0100894 mbedtls_printf(" GCM note: built-in implementation.\n");
895#endif /* MBEDTLS_GCM_ALT */
896 }
897
Yanray Wangd329c692023-05-11 16:40:57 +0800898 static const int loop_limit =
899 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
900
901 for (j = 0; j < loop_limit; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000902 int key_len = 128 + 64 * j;
903
Gilles Peskine449bd832023-01-11 14:50:10 +0100904 for (i = 0; i < MAX_TESTS; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100905 if (verbose != 0) {
906 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
907 key_len, i, "enc");
908 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909
Arto Kinnunen0f066182023-04-20 10:02:46 +0800910 mbedtls_gcm_init(&ctx);
911
Gilles Peskine449bd832023-01-11 14:50:10 +0100912 ret = mbedtls_gcm_setkey(&ctx, cipher,
913 key_test_data[key_index_test_data[i]],
914 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100915 /*
916 * AES-192 is an optional feature that may be unavailable when
917 * there is an alternative underlying implementation i.e. when
918 * MBEDTLS_AES_ALT is defined.
919 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100920 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
921 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100922 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100923 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100924 goto exit;
925 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000926
Gilles Peskine449bd832023-01-11 14:50:10 +0100927 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
928 pt_len_test_data[i],
929 iv_test_data[iv_index_test_data[i]],
930 iv_len_test_data[i],
931 additional_test_data[add_index_test_data[i]],
932 add_len_test_data[i],
933 pt_test_data[pt_index_test_data[i]],
934 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100935#if defined(MBEDTLS_GCM_ALT)
936 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100937 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
938 iv_len_test_data[i] != 12) {
939 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100940 break;
941 }
942#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100943 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100944 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100945 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000946
Gilles Peskine449bd832023-01-11 14:50:10 +0100947 if (memcmp(buf, ct_test_data[j * 6 + i],
948 pt_len_test_data[i]) != 0 ||
949 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100950 ret = 1;
951 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000952 }
953
Gilles Peskine449bd832023-01-11 14:50:10 +0100954 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200955
Gilles Peskine449bd832023-01-11 14:50:10 +0100956 if (verbose != 0) {
957 mbedtls_printf("passed\n");
958 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000959
Gilles Peskine449bd832023-01-11 14:50:10 +0100960 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100961
Gilles Peskine449bd832023-01-11 14:50:10 +0100962 if (verbose != 0) {
963 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
964 key_len, i, "dec");
965 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200966
Gilles Peskine449bd832023-01-11 14:50:10 +0100967 ret = mbedtls_gcm_setkey(&ctx, cipher,
968 key_test_data[key_index_test_data[i]],
969 key_len);
970 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100971 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100972 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000973
Gilles Peskine449bd832023-01-11 14:50:10 +0100974 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
975 pt_len_test_data[i],
976 iv_test_data[iv_index_test_data[i]],
977 iv_len_test_data[i],
978 additional_test_data[add_index_test_data[i]],
979 add_len_test_data[i],
980 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000981
Gilles Peskine449bd832023-01-11 14:50:10 +0100982 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100983 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100984 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100985
Gilles Peskine449bd832023-01-11 14:50:10 +0100986 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
987 pt_len_test_data[i]) != 0 ||
988 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100989 ret = 1;
990 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000991 }
992
Gilles Peskine449bd832023-01-11 14:50:10 +0100993 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200994
Gilles Peskine449bd832023-01-11 14:50:10 +0100995 if (verbose != 0) {
996 mbedtls_printf("passed\n");
997 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200998
Gilles Peskine449bd832023-01-11 14:50:10 +0100999 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001000
Gilles Peskine449bd832023-01-11 14:50:10 +01001001 if (verbose != 0) {
1002 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1003 key_len, i, "enc");
1004 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001005
Gilles Peskine449bd832023-01-11 14:50:10 +01001006 ret = mbedtls_gcm_setkey(&ctx, cipher,
1007 key_test_data[key_index_test_data[i]],
1008 key_len);
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 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1014 iv_test_data[iv_index_test_data[i]],
1015 iv_len_test_data[i]);
1016 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001017 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001018 }
Gilles Peskine295fc132021-04-15 18:32:23 +02001019
Gilles Peskine449bd832023-01-11 14:50:10 +01001020 ret = mbedtls_gcm_update_ad(&ctx,
1021 additional_test_data[add_index_test_data[i]],
1022 add_len_test_data[i]);
1023 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001024 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001025 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001026
Gilles Peskine449bd832023-01-11 14:50:10 +01001027 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001028 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001029 ret = mbedtls_gcm_update(&ctx,
1030 pt_test_data[pt_index_test_data[i]],
1031 32,
1032 buf, sizeof(buf), &olen);
1033 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001034 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001035 }
1036 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001037 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001038 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001039
Gilles Peskine449bd832023-01-11 14:50:10 +01001040 ret = mbedtls_gcm_update(&ctx,
1041 pt_test_data[pt_index_test_data[i]] + 32,
1042 rest_len,
1043 buf + 32, sizeof(buf) - 32, &olen);
1044 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001045 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001046 }
1047 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001048 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001049 }
1050 } else {
1051 ret = mbedtls_gcm_update(&ctx,
1052 pt_test_data[pt_index_test_data[i]],
1053 pt_len_test_data[i],
1054 buf, sizeof(buf), &olen);
1055 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001056 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001057 }
1058 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001059 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001061 }
1062
Gilles Peskine449bd832023-01-11 14:50:10 +01001063 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1064 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001065 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001066 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001067
Gilles Peskine449bd832023-01-11 14:50:10 +01001068 if (memcmp(buf, ct_test_data[j * 6 + i],
1069 pt_len_test_data[i]) != 0 ||
1070 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001071 ret = 1;
1072 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001073 }
1074
Gilles Peskine449bd832023-01-11 14:50:10 +01001075 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001076
Gilles Peskine449bd832023-01-11 14:50:10 +01001077 if (verbose != 0) {
1078 mbedtls_printf("passed\n");
1079 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001080
Gilles Peskine449bd832023-01-11 14:50:10 +01001081 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001082
Gilles Peskine449bd832023-01-11 14:50:10 +01001083 if (verbose != 0) {
1084 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1085 key_len, i, "dec");
1086 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001087
Gilles Peskine449bd832023-01-11 14:50:10 +01001088 ret = mbedtls_gcm_setkey(&ctx, cipher,
1089 key_test_data[key_index_test_data[i]],
1090 key_len);
1091 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001092 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001093 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001094
Gilles Peskine449bd832023-01-11 14:50:10 +01001095 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1096 iv_test_data[iv_index_test_data[i]],
1097 iv_len_test_data[i]);
1098 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001099 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001100 }
1101 ret = mbedtls_gcm_update_ad(&ctx,
1102 additional_test_data[add_index_test_data[i]],
1103 add_len_test_data[i]);
1104 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001105 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001107
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001109 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001110 ret = mbedtls_gcm_update(&ctx,
1111 ct_test_data[j * 6 + i], 32,
1112 buf, sizeof(buf), &olen);
1113 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001114 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001115 }
1116 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001117 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001118 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001119
Gilles Peskine449bd832023-01-11 14:50:10 +01001120 ret = mbedtls_gcm_update(&ctx,
1121 ct_test_data[j * 6 + i] + 32,
1122 rest_len,
1123 buf + 32, sizeof(buf) - 32, &olen);
1124 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001125 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001126 }
1127 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001128 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001129 }
1130 } else {
1131 ret = mbedtls_gcm_update(&ctx,
1132 ct_test_data[j * 6 + i],
1133 pt_len_test_data[i],
1134 buf, sizeof(buf), &olen);
1135 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001136 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001137 }
1138 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001139 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001140 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001141 }
1142
Gilles Peskine449bd832023-01-11 14:50:10 +01001143 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1144 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001145 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001146 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001147
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1149 pt_len_test_data[i]) != 0 ||
1150 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001151 ret = 1;
1152 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001153 }
1154
Gilles Peskine449bd832023-01-11 14:50:10 +01001155 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001156
Gilles Peskine449bd832023-01-11 14:50:10 +01001157 if (verbose != 0) {
1158 mbedtls_printf("passed\n");
1159 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001160 }
1161 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001162
Gilles Peskine449bd832023-01-11 14:50:10 +01001163 if (verbose != 0) {
1164 mbedtls_printf("\n");
1165 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001166
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001167 ret = 0;
1168
1169exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 if (ret != 0) {
1171 if (verbose != 0) {
1172 mbedtls_printf("failed\n");
1173 }
1174 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001175 }
1176
Gilles Peskine449bd832023-01-11 14:50:10 +01001177 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001178}
1179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001180#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182#endif /* MBEDTLS_GCM_C */