blob: 71fcc3540580462da378a0e715f1b462e7a3f855 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
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.
Jens Wiklander817466c2018-05-22 13:49:31 +020018 */
19
20/*
21 * 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.
28 */
29
Jerome Forissier79013242021-07-28 10:24:04 +020030#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020031
32#if defined(MBEDTLS_GCM_C)
33
34#include "mbedtls/gcm.h"
Jens Wiklander32b31802023-10-06 16:59:46 +020035#include "mbedtls/platform.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010036#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020037#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020038
39#include <string.h>
40
41#if defined(MBEDTLS_AESNI_C)
Jens Wiklander32b31802023-10-06 16:59:46 +020042#include "aesni.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020043#endif
44
Jens Wiklander32b31802023-10-06 16:59:46 +020045#if defined(MBEDTLS_AESCE_C)
46#include "aesce.h"
47#endif
Jens Wiklander817466c2018-05-22 13:49:31 +020048
Jens Wiklander3d3b0592019-03-20 15:30:29 +010049#if !defined(MBEDTLS_GCM_ALT)
50
Jens Wiklander817466c2018-05-22 13:49:31 +020051/*
Jens Wiklander817466c2018-05-22 13:49:31 +020052 * Initialize a context
53 */
Jens Wiklander32b31802023-10-06 16:59:46 +020054void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020055{
Jens Wiklander32b31802023-10-06 16:59:46 +020056 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Jens Wiklander817466c2018-05-22 13:49:31 +020057}
58
59/*
60 * 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 */
Jens Wiklander32b31802023-10-06 16:59:46 +020067static int gcm_gen_table(mbedtls_gcm_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020068{
69 int ret, i, j;
70 uint64_t hi, lo;
71 uint64_t vl, vh;
72 unsigned char h[16];
73 size_t olen = 0;
74
Jens Wiklander32b31802023-10-06 16:59:46 +020075 memset(h, 0, 16);
76 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
77 return ret;
78 }
Jens Wiklander817466c2018-05-22 13:49:31 +020079
80 /* pack h as two 64-bits ints, big-endian */
Jens Wiklander32b31802023-10-06 16:59:46 +020081 hi = MBEDTLS_GET_UINT32_BE(h, 0);
82 lo = MBEDTLS_GET_UINT32_BE(h, 4);
Jens Wiklander817466c2018-05-22 13:49:31 +020083 vh = (uint64_t) hi << 32 | lo;
84
Jens Wiklander32b31802023-10-06 16:59:46 +020085 hi = MBEDTLS_GET_UINT32_BE(h, 8);
86 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Jens Wiklander817466c2018-05-22 13:49:31 +020087 vl = (uint64_t) hi << 32 | lo;
88
89 /* 8 = 1000 corresponds to 1 in GF(2^128) */
90 ctx->HL[8] = vl;
91 ctx->HH[8] = vh;
92
Jens Wiklander32b31802023-10-06 16:59:46 +020093#if defined(MBEDTLS_AESNI_HAVE_CODE)
Jens Wiklander817466c2018-05-22 13:49:31 +020094 /* With CLMUL support, we need only h, not the rest of the table */
Jens Wiklander32b31802023-10-06 16:59:46 +020095 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
96 return 0;
97 }
98#endif
99
100#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
101 if (mbedtls_aesce_has_support()) {
102 return 0;
103 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200104#endif
105
106 /* 0 corresponds to 0 in GF(2^128) */
107 ctx->HH[0] = 0;
108 ctx->HL[0] = 0;
109
Jens Wiklander32b31802023-10-06 16:59:46 +0200110 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);
Jens Wiklander817466c2018-05-22 13:49:31 +0200114
115 ctx->HL[i] = vl;
116 ctx->HH[i] = vh;
117 }
118
Jens Wiklander32b31802023-10-06 16:59:46 +0200119 for (i = 2; i <= 8; i *= 2) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200120 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
121 vh = *HiH;
122 vl = *HiL;
Jens Wiklander32b31802023-10-06 16:59:46 +0200123 for (j = 1; j < i; j++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200124 HiH[j] = vh ^ ctx->HH[j];
125 HiL[j] = vl ^ ctx->HL[j];
126 }
127 }
128
Jens Wiklander32b31802023-10-06 16:59:46 +0200129 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200130}
131
Jens Wiklander32b31802023-10-06 16:59:46 +0200132int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
133 mbedtls_cipher_id_t cipher,
134 const unsigned char *key,
135 unsigned int keybits)
Jens Wiklander817466c2018-05-22 13:49:31 +0200136{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200137 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200138 const mbedtls_cipher_info_t *cipher_info;
139
Jens Wiklander32b31802023-10-06 16:59:46 +0200140 if (keybits != 128 && keybits != 192 && keybits != 256) {
141 return MBEDTLS_ERR_GCM_BAD_INPUT;
Jens Wiklander817466c2018-05-22 13:49:31 +0200142 }
143
Jens Wiklander32b31802023-10-06 16:59:46 +0200144 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 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200149
Jens Wiklander32b31802023-10-06 16:59:46 +0200150 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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200170}
171
172/*
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 */
177static 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
185/*
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 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200189static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
190 unsigned char output[16])
Jens Wiklander817466c2018-05-22 13:49:31 +0200191{
192 int i = 0;
193 unsigned char lo, hi, rem;
194 uint64_t zh, zl;
195
Jens Wiklander32b31802023-10-06 16:59:46 +0200196#if defined(MBEDTLS_AESNI_HAVE_CODE)
197 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200198 unsigned char h[16];
199
Jens Wiklander32b31802023-10-06 16:59:46 +0200200 /* mbedtls_aesni_gcm_mult needs big-endian input */
201 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);
Jens Wiklander817466c2018-05-22 13:49:31 +0200205
Jens Wiklander32b31802023-10-06 16:59:46 +0200206 mbedtls_aesni_gcm_mult(output, x, h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200207 return;
208 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200209#endif /* MBEDTLS_AESNI_HAVE_CODE */
210
211#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
212 if (mbedtls_aesce_has_support()) {
213 unsigned char h[16];
214
215 /* mbedtls_aesce_gcm_mult needs big-endian input */
216 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
Jens Wiklander817466c2018-05-22 13:49:31 +0200225
226 lo = x[15] & 0xf;
227
228 zh = ctx->HH[lo];
229 zl = ctx->HL[lo];
230
Jens Wiklander32b31802023-10-06 16:59:46 +0200231 for (i = 15; i >= 0; i--) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200232 lo = x[i] & 0xf;
Jens Wiklander32b31802023-10-06 16:59:46 +0200233 hi = (x[i] >> 4) & 0xf;
Jens Wiklander817466c2018-05-22 13:49:31 +0200234
Jens Wiklander32b31802023-10-06 16:59:46 +0200235 if (i != 15) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200236 rem = (unsigned char) zl & 0xf;
Jens Wiklander32b31802023-10-06 16:59:46 +0200237 zl = (zh << 60) | (zl >> 4);
238 zh = (zh >> 4);
Jens Wiklander817466c2018-05-22 13:49:31 +0200239 zh ^= (uint64_t) last4[rem] << 48;
240 zh ^= ctx->HH[lo];
241 zl ^= ctx->HL[lo];
242
243 }
244
245 rem = (unsigned char) zl & 0xf;
Jens Wiklander32b31802023-10-06 16:59:46 +0200246 zl = (zh << 60) | (zl >> 4);
247 zh = (zh >> 4);
Jens Wiklander817466c2018-05-22 13:49:31 +0200248 zh ^= (uint64_t) last4[rem] << 48;
249 zh ^= ctx->HH[hi];
250 zl ^= ctx->HL[hi];
251 }
252
Jens Wiklander32b31802023-10-06 16:59:46 +0200253 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);
Jens Wiklander817466c2018-05-22 13:49:31 +0200257}
258
Jens Wiklander32b31802023-10-06 16:59:46 +0200259int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
260 int mode,
261 const unsigned char *iv, size_t iv_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200262{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200263 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200264 unsigned char work_buf[16];
Jens Wiklander817466c2018-05-22 13:49:31 +0200265 const unsigned char *p;
266 size_t use_len, olen = 0;
Jerome Forissier039e02d2022-08-09 17:10:15 +0200267 uint64_t iv_bits;
Jens Wiklander817466c2018-05-22 13:49:31 +0200268
Jens Wiklander32b31802023-10-06 16:59:46 +0200269 /* IV is limited to 2^64 bits, so 2^61 bytes */
Jens Wiklander817466c2018-05-22 13:49:31 +0200270 /* IV is not allowed to be zero length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200271 if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
272 return MBEDTLS_ERR_GCM_BAD_INPUT;
Jens Wiklander817466c2018-05-22 13:49:31 +0200273 }
274
Jens Wiklander32b31802023-10-06 16:59:46 +0200275 memset(ctx->y, 0x00, sizeof(ctx->y));
276 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Jens Wiklander817466c2018-05-22 13:49:31 +0200277
278 ctx->mode = mode;
279 ctx->len = 0;
280 ctx->add_len = 0;
281
Jens Wiklander32b31802023-10-06 16:59:46 +0200282 if (iv_len == 12) {
283 memcpy(ctx->y, iv, iv_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200284 ctx->y[15] = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200285 } 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);
Jens Wiklander817466c2018-05-22 13:49:31 +0200289
290 p = iv;
Jens Wiklander32b31802023-10-06 16:59:46 +0200291 while (iv_len > 0) {
292 use_len = (iv_len < 16) ? iv_len : 16;
Jens Wiklander817466c2018-05-22 13:49:31 +0200293
Jens Wiklander32b31802023-10-06 16:59:46 +0200294 mbedtls_xor(ctx->y, ctx->y, p, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200295
Jens Wiklander32b31802023-10-06 16:59:46 +0200296 gcm_mult(ctx, ctx->y, ctx->y);
Jens Wiklander817466c2018-05-22 13:49:31 +0200297
298 iv_len -= use_len;
299 p += use_len;
300 }
301
Jens Wiklander32b31802023-10-06 16:59:46 +0200302 mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
Jens Wiklander817466c2018-05-22 13:49:31 +0200303
Jens Wiklander32b31802023-10-06 16:59:46 +0200304 gcm_mult(ctx, ctx->y, ctx->y);
Jens Wiklander817466c2018-05-22 13:49:31 +0200305 }
306
Jens Wiklander32b31802023-10-06 16:59:46 +0200307 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
308 ctx->base_ectr, &olen)) != 0) {
309 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200310 }
311
Jens Wiklander32b31802023-10-06 16:59:46 +0200312 return 0;
313}
314
315/**
316 * mbedtls_gcm_context::buf contains the partial state of the computation of
317 * the authentication tag.
318 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
319 * different stages of the computation:
320 * * 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.
331 */
332int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
333 const unsigned char *add, size_t add_len)
334{
335 const unsigned char *p;
336 size_t use_len, offset;
337
338 /* IV is limited to 2^64 bits, so 2^61 bytes */
339 if ((uint64_t) add_len >> 61 != 0) {
340 return MBEDTLS_ERR_GCM_BAD_INPUT;
341 }
342
343 offset = ctx->add_len % 16;
Jens Wiklander817466c2018-05-22 13:49:31 +0200344 p = add;
Jens Wiklander817466c2018-05-22 13:49:31 +0200345
Jens Wiklander32b31802023-10-06 16:59:46 +0200346 if (offset != 0) {
347 use_len = 16 - offset;
348 if (use_len > add_len) {
349 use_len = add_len;
350 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200351
Jens Wiklander32b31802023-10-06 16:59:46 +0200352 mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200353
Jens Wiklander32b31802023-10-06 16:59:46 +0200354 if (offset + use_len == 16) {
355 gcm_mult(ctx, ctx->buf, ctx->buf);
356 }
357
358 ctx->add_len += use_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200359 add_len -= use_len;
360 p += use_len;
361 }
362
Jens Wiklander32b31802023-10-06 16:59:46 +0200363 ctx->add_len += add_len;
364
365 while (add_len >= 16) {
366 mbedtls_xor(ctx->buf, ctx->buf, p, 16);
367
368 gcm_mult(ctx, ctx->buf, ctx->buf);
369
370 add_len -= 16;
371 p += 16;
372 }
373
374 if (add_len > 0) {
375 mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
376 }
377
378 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200379}
380
Jens Wiklander32b31802023-10-06 16:59:46 +0200381/* Increment the counter. */
382static void gcm_incr(unsigned char y[16])
383{
384 size_t i;
385 for (i = 16; i > 12; i--) {
386 if (++y[i - 1] != 0) {
387 break;
388 }
389 }
390}
391
392/* Calculate and apply the encryption mask. Process use_len bytes of data,
393 * starting at position offset in the mask block. */
394static 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)
399{
400 size_t olen = 0;
401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
402
403 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
404 &olen)) != 0) {
405 mbedtls_platform_zeroize(ectr, 16);
406 return ret;
407 }
408
409 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 }
416
417 return 0;
418}
419
420int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200424{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200425 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200426 const unsigned char *p = input;
Jens Wiklander817466c2018-05-22 13:49:31 +0200427 unsigned char *out_p = output;
Jens Wiklander32b31802023-10-06 16:59:46 +0200428 size_t offset;
429 unsigned char ectr[16] = { 0 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200430
Jens Wiklander32b31802023-10-06 16:59:46 +0200431 if (output_size < input_length) {
432 return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
433 }
434 *output_length = input_length;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100435
Jens Wiklander32b31802023-10-06 16:59:46 +0200436 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
437 * on a potentially null pointer.
438 * Returning early also means that the last partial block of AD remains
439 * untouched for mbedtls_gcm_finish */
440 if (input_length == 0) {
441 return 0;
442 }
443
444 if (output > input && (size_t) (output - input) < input_length) {
445 return MBEDTLS_ERR_GCM_BAD_INPUT;
446 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200447
448 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
449 * Also check for possible overflow */
Jens Wiklander32b31802023-10-06 16:59:46 +0200450 if (ctx->len + input_length < ctx->len ||
451 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
452 return MBEDTLS_ERR_GCM_BAD_INPUT;
Jens Wiklander817466c2018-05-22 13:49:31 +0200453 }
454
Jens Wiklander32b31802023-10-06 16:59:46 +0200455 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
456 gcm_mult(ctx, ctx->buf, ctx->buf);
457 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200458
Jens Wiklander32b31802023-10-06 16:59:46 +0200459 offset = ctx->len % 16;
460 if (offset != 0) {
461 size_t use_len = 16 - offset;
462 if (use_len > input_length) {
463 use_len = input_length;
Jens Wiklander817466c2018-05-22 13:49:31 +0200464 }
465
Jens Wiklander32b31802023-10-06 16:59:46 +0200466 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
467 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200468 }
469
Jens Wiklander32b31802023-10-06 16:59:46 +0200470 if (offset + use_len == 16) {
471 gcm_mult(ctx, ctx->buf, ctx->buf);
472 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200473
Jens Wiklander32b31802023-10-06 16:59:46 +0200474 ctx->len += use_len;
475 input_length -= use_len;
Jens Wiklander817466c2018-05-22 13:49:31 +0200476 p += use_len;
477 out_p += use_len;
478 }
479
Jens Wiklander32b31802023-10-06 16:59:46 +0200480 ctx->len += input_length;
481
482 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 }
487
488 gcm_mult(ctx, ctx->buf, ctx->buf);
489
490 input_length -= 16;
491 p += 16;
492 out_p += 16;
493 }
494
495 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 }
500 }
501
502 mbedtls_platform_zeroize(ectr, sizeof(ectr));
503 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200504}
505
Jens Wiklander32b31802023-10-06 16:59:46 +0200506int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200510{
511 unsigned char work_buf[16];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100512 uint64_t orig_len;
513 uint64_t orig_add_len;
514
Jens Wiklander32b31802023-10-06 16:59:46 +0200515 /* We never pass any output in finish(). The output parameter exists only
516 * for the sake of alternative implementations. */
517 (void) output;
518 (void) output_size;
519 *output_length = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100520
521 orig_len = ctx->len * 8;
522 orig_add_len = ctx->add_len * 8;
Jens Wiklander817466c2018-05-22 13:49:31 +0200523
Jens Wiklander32b31802023-10-06 16:59:46 +0200524 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
525 gcm_mult(ctx, ctx->buf, ctx->buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200526 }
527
Jens Wiklander32b31802023-10-06 16:59:46 +0200528 if (tag_len > 16 || tag_len < 4) {
529 return MBEDTLS_ERR_GCM_BAD_INPUT;
530 }
531
532 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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200554}
555
Jens Wiklander32b31802023-10-06 16:59:46 +0200556int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200567{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200568 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200569 size_t olen;
Jens Wiklander817466c2018-05-22 13:49:31 +0200570
Jens Wiklander32b31802023-10-06 16:59:46 +0200571 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
572 return ret;
573 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100574
Jens Wiklander32b31802023-10-06 16:59:46 +0200575 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
576 return ret;
577 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200578
Jens Wiklander32b31802023-10-06 16:59:46 +0200579 if ((ret = mbedtls_gcm_update(ctx, input, length,
580 output, length, &olen)) != 0) {
581 return ret;
582 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200583
Jens Wiklander32b31802023-10-06 16:59:46 +0200584 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
585 return ret;
586 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200587
Jens Wiklander32b31802023-10-06 16:59:46 +0200588 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200589}
590
Jens Wiklander32b31802023-10-06 16:59:46 +0200591int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200601{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200602 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200603 unsigned char check_tag[16];
604 size_t i;
605 int diff;
606
Jens Wiklander32b31802023-10-06 16:59:46 +0200607 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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200611 }
612
613 /* Check tag in "constant-time" */
Jens Wiklander32b31802023-10-06 16:59:46 +0200614 for (diff = 0, i = 0; i < tag_len; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200615 diff |= tag[i] ^ check_tag[i];
Jens Wiklander817466c2018-05-22 13:49:31 +0200616 }
617
Jens Wiklander32b31802023-10-06 16:59:46 +0200618 if (diff != 0) {
619 mbedtls_platform_zeroize(output, length);
620 return MBEDTLS_ERR_GCM_AUTH_FAILED;
621 }
622
623 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200624}
625
Jens Wiklander32b31802023-10-06 16:59:46 +0200626void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200627{
Jens Wiklander32b31802023-10-06 16:59:46 +0200628 if (ctx == NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100629 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200630 }
631 mbedtls_cipher_free(&ctx->cipher_ctx);
632 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Jens Wiklander817466c2018-05-22 13:49:31 +0200633}
634
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100635#endif /* !MBEDTLS_GCM_ALT */
636
Jens Wiklander817466c2018-05-22 13:49:31 +0200637#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
638/*
639 * AES-GCM test vectors from:
640 *
641 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
642 */
643#define MAX_TESTS 6
644
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200645static const int key_index_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200646{ 0, 0, 1, 1, 1, 1 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200647
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200648static const unsigned char key_test_data[MAX_TESTS][32] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200649{
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,
657 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
658};
659
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200660static const size_t iv_len_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200661{ 12, 12, 12, 12, 8, 60 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200662
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200663static const int iv_index_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200664{ 0, 0, 1, 1, 1, 2 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200665
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200666static const unsigned char iv_test_data[MAX_TESTS][64] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200667{
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,
673 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
674 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
675 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
676 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
677 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
678 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
679 0xa6, 0x37, 0xb3, 0x9b },
680};
681
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200682static const size_t add_len_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200683{ 0, 0, 0, 20, 20, 20 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200684
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200685static const int add_index_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200686{ 0, 0, 0, 1, 1, 1 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200687
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200688static const unsigned char additional_test_data[MAX_TESTS][64] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200689{
690 { 0x00 },
691 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
692 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
693 0xab, 0xad, 0xda, 0xd2 },
694};
695
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200696static const size_t pt_len_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200697{ 0, 16, 64, 60, 60, 60 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200698
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200699static const int pt_index_test_data[MAX_TESTS] =
Jens Wiklander32b31802023-10-06 16:59:46 +0200700{ 0, 0, 1, 1, 1, 1 };
Jens Wiklander817466c2018-05-22 13:49:31 +0200701
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200702static const unsigned char pt_test_data[MAX_TESTS][64] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200703{
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
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200716static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200717{
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,
722 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
723 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
724 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
725 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
726 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
727 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,
730 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
731 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
732 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
733 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
734 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
735 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
736 0x3d, 0x58, 0xe0, 0x91 },
737 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
738 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
739 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
740 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
741 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
742 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
743 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
744 0xc2, 0x3f, 0x45, 0x98 },
745 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
746 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
747 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
748 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
749 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
750 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
751 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
752 0x4c, 0x34, 0xae, 0xe5 },
753 { 0x00 },
754 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
755 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
756 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
757 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
758 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
759 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
760 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
761 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
762 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
763 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
764 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
765 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
766 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
767 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
768 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
769 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
770 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
771 0xcc, 0xda, 0x27, 0x10 },
772 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
773 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
774 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
775 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
776 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
777 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
778 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
779 0xa0, 0xf0, 0x62, 0xf7 },
780 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
781 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
782 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
783 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
784 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
785 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
786 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
787 0xe9, 0xb7, 0x37, 0x3b },
788 { 0x00 },
789 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
790 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
791 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
792 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
793 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
794 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
795 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
796 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
797 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
798 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
799 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
800 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
801 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
802 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
803 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
804 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
805 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
806 0xbc, 0xc9, 0xf6, 0x62 },
807 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
808 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
809 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
810 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
811 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
812 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
813 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
814 0xf4, 0x7c, 0x9b, 0x1f },
815 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
816 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
817 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
818 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
819 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
820 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
821 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
822 0x44, 0xae, 0x7e, 0x3f },
823};
824
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200825static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Jens Wiklander817466c2018-05-22 13:49:31 +0200826{
827 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
828 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
829 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
830 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
831 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
832 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
833 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
834 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
835 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
836 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
837 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
838 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
839 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
840 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
841 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
842 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
843 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
844 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
845 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
846 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
847 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
848 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
849 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
850 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
851 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
852 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
853 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
854 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
855 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
856 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
857 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
858 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
859 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
860 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
861 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
862 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
863};
864
Jens Wiklander32b31802023-10-06 16:59:46 +0200865int mbedtls_gcm_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200866{
867 mbedtls_gcm_context ctx;
868 unsigned char buf[64];
869 unsigned char tag_buf[16];
870 int i, j, ret;
871 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Jens Wiklander32b31802023-10-06 16:59:46 +0200872 size_t olen;
Jens Wiklander817466c2018-05-22 13:49:31 +0200873
Jens Wiklander32b31802023-10-06 16:59:46 +0200874 if (verbose != 0) {
875#if defined(MBEDTLS_GCM_ALT)
876 mbedtls_printf(" GCM note: alternative implementation.\n");
877#else /* MBEDTLS_GCM_ALT */
878#if defined(MBEDTLS_AESNI_HAVE_CODE)
879 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
880 mbedtls_printf(" GCM note: using AESNI.\n");
881 } else
882#endif
883 mbedtls_printf(" GCM note: built-in implementation.\n");
884#endif /* MBEDTLS_GCM_ALT */
885 }
886
887 for (j = 0; j < 3; j++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200888 int key_len = 128 + 64 * j;
889
Jens Wiklander32b31802023-10-06 16:59:46 +0200890 for (i = 0; i < MAX_TESTS; i++) {
891 mbedtls_gcm_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100892
Jens Wiklander32b31802023-10-06 16:59:46 +0200893 if (verbose != 0) {
894 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
895 key_len, i, "enc");
896 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200897
Jens Wiklander32b31802023-10-06 16:59:46 +0200898 ret = mbedtls_gcm_setkey(&ctx, cipher,
899 key_test_data[key_index_test_data[i]],
900 key_len);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100901 /*
902 * AES-192 is an optional feature that may be unavailable when
903 * there is an alternative underlying implementation i.e. when
904 * MBEDTLS_AES_ALT is defined.
905 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200906 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
907 mbedtls_printf("skipped\n");
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100908 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200909 } else if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100910 goto exit;
911 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200912
Jens Wiklander32b31802023-10-06 16:59:46 +0200913 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
914 pt_len_test_data[i],
915 iv_test_data[iv_index_test_data[i]],
916 iv_len_test_data[i],
917 additional_test_data[add_index_test_data[i]],
918 add_len_test_data[i],
919 pt_test_data[pt_index_test_data[i]],
920 buf, 16, tag_buf);
Jerome Forissier79013242021-07-28 10:24:04 +0200921#if defined(MBEDTLS_GCM_ALT)
922 /* Allow alternative implementations to only support 12-byte nonces. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200923 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
924 iv_len_test_data[i] != 12) {
925 mbedtls_printf("skipped\n");
Jerome Forissier79013242021-07-28 10:24:04 +0200926 break;
927 }
928#endif /* defined(MBEDTLS_GCM_ALT) */
Jens Wiklander32b31802023-10-06 16:59:46 +0200929 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100930 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200931 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200932
Jens Wiklander32b31802023-10-06 16:59:46 +0200933 if (memcmp(buf, ct_test_data[j * 6 + i],
934 pt_len_test_data[i]) != 0 ||
935 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100936 ret = 1;
937 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200938 }
939
Jens Wiklander32b31802023-10-06 16:59:46 +0200940 mbedtls_gcm_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200941
Jens Wiklander32b31802023-10-06 16:59:46 +0200942 if (verbose != 0) {
943 mbedtls_printf("passed\n");
944 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200945
Jens Wiklander32b31802023-10-06 16:59:46 +0200946 mbedtls_gcm_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100947
Jens Wiklander32b31802023-10-06 16:59:46 +0200948 if (verbose != 0) {
949 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
950 key_len, i, "dec");
951 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200952
Jens Wiklander32b31802023-10-06 16:59:46 +0200953 ret = mbedtls_gcm_setkey(&ctx, cipher,
954 key_test_data[key_index_test_data[i]],
955 key_len);
956 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100957 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200958 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200959
Jens Wiklander32b31802023-10-06 16:59:46 +0200960 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
961 pt_len_test_data[i],
962 iv_test_data[iv_index_test_data[i]],
963 iv_len_test_data[i],
964 additional_test_data[add_index_test_data[i]],
965 add_len_test_data[i],
966 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200967
Jens Wiklander32b31802023-10-06 16:59:46 +0200968 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100969 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200970 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100971
Jens Wiklander32b31802023-10-06 16:59:46 +0200972 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
973 pt_len_test_data[i]) != 0 ||
974 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100975 ret = 1;
976 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +0200977 }
978
Jens Wiklander32b31802023-10-06 16:59:46 +0200979 mbedtls_gcm_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200980
Jens Wiklander32b31802023-10-06 16:59:46 +0200981 if (verbose != 0) {
982 mbedtls_printf("passed\n");
983 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200984
Jens Wiklander32b31802023-10-06 16:59:46 +0200985 mbedtls_gcm_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100986
Jens Wiklander32b31802023-10-06 16:59:46 +0200987 if (verbose != 0) {
988 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
989 key_len, i, "enc");
990 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200991
Jens Wiklander32b31802023-10-06 16:59:46 +0200992 ret = mbedtls_gcm_setkey(&ctx, cipher,
993 key_test_data[key_index_test_data[i]],
994 key_len);
995 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100996 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200997 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200998
Jens Wiklander32b31802023-10-06 16:59:46 +0200999 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1000 iv_test_data[iv_index_test_data[i]],
1001 iv_len_test_data[i]);
1002 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001003 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001004 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001005
Jens Wiklander32b31802023-10-06 16:59:46 +02001006 ret = mbedtls_gcm_update_ad(&ctx,
1007 additional_test_data[add_index_test_data[i]],
1008 add_len_test_data[i]);
1009 if (ret != 0) {
1010 goto exit;
1011 }
1012
1013 if (pt_len_test_data[i] > 32) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001014 size_t rest_len = pt_len_test_data[i] - 32;
Jens Wiklander32b31802023-10-06 16:59:46 +02001015 ret = mbedtls_gcm_update(&ctx,
1016 pt_test_data[pt_index_test_data[i]],
1017 32,
1018 buf, sizeof(buf), &olen);
1019 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001020 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001021 }
1022 if (olen != 32) {
1023 goto exit;
1024 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001025
Jens Wiklander32b31802023-10-06 16:59:46 +02001026 ret = mbedtls_gcm_update(&ctx,
1027 pt_test_data[pt_index_test_data[i]] + 32,
1028 rest_len,
1029 buf + 32, sizeof(buf) - 32, &olen);
1030 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001031 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001032 }
1033 if (olen != rest_len) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001034 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001035 }
1036 } else {
1037 ret = mbedtls_gcm_update(&ctx,
1038 pt_test_data[pt_index_test_data[i]],
1039 pt_len_test_data[i],
1040 buf, sizeof(buf), &olen);
1041 if (ret != 0) {
1042 goto exit;
1043 }
1044 if (olen != pt_len_test_data[i]) {
1045 goto exit;
1046 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001047 }
1048
Jens Wiklander32b31802023-10-06 16:59:46 +02001049 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1050 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001051 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001052 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001053
Jens Wiklander32b31802023-10-06 16:59:46 +02001054 if (memcmp(buf, ct_test_data[j * 6 + i],
1055 pt_len_test_data[i]) != 0 ||
1056 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001057 ret = 1;
1058 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +02001059 }
1060
Jens Wiklander32b31802023-10-06 16:59:46 +02001061 mbedtls_gcm_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +02001062
Jens Wiklander32b31802023-10-06 16:59:46 +02001063 if (verbose != 0) {
1064 mbedtls_printf("passed\n");
1065 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001066
Jens Wiklander32b31802023-10-06 16:59:46 +02001067 mbedtls_gcm_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001068
Jens Wiklander32b31802023-10-06 16:59:46 +02001069 if (verbose != 0) {
1070 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1071 key_len, i, "dec");
1072 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001073
Jens Wiklander32b31802023-10-06 16:59:46 +02001074 ret = mbedtls_gcm_setkey(&ctx, cipher,
1075 key_test_data[key_index_test_data[i]],
1076 key_len);
1077 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001078 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001079 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001080
Jens Wiklander32b31802023-10-06 16:59:46 +02001081 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1082 iv_test_data[iv_index_test_data[i]],
1083 iv_len_test_data[i]);
1084 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001085 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001086 }
1087 ret = mbedtls_gcm_update_ad(&ctx,
1088 additional_test_data[add_index_test_data[i]],
1089 add_len_test_data[i]);
1090 if (ret != 0) {
1091 goto exit;
1092 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001093
Jens Wiklander32b31802023-10-06 16:59:46 +02001094 if (pt_len_test_data[i] > 32) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001095 size_t rest_len = pt_len_test_data[i] - 32;
Jens Wiklander32b31802023-10-06 16:59:46 +02001096 ret = mbedtls_gcm_update(&ctx,
1097 ct_test_data[j * 6 + i], 32,
1098 buf, sizeof(buf), &olen);
1099 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001100 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001101 }
1102 if (olen != 32) {
1103 goto exit;
1104 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001105
Jens Wiklander32b31802023-10-06 16:59:46 +02001106 ret = mbedtls_gcm_update(&ctx,
1107 ct_test_data[j * 6 + i] + 32,
1108 rest_len,
1109 buf + 32, sizeof(buf) - 32, &olen);
1110 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001111 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001112 }
1113 if (olen != rest_len) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001114 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001115 }
1116 } else {
1117 ret = mbedtls_gcm_update(&ctx,
1118 ct_test_data[j * 6 + i],
1119 pt_len_test_data[i],
1120 buf, sizeof(buf), &olen);
1121 if (ret != 0) {
1122 goto exit;
1123 }
1124 if (olen != pt_len_test_data[i]) {
1125 goto exit;
1126 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001127 }
1128
Jens Wiklander32b31802023-10-06 16:59:46 +02001129 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1130 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001131 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +02001132 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001133
Jens Wiklander32b31802023-10-06 16:59:46 +02001134 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1135 pt_len_test_data[i]) != 0 ||
1136 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001137 ret = 1;
1138 goto exit;
Jens Wiklander817466c2018-05-22 13:49:31 +02001139 }
1140
Jens Wiklander32b31802023-10-06 16:59:46 +02001141 mbedtls_gcm_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +02001142
Jens Wiklander32b31802023-10-06 16:59:46 +02001143 if (verbose != 0) {
1144 mbedtls_printf("passed\n");
1145 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001146 }
1147 }
1148
Jens Wiklander32b31802023-10-06 16:59:46 +02001149 if (verbose != 0) {
1150 mbedtls_printf("\n");
1151 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001152
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001153 ret = 0;
1154
1155exit:
Jens Wiklander32b31802023-10-06 16:59:46 +02001156 if (ret != 0) {
1157 if (verbose != 0) {
1158 mbedtls_printf("failed\n");
1159 }
1160 mbedtls_gcm_free(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001161 }
1162
Jens Wiklander32b31802023-10-06 16:59:46 +02001163 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001164}
1165
1166#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
1167
1168#endif /* MBEDTLS_GCM_C */