blob: 782120417d0b915a82e11eae87064319dd818444 [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)
101 if (mbedtls_aesce_has_support()) {
102 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 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000177static const uint64_t last4[16] =
178{
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)
212 if (mbedtls_aesce_has_support()) {
213 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
887 mbedtls_printf(" GCM note: built-in implementation.\n");
888#endif /* MBEDTLS_GCM_ALT */
889 }
890
Yanray Wangd329c692023-05-11 16:40:57 +0800891 static const int loop_limit =
892 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
893
894 for (j = 0; j < loop_limit; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000895 int key_len = 128 + 64 * j;
896
Gilles Peskine449bd832023-01-11 14:50:10 +0100897 for (i = 0; i < MAX_TESTS; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100898 if (verbose != 0) {
899 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
900 key_len, i, "enc");
901 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200902
Arto Kinnunen0f066182023-04-20 10:02:46 +0800903 mbedtls_gcm_init(&ctx);
904
Gilles Peskine449bd832023-01-11 14:50:10 +0100905 ret = mbedtls_gcm_setkey(&ctx, cipher,
906 key_test_data[key_index_test_data[i]],
907 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100908 /*
909 * AES-192 is an optional feature that may be unavailable when
910 * there is an alternative underlying implementation i.e. when
911 * MBEDTLS_AES_ALT is defined.
912 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100913 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
914 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100915 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100916 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100917 goto exit;
918 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000919
Gilles Peskine449bd832023-01-11 14:50:10 +0100920 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
921 pt_len_test_data[i],
922 iv_test_data[iv_index_test_data[i]],
923 iv_len_test_data[i],
924 additional_test_data[add_index_test_data[i]],
925 add_len_test_data[i],
926 pt_test_data[pt_index_test_data[i]],
927 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100928#if defined(MBEDTLS_GCM_ALT)
929 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100930 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
931 iv_len_test_data[i] != 12) {
932 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100933 break;
934 }
935#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100936 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100937 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100938 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000939
Gilles Peskine449bd832023-01-11 14:50:10 +0100940 if (memcmp(buf, ct_test_data[j * 6 + i],
941 pt_len_test_data[i]) != 0 ||
942 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100943 ret = 1;
944 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000945 }
946
Gilles Peskine449bd832023-01-11 14:50:10 +0100947 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200948
Gilles Peskine449bd832023-01-11 14:50:10 +0100949 if (verbose != 0) {
950 mbedtls_printf("passed\n");
951 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000952
Gilles Peskine449bd832023-01-11 14:50:10 +0100953 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100954
Gilles Peskine449bd832023-01-11 14:50:10 +0100955 if (verbose != 0) {
956 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
957 key_len, i, "dec");
958 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200959
Gilles Peskine449bd832023-01-11 14:50:10 +0100960 ret = mbedtls_gcm_setkey(&ctx, cipher,
961 key_test_data[key_index_test_data[i]],
962 key_len);
963 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100964 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100965 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000966
Gilles Peskine449bd832023-01-11 14:50:10 +0100967 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
968 pt_len_test_data[i],
969 iv_test_data[iv_index_test_data[i]],
970 iv_len_test_data[i],
971 additional_test_data[add_index_test_data[i]],
972 add_len_test_data[i],
973 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000974
Gilles Peskine449bd832023-01-11 14:50:10 +0100975 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100976 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100977 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100978
Gilles Peskine449bd832023-01-11 14:50:10 +0100979 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
980 pt_len_test_data[i]) != 0 ||
981 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100982 ret = 1;
983 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000984 }
985
Gilles Peskine449bd832023-01-11 14:50:10 +0100986 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200987
Gilles Peskine449bd832023-01-11 14:50:10 +0100988 if (verbose != 0) {
989 mbedtls_printf("passed\n");
990 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200991
Gilles Peskine449bd832023-01-11 14:50:10 +0100992 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100993
Gilles Peskine449bd832023-01-11 14:50:10 +0100994 if (verbose != 0) {
995 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
996 key_len, i, "enc");
997 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200998
Gilles Peskine449bd832023-01-11 14:50:10 +0100999 ret = mbedtls_gcm_setkey(&ctx, cipher,
1000 key_test_data[key_index_test_data[i]],
1001 key_len);
1002 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001003 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001004 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001005
Gilles Peskine449bd832023-01-11 14:50:10 +01001006 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1007 iv_test_data[iv_index_test_data[i]],
1008 iv_len_test_data[i]);
1009 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001010 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001011 }
Gilles Peskine295fc132021-04-15 18:32:23 +02001012
Gilles Peskine449bd832023-01-11 14:50:10 +01001013 ret = mbedtls_gcm_update_ad(&ctx,
1014 additional_test_data[add_index_test_data[i]],
1015 add_len_test_data[i]);
1016 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001017 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001018 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001019
Gilles Peskine449bd832023-01-11 14:50:10 +01001020 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001021 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001022 ret = mbedtls_gcm_update(&ctx,
1023 pt_test_data[pt_index_test_data[i]],
1024 32,
1025 buf, sizeof(buf), &olen);
1026 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001027 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 }
1029 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001030 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001031 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001032
Gilles Peskine449bd832023-01-11 14:50:10 +01001033 ret = mbedtls_gcm_update(&ctx,
1034 pt_test_data[pt_index_test_data[i]] + 32,
1035 rest_len,
1036 buf + 32, sizeof(buf) - 32, &olen);
1037 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001038 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001039 }
1040 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001041 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001042 }
1043 } else {
1044 ret = mbedtls_gcm_update(&ctx,
1045 pt_test_data[pt_index_test_data[i]],
1046 pt_len_test_data[i],
1047 buf, sizeof(buf), &olen);
1048 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001049 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001050 }
1051 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001052 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001053 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001054 }
1055
Gilles Peskine449bd832023-01-11 14:50:10 +01001056 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1057 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001058 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001059 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001060
Gilles Peskine449bd832023-01-11 14:50:10 +01001061 if (memcmp(buf, ct_test_data[j * 6 + i],
1062 pt_len_test_data[i]) != 0 ||
1063 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001064 ret = 1;
1065 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001066 }
1067
Gilles Peskine449bd832023-01-11 14:50:10 +01001068 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001069
Gilles Peskine449bd832023-01-11 14:50:10 +01001070 if (verbose != 0) {
1071 mbedtls_printf("passed\n");
1072 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001073
Gilles Peskine449bd832023-01-11 14:50:10 +01001074 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001075
Gilles Peskine449bd832023-01-11 14:50:10 +01001076 if (verbose != 0) {
1077 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1078 key_len, i, "dec");
1079 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001080
Gilles Peskine449bd832023-01-11 14:50:10 +01001081 ret = mbedtls_gcm_setkey(&ctx, cipher,
1082 key_test_data[key_index_test_data[i]],
1083 key_len);
1084 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001085 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001087
Gilles Peskine449bd832023-01-11 14:50:10 +01001088 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1089 iv_test_data[iv_index_test_data[i]],
1090 iv_len_test_data[i]);
1091 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001092 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001093 }
1094 ret = mbedtls_gcm_update_ad(&ctx,
1095 additional_test_data[add_index_test_data[i]],
1096 add_len_test_data[i]);
1097 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001098 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001099 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001100
Gilles Peskine449bd832023-01-11 14:50:10 +01001101 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001102 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001103 ret = mbedtls_gcm_update(&ctx,
1104 ct_test_data[j * 6 + i], 32,
1105 buf, sizeof(buf), &olen);
1106 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001107 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 }
1109 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001110 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001111 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001112
Gilles Peskine449bd832023-01-11 14:50:10 +01001113 ret = mbedtls_gcm_update(&ctx,
1114 ct_test_data[j * 6 + i] + 32,
1115 rest_len,
1116 buf + 32, sizeof(buf) - 32, &olen);
1117 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001118 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001119 }
1120 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001121 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001122 }
1123 } else {
1124 ret = mbedtls_gcm_update(&ctx,
1125 ct_test_data[j * 6 + i],
1126 pt_len_test_data[i],
1127 buf, sizeof(buf), &olen);
1128 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001129 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001130 }
1131 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001132 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001133 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001134 }
1135
Gilles Peskine449bd832023-01-11 14:50:10 +01001136 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1137 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001138 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001139 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001140
Gilles Peskine449bd832023-01-11 14:50:10 +01001141 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1142 pt_len_test_data[i]) != 0 ||
1143 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001144 ret = 1;
1145 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001146 }
1147
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001149
Gilles Peskine449bd832023-01-11 14:50:10 +01001150 if (verbose != 0) {
1151 mbedtls_printf("passed\n");
1152 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001153 }
1154 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001155
Gilles Peskine449bd832023-01-11 14:50:10 +01001156 if (verbose != 0) {
1157 mbedtls_printf("\n");
1158 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001159
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001160 ret = 0;
1161
1162exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001163 if (ret != 0) {
1164 if (verbose != 0) {
1165 mbedtls_printf("failed\n");
1166 }
1167 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001168 }
1169
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001171}
1172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001175#endif /* MBEDTLS_GCM_C */