blob: 02f8cbfcaad315d2d49f69d39053d3a16796df90 [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
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 if (cipher_info->block_size != 16) {
151 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
Dave Rodgman660cd372023-06-15 18:53:35 +0100420MBEDTLS_OPTIMIZE_ALWAYS
Gilles Peskine449bd832023-01-11 14:50:10 +0100421int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
422 const unsigned char *input, size_t input_length,
423 unsigned char *output, size_t output_size,
424 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200425{
Janos Follath24eed8d2019-11-22 13:21:35 +0000426 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200427 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200428 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200429 size_t offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 unsigned char ectr[16] = { 0 };
Gilles Peskine58fc2722021-04-13 15:58:27 +0200431
Gilles Peskine449bd832023-01-11 14:50:10 +0100432 if (output_size < input_length) {
433 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
434 }
Gilles Peskinea56c4482021-04-15 17:22:35 +0200435 *output_length = input_length;
436
437 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200438 * on a potentially null pointer.
439 * Returning early also means that the last partial block of AD remains
440 * untouched for mbedtls_gcm_finish */
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 if (input_length == 0) {
442 return 0;
443 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 if (output > input && (size_t) (output - input) < input_length) {
446 return MBEDTLS_ERR_GCM_BAD_INPUT;
447 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200448
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200449 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
450 * Also check for possible overflow */
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 if (ctx->len + input_length < ctx->len ||
452 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
453 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200454 }
455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
457 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200458 }
459
Gilles Peskine58fc2722021-04-13 15:58:27 +0200460 offset = ctx->len % 16;
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200462 size_t use_len = 16 - offset;
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 if (use_len > input_length) {
Gilles Peskinea56c4482021-04-15 17:22:35 +0200464 use_len = input_length;
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000466
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
468 return ret;
469 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000470
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 if (offset + use_len == 16) {
472 gcm_mult(ctx, ctx->buf, ctx->buf);
473 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200474
Gilles Peskine58fc2722021-04-13 15:58:27 +0200475 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200476 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000477 p += use_len;
478 out_p += use_len;
479 }
480
Gilles Peskinea56c4482021-04-15 17:22:35 +0200481 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 while (input_length >= 16) {
484 gcm_incr(ctx->y);
485 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
486 return ret;
487 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200488
Gilles Peskine449bd832023-01-11 14:50:10 +0100489 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200490
Gilles Peskinea56c4482021-04-15 17:22:35 +0200491 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200492 p += 16;
493 out_p += 16;
494 }
495
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 if (input_length > 0) {
497 gcm_incr(ctx->y);
498 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
499 return ret;
500 }
Gilles Peskine58fc2722021-04-13 15:58:27 +0200501 }
502
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 mbedtls_platform_zeroize(ectr, sizeof(ectr));
504 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200505}
506
Gilles Peskine449bd832023-01-11 14:50:10 +0100507int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
508 unsigned char *output, size_t output_size,
509 size_t *output_length,
510 unsigned char *tag, size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200511{
512 unsigned char work_buf[16];
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100513 uint64_t orig_len;
514 uint64_t orig_add_len;
515
Gilles Peskine9461e452021-04-15 16:48:32 +0200516 /* We never pass any output in finish(). The output parameter exists only
517 * for the sake of alternative implementations. */
518 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200519 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200520 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200521
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100522 orig_len = ctx->len * 8;
523 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200524
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
526 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200527 }
528
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 if (tag_len > 16 || tag_len < 4) {
530 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000531 }
532
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 if (ctx->len % 16 != 0) {
534 gcm_mult(ctx, ctx->buf, ctx->buf);
535 }
536
537 memcpy(tag, ctx->base_ectr, tag_len);
538
539 if (orig_len || orig_add_len) {
540 memset(work_buf, 0x00, 16);
541
542 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
543 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
544 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
545 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
546
547 mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
548
549 gcm_mult(ctx, ctx->buf, ctx->buf);
550
551 mbedtls_xor(tag, tag, ctx->buf, tag_len);
552 }
553
554 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000555}
556
Gilles Peskine449bd832023-01-11 14:50:10 +0100557int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
558 int mode,
559 size_t length,
560 const unsigned char *iv,
561 size_t iv_len,
562 const unsigned char *add,
563 size_t add_len,
564 const unsigned char *input,
565 unsigned char *output,
566 size_t tag_len,
567 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200568{
Janos Follath24eed8d2019-11-22 13:21:35 +0000569 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200570 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200571
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
573 return ret;
574 }
Gilles Peskine295fc132021-04-15 18:32:23 +0200575
Gilles Peskine449bd832023-01-11 14:50:10 +0100576 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
577 return ret;
578 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200579
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 if ((ret = mbedtls_gcm_update(ctx, input, length,
581 output, length, &olen)) != 0) {
582 return ret;
583 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200584
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
586 return ret;
587 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200588
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200590}
591
Gilles Peskine449bd832023-01-11 14:50:10 +0100592int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
593 size_t length,
594 const unsigned char *iv,
595 size_t iv_len,
596 const unsigned char *add,
597 size_t add_len,
598 const unsigned char *tag,
599 size_t tag_len,
600 const unsigned char *input,
601 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000602{
Janos Follath24eed8d2019-11-22 13:21:35 +0000603 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000604 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200605 size_t i;
606 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000607
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
609 iv, iv_len, add, add_len,
610 input, output, tag_len, check_tag)) != 0) {
611 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100612 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000613
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200614 /* Check tag in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 for (diff = 0, i = 0; i < tag_len; i++) {
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200616 diff |= tag[i] ^ check_tag[i];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200617 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000618
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 if (diff != 0) {
620 mbedtls_platform_zeroize(output, length);
621 return MBEDTLS_ERR_GCM_AUTH_FAILED;
622 }
623
624 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000625}
626
Gilles Peskine449bd832023-01-11 14:50:10 +0100627void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200628{
Gilles Peskine449bd832023-01-11 14:50:10 +0100629 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100630 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100631 }
632 mbedtls_cipher_free(&ctx->cipher_ctx);
633 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200634}
635
Jaeden Amero15263302017-09-21 12:53:48 +0100636#endif /* !MBEDTLS_GCM_ALT */
637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000639/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200640 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000641 *
642 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
643 */
644#define MAX_TESTS 6
645
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100646static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100647{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000648
Yanray Wang93533b52023-05-11 16:45:59 +0800649static const unsigned char key_test_data[][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000650{
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
655 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
656 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
657 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200658 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000659};
660
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100661static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100662{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000663
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100664static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100665{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000666
Yanray Wang93533b52023-05-11 16:45:59 +0800667static const unsigned char iv_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000668{
669 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00 },
671 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
672 0xde, 0xca, 0xf8, 0x88 },
673 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200674 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000675 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200676 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000677 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200678 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000679 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200680 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000681};
682
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100683static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100684{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000685
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100686static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100687{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000688
Yanray Wang93533b52023-05-11 16:45:59 +0800689static const unsigned char additional_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000690{
691 { 0x00 },
692 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200693 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000694 0xab, 0xad, 0xda, 0xd2 },
695};
696
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100697static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100698{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000699
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100700static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100701{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000702
Yanray Wang93533b52023-05-11 16:45:59 +0800703static const unsigned char pt_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000704{
705 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
707 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
708 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
709 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
710 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
711 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
712 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
713 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
714 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
715};
716
Yanray Wangd329c692023-05-11 16:40:57 +0800717static const unsigned char ct_test_data[][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000718{
719 { 0x00 },
720 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
721 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
722 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200723 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000724 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200725 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200727 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000728 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
729 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
730 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200731 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000732 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200733 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000734 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200735 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000736 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
737 0x3d, 0x58, 0xe0, 0x91 },
738 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200739 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000740 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200741 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000742 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200743 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000744 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
745 0xc2, 0x3f, 0x45, 0x98 },
746 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200747 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000748 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200749 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000750 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200751 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000752 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
753 0x4c, 0x34, 0xae, 0xe5 },
Yanray Wangd329c692023-05-11 16:40:57 +0800754#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000755 { 0x00 },
756 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200757 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000758 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200759 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000760 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200761 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000762 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200763 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000764 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
765 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
766 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200767 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000768 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200769 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
770 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
771 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000772 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200773 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000774 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200775 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000776 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200777 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000778 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200779 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000780 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200781 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000782 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200783 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000784 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200785 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000786 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200787 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000788 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200789 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000790 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200791 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
792 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
793 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
794 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
795 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
796 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
797 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
798 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
799 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
800 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
801 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
802 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
803 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
804 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
805 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
806 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
807 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
808 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000809 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200810 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000811 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200812 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000813 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200814 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000815 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200816 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000817 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200818 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000819 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200820 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000821 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200822 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000823 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200824 0x44, 0xae, 0x7e, 0x3f },
Yanray Wangd329c692023-05-11 16:40:57 +0800825#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000826};
827
Yanray Wangd329c692023-05-11 16:40:57 +0800828static const unsigned char tag_test_data[][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000829{
830 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
831 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
832 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
833 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
834 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200835 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000836 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
837 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
838 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
839 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
840 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
841 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
Yanray Wangd329c692023-05-11 16:40:57 +0800842#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Paul Bakker89e80c92012-03-20 13:50:09 +0000843 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
844 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
845 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200846 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000847 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
848 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
849 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200850 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000851 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200852 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000853 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200854 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000855 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200856 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000857 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200858 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000859 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200860 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000861 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200862 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000863 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200864 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000865 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200866 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Yanray Wangd329c692023-05-11 16:40:57 +0800867#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Bakker89e80c92012-03-20 13:50:09 +0000868};
869
Gilles Peskine449bd832023-01-11 14:50:10 +0100870int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000871{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000873 unsigned char buf[64];
874 unsigned char tag_buf[16];
875 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200877 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +0000878
Gilles Peskine0cd9ab72023-03-16 13:06:14 +0100879 if (verbose != 0) {
Gilles Peskine7e67bd52023-03-10 22:35:24 +0100880#if defined(MBEDTLS_GCM_ALT)
881 mbedtls_printf(" GCM note: alternative implementation.\n");
882#else /* MBEDTLS_GCM_ALT */
883#if defined(MBEDTLS_AESNI_HAVE_CODE)
884 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
885 mbedtls_printf(" GCM note: using AESNI.\n");
886 } else
887#endif
888 mbedtls_printf(" GCM note: built-in implementation.\n");
889#endif /* MBEDTLS_GCM_ALT */
890 }
891
Yanray Wangd329c692023-05-11 16:40:57 +0800892 static const int loop_limit =
893 (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
894
895 for (j = 0; j < loop_limit; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000896 int key_len = 128 + 64 * j;
897
Gilles Peskine449bd832023-01-11 14:50:10 +0100898 for (i = 0; i < MAX_TESTS; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100899 if (verbose != 0) {
900 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
901 key_len, i, "enc");
902 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200903
Arto Kinnunen0f066182023-04-20 10:02:46 +0800904 mbedtls_gcm_init(&ctx);
905
Gilles Peskine449bd832023-01-11 14:50:10 +0100906 ret = mbedtls_gcm_setkey(&ctx, cipher,
907 key_test_data[key_index_test_data[i]],
908 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100909 /*
910 * AES-192 is an optional feature that may be unavailable when
911 * there is an alternative underlying implementation i.e. when
912 * MBEDTLS_AES_ALT is defined.
913 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100914 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
915 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100916 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100917 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100918 goto exit;
919 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000920
Gilles Peskine449bd832023-01-11 14:50:10 +0100921 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
922 pt_len_test_data[i],
923 iv_test_data[iv_index_test_data[i]],
924 iv_len_test_data[i],
925 additional_test_data[add_index_test_data[i]],
926 add_len_test_data[i],
927 pt_test_data[pt_index_test_data[i]],
928 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100929#if defined(MBEDTLS_GCM_ALT)
930 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100931 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
932 iv_len_test_data[i] != 12) {
933 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100934 break;
935 }
936#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100937 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100938 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100939 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000940
Gilles Peskine449bd832023-01-11 14:50:10 +0100941 if (memcmp(buf, ct_test_data[j * 6 + i],
942 pt_len_test_data[i]) != 0 ||
943 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100944 ret = 1;
945 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000946 }
947
Gilles Peskine449bd832023-01-11 14:50:10 +0100948 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200949
Gilles Peskine449bd832023-01-11 14:50:10 +0100950 if (verbose != 0) {
951 mbedtls_printf("passed\n");
952 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000953
Gilles Peskine449bd832023-01-11 14:50:10 +0100954 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100955
Gilles Peskine449bd832023-01-11 14:50:10 +0100956 if (verbose != 0) {
957 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
958 key_len, i, "dec");
959 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200960
Gilles Peskine449bd832023-01-11 14:50:10 +0100961 ret = mbedtls_gcm_setkey(&ctx, cipher,
962 key_test_data[key_index_test_data[i]],
963 key_len);
964 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100965 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100966 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000967
Gilles Peskine449bd832023-01-11 14:50:10 +0100968 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
969 pt_len_test_data[i],
970 iv_test_data[iv_index_test_data[i]],
971 iv_len_test_data[i],
972 additional_test_data[add_index_test_data[i]],
973 add_len_test_data[i],
974 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000975
Gilles Peskine449bd832023-01-11 14:50:10 +0100976 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100977 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100978 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100979
Gilles Peskine449bd832023-01-11 14:50:10 +0100980 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
981 pt_len_test_data[i]) != 0 ||
982 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100983 ret = 1;
984 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000985 }
986
Gilles Peskine449bd832023-01-11 14:50:10 +0100987 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200988
Gilles Peskine449bd832023-01-11 14:50:10 +0100989 if (verbose != 0) {
990 mbedtls_printf("passed\n");
991 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200992
Gilles Peskine449bd832023-01-11 14:50:10 +0100993 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100994
Gilles Peskine449bd832023-01-11 14:50:10 +0100995 if (verbose != 0) {
996 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
997 key_len, i, "enc");
998 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200999
Gilles Peskine449bd832023-01-11 14:50:10 +01001000 ret = mbedtls_gcm_setkey(&ctx, cipher,
1001 key_test_data[key_index_test_data[i]],
1002 key_len);
1003 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001004 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001005 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001006
Gilles Peskine449bd832023-01-11 14:50:10 +01001007 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1008 iv_test_data[iv_index_test_data[i]],
1009 iv_len_test_data[i]);
1010 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001011 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001012 }
Gilles Peskine295fc132021-04-15 18:32:23 +02001013
Gilles Peskine449bd832023-01-11 14:50:10 +01001014 ret = mbedtls_gcm_update_ad(&ctx,
1015 additional_test_data[add_index_test_data[i]],
1016 add_len_test_data[i]);
1017 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001018 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001019 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001020
Gilles Peskine449bd832023-01-11 14:50:10 +01001021 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001022 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001023 ret = mbedtls_gcm_update(&ctx,
1024 pt_test_data[pt_index_test_data[i]],
1025 32,
1026 buf, sizeof(buf), &olen);
1027 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001028 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001029 }
1030 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001031 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001032 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001033
Gilles Peskine449bd832023-01-11 14:50:10 +01001034 ret = mbedtls_gcm_update(&ctx,
1035 pt_test_data[pt_index_test_data[i]] + 32,
1036 rest_len,
1037 buf + 32, sizeof(buf) - 32, &olen);
1038 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001039 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001040 }
1041 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001042 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 }
1044 } else {
1045 ret = mbedtls_gcm_update(&ctx,
1046 pt_test_data[pt_index_test_data[i]],
1047 pt_len_test_data[i],
1048 buf, sizeof(buf), &olen);
1049 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001050 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001051 }
1052 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001053 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001054 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001055 }
1056
Gilles Peskine449bd832023-01-11 14:50:10 +01001057 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1058 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001059 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001061
Gilles Peskine449bd832023-01-11 14:50:10 +01001062 if (memcmp(buf, ct_test_data[j * 6 + i],
1063 pt_len_test_data[i]) != 0 ||
1064 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001065 ret = 1;
1066 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001067 }
1068
Gilles Peskine449bd832023-01-11 14:50:10 +01001069 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001070
Gilles Peskine449bd832023-01-11 14:50:10 +01001071 if (verbose != 0) {
1072 mbedtls_printf("passed\n");
1073 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001074
Gilles Peskine449bd832023-01-11 14:50:10 +01001075 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001076
Gilles Peskine449bd832023-01-11 14:50:10 +01001077 if (verbose != 0) {
1078 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1079 key_len, i, "dec");
1080 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001081
Gilles Peskine449bd832023-01-11 14:50:10 +01001082 ret = mbedtls_gcm_setkey(&ctx, cipher,
1083 key_test_data[key_index_test_data[i]],
1084 key_len);
1085 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001086 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001087 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001088
Gilles Peskine449bd832023-01-11 14:50:10 +01001089 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1090 iv_test_data[iv_index_test_data[i]],
1091 iv_len_test_data[i]);
1092 if (ret != 0) {
Gilles Peskine295fc132021-04-15 18:32:23 +02001093 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001094 }
1095 ret = mbedtls_gcm_update_ad(&ctx,
1096 additional_test_data[add_index_test_data[i]],
1097 add_len_test_data[i]);
1098 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001099 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001100 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001101
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001103 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 ret = mbedtls_gcm_update(&ctx,
1105 ct_test_data[j * 6 + i], 32,
1106 buf, sizeof(buf), &olen);
1107 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001108 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001109 }
1110 if (olen != 32) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001111 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001112 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001113
Gilles Peskine449bd832023-01-11 14:50:10 +01001114 ret = mbedtls_gcm_update(&ctx,
1115 ct_test_data[j * 6 + i] + 32,
1116 rest_len,
1117 buf + 32, sizeof(buf) - 32, &olen);
1118 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001119 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001120 }
1121 if (olen != rest_len) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001122 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001123 }
1124 } else {
1125 ret = mbedtls_gcm_update(&ctx,
1126 ct_test_data[j * 6 + i],
1127 pt_len_test_data[i],
1128 buf, sizeof(buf), &olen);
1129 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001130 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001131 }
1132 if (olen != pt_len_test_data[i]) {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001133 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001135 }
1136
Gilles Peskine449bd832023-01-11 14:50:10 +01001137 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1138 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001139 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +01001140 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001141
Gilles Peskine449bd832023-01-11 14:50:10 +01001142 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1143 pt_len_test_data[i]) != 0 ||
1144 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001145 ret = 1;
1146 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001147 }
1148
Gilles Peskine449bd832023-01-11 14:50:10 +01001149 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001150
Gilles Peskine449bd832023-01-11 14:50:10 +01001151 if (verbose != 0) {
1152 mbedtls_printf("passed\n");
1153 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001154 }
1155 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001156
Gilles Peskine449bd832023-01-11 14:50:10 +01001157 if (verbose != 0) {
1158 mbedtls_printf("\n");
1159 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001160
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001161 ret = 0;
1162
1163exit:
Gilles Peskine449bd832023-01-11 14:50:10 +01001164 if (ret != 0) {
1165 if (verbose != 0) {
1166 mbedtls_printf("failed\n");
1167 }
1168 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001169 }
1170
Gilles Peskine449bd832023-01-11 14:50:10 +01001171 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001172}
1173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001174#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001176#endif /* MBEDTLS_GCM_C */