blob: 2740e848c8c93d4e9f24f12102d5eb01ef9b45a3 [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:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020024 * [MGV]
25 * http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010026 *
27 * We use the algorithm described as Shoup's method with 4-bit tables in
28 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000029 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010030
Gilles Peskinedb09ef62020-06-03 01:43:33 +020031#include "common.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000034
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020035# include "mbedtls/gcm.h"
36# include "mbedtls/platform_util.h"
37# include "mbedtls/error.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000038
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020039# include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000040
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020041# if defined(MBEDTLS_AESNI_C)
42# include "aesni.h"
43# endif
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010044
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020045# if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
46# include "mbedtls/aes.h"
47# include "mbedtls/platform.h"
48# if !defined(MBEDTLS_PLATFORM_C)
49# include <stdio.h>
50# define mbedtls_printf printf
51# endif /* MBEDTLS_PLATFORM_C */
52# endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020054# if !defined(MBEDTLS_GCM_ALT)
Jaeden Amero15263302017-09-21 12:53:48 +010055
k-stachowiak8ffc92a2018-12-12 14:21:59 +010056/* Parameter validation macros */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020057# define GCM_VALIDATE_RET(cond) \
58 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_GCM_BAD_INPUT)
59# define GCM_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond)
k-stachowiak8ffc92a2018-12-12 14:21:59 +010060
Paul Bakker89e80c92012-03-20 13:50:09 +000061/*
62 * 32-bit integer manipulation macros (big endian)
63 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020064# ifndef GET_UINT32_BE
65# define GET_UINT32_BE(n, b, i) \
66 { \
67 (n) = ((uint32_t)(b)[(i)] << 24) | \
68 ((uint32_t)(b)[(i) + 1] << 16) | \
69 ((uint32_t)(b)[(i) + 2] << 8) | \
70 ((uint32_t)(b)[(i) + 3]); \
71 }
72# endif
Paul Bakker89e80c92012-03-20 13:50:09 +000073
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020074# ifndef PUT_UINT32_BE
75# define PUT_UINT32_BE(n, b, i) \
76 { \
77 (b)[(i)] = (unsigned char)((n) >> 24); \
78 (b)[(i) + 1] = (unsigned char)((n) >> 16); \
79 (b)[(i) + 2] = (unsigned char)((n) >> 8); \
80 (b)[(i) + 3] = (unsigned char)((n)); \
81 }
82# endif
Paul Bakker89e80c92012-03-20 13:50:09 +000083
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010084/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020085 * Initialize a context
86 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020087void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020088{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020089 GCM_VALIDATE(ctx != NULL);
90 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020091}
92
93/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010094 * Precompute small multiples of H, that is set
95 * HH[i] || HL[i] = H times i,
96 * where i is seen as a field element as in [MGV], ie high-order bits
97 * correspond to low powers of P. The result is stored in the same way, that
98 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
99 * corresponds to P^127.
100 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200101static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +0000102{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200103 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000104 uint64_t hi, lo;
105 uint64_t vl, vh;
106 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200107 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200108
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200109 memset(h, 0, 16);
110 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0)
111 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000112
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100113 /* pack h as two 64-bits ints, big-endian */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200114 GET_UINT32_BE(hi, h, 0);
115 GET_UINT32_BE(lo, h, 4);
116 vh = (uint64_t)hi << 32 | lo;
Paul Bakker89e80c92012-03-20 13:50:09 +0000117
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200118 GET_UINT32_BE(hi, h, 8);
119 GET_UINT32_BE(lo, h, 12);
120 vl = (uint64_t)hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200121
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100122 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000123 ctx->HL[8] = vl;
124 ctx->HH[8] = vh;
125
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200126# if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100127 /* With CLMUL support, we need only h, not the rest of the table */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200128 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL))
129 return 0;
130# endif
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100131
132 /* 0 corresponds to 0 in GF(2^128) */
133 ctx->HH[0] = 0;
134 ctx->HL[0] = 0;
135
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200136 for (i = 4; i > 0; i >>= 1) {
137 uint32_t T = (vl & 1) * 0xe1000000U;
138 vl = (vh << 63) | (vl >> 1);
139 vh = (vh >> 1) ^ ((uint64_t)T << 32);
Paul Bakker89e80c92012-03-20 13:50:09 +0000140
141 ctx->HL[i] = vl;
142 ctx->HH[i] = vh;
143 }
144
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200145 for (i = 2; i <= 8; i *= 2) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000146 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
147 vh = *HiH;
148 vl = *HiL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200149 for (j = 1; j < i; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000150 HiH[j] = vh ^ ctx->HH[j];
151 HiL[j] = vl ^ ctx->HL[j];
152 }
153 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200154
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200155 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000156}
157
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200158int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
159 mbedtls_cipher_id_t cipher,
160 const unsigned char *key,
161 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000162{
Janos Follath24eed8d2019-11-22 13:21:35 +0000163 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000165
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200166 GCM_VALIDATE_RET(ctx != NULL);
167 GCM_VALIDATE_RET(key != NULL);
168 GCM_VALIDATE_RET(keybits == 128 || keybits == 192 || keybits == 256);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100169
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200170 cipher_info =
171 mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB);
172 if (cipher_info == NULL)
173 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200174
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200175 if (cipher_info->block_size != 16)
176 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakkera0558e02013-09-10 14:25:51 +0200177
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200178 mbedtls_cipher_free(&ctx->cipher_ctx);
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200179
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200180 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0)
181 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000182
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200183 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
184 MBEDTLS_ENCRYPT)) != 0) {
185 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200186 }
187
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200188 if ((ret = gcm_gen_table(ctx)) != 0)
189 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000190
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200191 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000192}
193
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100194/*
195 * Shoup's method for multiplication use this table with
196 * last4[x] = x times P^128
197 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
198 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200199static const uint64_t last4[16] = { 0x0000, 0x1c20, 0x3840, 0x2460,
200 0x7080, 0x6ca0, 0x48c0, 0x54e0,
201 0xe100, 0xfd20, 0xd940, 0xc560,
202 0x9180, 0x8da0, 0xa9c0, 0xb5e0 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000203
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100204/*
205 * Sets output to x times H using the precomputed tables.
206 * x and output are seen as elements of GF(2^128) as in [MGV].
207 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200208static void gcm_mult(mbedtls_gcm_context *ctx,
209 const unsigned char x[16],
210 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000211{
212 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000213 unsigned char lo, hi, rem;
214 uint64_t zh, zl;
215
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200216# if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
217 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100218 unsigned char h[16];
219
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200220 PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
221 PUT_UINT32_BE(ctx->HH[8], h, 4);
222 PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
223 PUT_UINT32_BE(ctx->HL[8], h, 12);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100224
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200225 mbedtls_aesni_gcm_mult(output, x, h);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100226 return;
227 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200228# endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100229
Paul Bakker89e80c92012-03-20 13:50:09 +0000230 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000231
232 zh = ctx->HH[lo];
233 zl = ctx->HL[lo];
234
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200235 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000236 lo = x[i] & 0xf;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200237 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000238
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200239 if (i != 15) {
240 rem = (unsigned char)zl & 0xf;
241 zl = (zh << 60) | (zl >> 4);
242 zh = (zh >> 4);
243 zh ^= (uint64_t)last4[rem] << 48;
Paul Bakker89e80c92012-03-20 13:50:09 +0000244 zh ^= ctx->HH[lo];
245 zl ^= ctx->HL[lo];
Paul Bakker89e80c92012-03-20 13:50:09 +0000246 }
247
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200248 rem = (unsigned char)zl & 0xf;
249 zl = (zh << 60) | (zl >> 4);
250 zh = (zh >> 4);
251 zh ^= (uint64_t)last4[rem] << 48;
Paul Bakker89e80c92012-03-20 13:50:09 +0000252 zh ^= ctx->HH[hi];
253 zl ^= ctx->HL[hi];
254 }
255
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200256 PUT_UINT32_BE(zh >> 32, output, 0);
257 PUT_UINT32_BE(zh, output, 4);
258 PUT_UINT32_BE(zl >> 32, output, 8);
259 PUT_UINT32_BE(zl, output, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000260}
261
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200262int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
263 int mode,
264 const unsigned char *iv,
265 size_t iv_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000266{
Janos Follath24eed8d2019-11-22 13:21:35 +0000267 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000268 unsigned char work_buf[16];
269 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000270 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200271 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000272
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200273 GCM_VALIDATE_RET(ctx != NULL);
274 GCM_VALIDATE_RET(iv != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100275
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200276 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200277 /* IV is not allowed to be zero length */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200278 if (iv_len == 0 || (uint64_t)iv_len >> 61 != 0)
279 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200280
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200281 memset(ctx->y, 0x00, sizeof(ctx->y));
282 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200283
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200284 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200285 ctx->len = 0;
286 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000287
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200288 if (iv_len == 12) {
289 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200290 ctx->y[15] = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200291 } else {
292 memset(work_buf, 0x00, 16);
293 PUT_UINT32_BE(iv_len * 8, work_buf, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000294
295 p = iv;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200296 while (iv_len > 0) {
297 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000298
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200299 for (i = 0; i < use_len; i++)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200300 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200301
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200302 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000303
304 iv_len -= use_len;
305 p += use_len;
306 }
307
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200308 for (i = 0; i < 16; i++)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200309 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000310
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200311 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000312 }
313
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200314 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
315 ctx->base_ectr, &olen)) != 0) {
316 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200317 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000318
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200319 return 0;
Gilles Peskine295fc132021-04-15 18:32:23 +0200320}
321
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200322/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200323 * mbedtls_gcm_context::buf contains the partial state of the computation of
324 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200325 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
326 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200327 * * len == 0 && add_len == 0: initial state
328 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
329 * a partial block of AD that has been
330 * xored in but not yet multiplied in.
331 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
332 * the data ends now.
333 * * len % 16 != 0: the first `len % 16` bytes have
334 * a partial block of ciphertext that has
335 * been xored in but not yet multiplied in.
336 * * len > 0 && len % 16 == 0: the authentication tag is correct if
337 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200338 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200339int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
340 const unsigned char *add,
341 size_t add_len)
Gilles Peskine295fc132021-04-15 18:32:23 +0200342{
343 const unsigned char *p;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200344 size_t use_len, i, offset;
Gilles Peskine295fc132021-04-15 18:32:23 +0200345
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200346 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
Gilles Peskine295fc132021-04-15 18:32:23 +0200347
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200348 /* IV is limited to 2^64 bits, so 2^61 bytes */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200349 if ((uint64_t)add_len >> 61 != 0)
350 return MBEDTLS_ERR_GCM_BAD_INPUT;
Gilles Peskine295fc132021-04-15 18:32:23 +0200351
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200352 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000353 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200354
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200355 if (offset != 0) {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200356 use_len = 16 - offset;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200357 if (use_len > add_len)
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200358 use_len = add_len;
359
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200360 for (i = 0; i < use_len; i++)
361 ctx->buf[i + offset] ^= p[i];
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200362
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200363 if (offset + use_len == 16)
364 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200365
366 ctx->add_len += use_len;
367 add_len -= use_len;
368 p += use_len;
369 }
370
371 ctx->add_len += add_len;
372
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200373 while (add_len >= 16) {
374 for (i = 0; i < 16; i++)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200375 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200376
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200377 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000378
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200379 add_len -= 16;
380 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000381 }
382
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200383 if (add_len > 0) {
384 for (i = 0; i < add_len; i++)
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200385 ctx->buf[i] ^= p[i];
386 }
387
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200388 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200389}
390
Gilles Peskine58fc2722021-04-13 15:58:27 +0200391/* Increment the counter. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200392static void gcm_incr(unsigned char y[16])
Gilles Peskine58fc2722021-04-13 15:58:27 +0200393{
394 size_t i;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200395 for (i = 16; i > 12; i--)
396 if (++y[i - 1] != 0)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200397 break;
398}
399
400/* Calculate and apply the encryption mask. Process use_len bytes of data,
401 * starting at position offset in the mask block. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200402static int gcm_mask(mbedtls_gcm_context *ctx,
403 unsigned char ectr[16],
404 size_t offset,
405 size_t use_len,
406 const unsigned char *input,
407 unsigned char *output)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200408{
409 size_t i;
410 size_t olen = 0;
411 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
412
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200413 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
414 &olen)) != 0) {
415 mbedtls_platform_zeroize(ectr, 16);
416 return ret;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200417 }
418
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200419 for (i = 0; i < use_len; i++) {
420 if (ctx->mode == MBEDTLS_GCM_DECRYPT)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200421 ctx->buf[offset + i] ^= input[i];
422 output[i] = ectr[offset + i] ^ input[i];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200423 if (ctx->mode == MBEDTLS_GCM_ENCRYPT)
Gilles Peskine58fc2722021-04-13 15:58:27 +0200424 ctx->buf[offset + i] ^= output[i];
425 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200426 return 0;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200427}
428
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200429int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
430 const unsigned char *input,
431 size_t input_length,
432 unsigned char *output,
433 size_t output_size,
434 size_t *output_length)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200435{
Janos Follath24eed8d2019-11-22 13:21:35 +0000436 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200437 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200438 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200439 size_t offset;
440 unsigned char ectr[16];
441
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200442 if (output_size < input_length)
443 return MBEDTLS_ERR_GCM_BAD_INPUT;
444 GCM_VALIDATE_RET(output_length != NULL);
Gilles Peskinea56c4482021-04-15 17:22:35 +0200445 *output_length = input_length;
446
447 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200448 * on a potentially null pointer.
449 * Returning early also means that the last partial block of AD remains
450 * untouched for mbedtls_gcm_finish */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200451 if (input_length == 0)
452 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200453
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200454 GCM_VALIDATE_RET(ctx != NULL);
455 GCM_VALIDATE_RET(input != NULL);
456 GCM_VALIDATE_RET(output != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100457
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200458 if (output > input && (size_t)(output - input) < input_length)
459 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200460
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200461 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
462 * Also check for possible overflow */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200463 if (ctx->len + input_length < ctx->len ||
464 (uint64_t)ctx->len + input_length > 0xFFFFFFFE0ull) {
465 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200466 }
467
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200468 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
469 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200470 }
471
Gilles Peskine58fc2722021-04-13 15:58:27 +0200472 offset = ctx->len % 16;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200473 if (offset != 0) {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200474 size_t use_len = 16 - offset;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200475 if (use_len > input_length)
Gilles Peskinea56c4482021-04-15 17:22:35 +0200476 use_len = input_length;
Paul Bakker89e80c92012-03-20 13:50:09 +0000477
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200478 if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0)
479 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000480
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200481 if (offset + use_len == 16)
482 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker169b7f42013-06-25 14:58:00 +0200483
Gilles Peskine58fc2722021-04-13 15:58:27 +0200484 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200485 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000486 p += use_len;
487 out_p += use_len;
488 }
489
Gilles Peskinea56c4482021-04-15 17:22:35 +0200490 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200491
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200492 while (input_length >= 16) {
493 gcm_incr(ctx->y);
494 if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0)
495 return ret;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200496
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200497 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200498
Gilles Peskinea56c4482021-04-15 17:22:35 +0200499 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200500 p += 16;
501 out_p += 16;
502 }
503
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200504 if (input_length > 0) {
505 gcm_incr(ctx->y);
506 if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0)
507 return ret;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200508 }
509
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200510 mbedtls_platform_zeroize(ectr, sizeof(ectr));
511 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200512}
513
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200514int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
515 unsigned char *output,
516 size_t output_size,
517 size_t *output_length,
518 unsigned char *tag,
519 size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200520{
521 unsigned char work_buf[16];
522 size_t i;
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100523 uint64_t orig_len;
524 uint64_t orig_add_len;
525
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200526 GCM_VALIDATE_RET(ctx != NULL);
527 GCM_VALIDATE_RET(tag != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100528
Gilles Peskine9461e452021-04-15 16:48:32 +0200529 /* We never pass any output in finish(). The output parameter exists only
530 * for the sake of alternative implementations. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200531 (void)output;
532 (void)output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200533 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200534
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100535 orig_len = ctx->len * 8;
536 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200537
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200538 if (ctx->len == 0 && ctx->add_len % 16 != 0) {
539 gcm_mult(ctx, ctx->buf, ctx->buf);
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200540 }
541
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200542 if (tag_len > 16 || tag_len < 4)
543 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200544
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200545 if (ctx->len % 16 != 0)
546 gcm_mult(ctx, ctx->buf, ctx->buf);
Gilles Peskine58fc2722021-04-13 15:58:27 +0200547
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200548 memcpy(tag, ctx->base_ectr, tag_len);
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200549
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200550 if (orig_len || orig_add_len) {
551 memset(work_buf, 0x00, 16);
Paul Bakker89e80c92012-03-20 13:50:09 +0000552
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200553 PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
554 PUT_UINT32_BE((orig_add_len), work_buf, 4);
555 PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
556 PUT_UINT32_BE((orig_len), work_buf, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000557
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200558 for (i = 0; i < 16; i++)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200559 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000560
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200561 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000562
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200563 for (i = 0; i < tag_len; i++)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200564 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000565 }
566
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200567 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000568}
569
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200570int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
571 int mode,
572 size_t length,
573 const unsigned char *iv,
574 size_t iv_len,
575 const unsigned char *add,
576 size_t add_len,
577 const unsigned char *input,
578 unsigned char *output,
579 size_t tag_len,
580 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200581{
Janos Follath24eed8d2019-11-22 13:21:35 +0000582 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200583 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200584
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200585 GCM_VALIDATE_RET(ctx != NULL);
586 GCM_VALIDATE_RET(iv != NULL);
587 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
588 GCM_VALIDATE_RET(length == 0 || input != NULL);
589 GCM_VALIDATE_RET(length == 0 || output != NULL);
590 GCM_VALIDATE_RET(tag != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100591
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200592 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0)
593 return ret;
Gilles Peskine295fc132021-04-15 18:32:23 +0200594
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200595 if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0)
596 return ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200597
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200598 if ((ret = mbedtls_gcm_update(ctx, input, length, output, length, &olen)) !=
599 0)
600 return ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200601
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200602 if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0)
603 return ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200604
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200605 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200606}
607
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200608int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
609 size_t length,
610 const unsigned char *iv,
611 size_t iv_len,
612 const unsigned char *add,
613 size_t add_len,
614 const unsigned char *tag,
615 size_t tag_len,
616 const unsigned char *input,
617 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000618{
Janos Follath24eed8d2019-11-22 13:21:35 +0000619 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000620 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200621 size_t i;
622 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000623
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200624 GCM_VALIDATE_RET(ctx != NULL);
625 GCM_VALIDATE_RET(iv != NULL);
626 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
627 GCM_VALIDATE_RET(tag != NULL);
628 GCM_VALIDATE_RET(length == 0 || input != NULL);
629 GCM_VALIDATE_RET(length == 0 || output != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100630
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200631 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length, iv,
632 iv_len, add, add_len, input, output,
633 tag_len, check_tag)) != 0) {
634 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100635 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000636
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200637 /* Check tag in "constant-time" */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200638 for (diff = 0, i = 0; i < tag_len; i++)
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200639 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000640
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200641 if (diff != 0) {
642 mbedtls_platform_zeroize(output, length);
643 return MBEDTLS_ERR_GCM_AUTH_FAILED;
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200644 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000645
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200646 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000647}
648
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200649void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200650{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200651 if (ctx == NULL)
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100652 return;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200653 mbedtls_cipher_free(&ctx->cipher_ctx);
654 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200655}
656
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200657# endif /* !MBEDTLS_GCM_ALT */
Jaeden Amero15263302017-09-21 12:53:48 +0100658
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200659# if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000660/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200661 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 *
663 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
664 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200665# define MAX_TESTS 6
Paul Bakker89e80c92012-03-20 13:50:09 +0000666
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200667static const int key_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000668
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200669static const unsigned char key_test_data[MAX_TESTS][32] = {
670 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
673 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f,
674 0x94, 0x67, 0x30, 0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65,
675 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000676};
677
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200678static const size_t iv_len_test_data[MAX_TESTS] = { 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000679
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200680static const int iv_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000681
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200682static const unsigned char iv_test_data[MAX_TESTS][64] = {
683 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
684 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 },
685 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a,
686 0xff, 0x52, 0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
687 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51,
688 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
689 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, 0xa6, 0x37, 0xb3, 0x9b },
690};
691
692static const size_t add_len_test_data[MAX_TESTS] = { 0, 0, 0, 20, 20, 20 };
693
694static const int add_index_test_data[MAX_TESTS] = { 0, 0, 0, 1, 1, 1 };
695
696static const unsigned char additional_test_data[MAX_TESTS][64] = {
697 { 0x00 },
698 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed,
699 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 },
700};
701
702static const size_t pt_len_test_data[MAX_TESTS] = { 0, 16, 64, 60, 60, 60 };
703
704static const int pt_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 };
705
706static const unsigned char pt_test_data[MAX_TESTS][64] = {
707 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Paul Bakker89e80c92012-03-20 13:50:09 +0000708 0x00, 0x00, 0x00, 0x00 },
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200709 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09,
710 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34,
711 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c,
712 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24,
713 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6,
714 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000715};
716
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200717static const unsigned char ct_test_data[MAX_TESTS * 3][64] = {
Paul Bakker89e80c92012-03-20 13:50:09 +0000718 { 0x00 },
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200719 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9,
720 0x71, 0xb2, 0xfe, 0x78 },
721 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21,
722 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02,
723 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21,
724 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a,
725 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac,
726 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
727 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7,
728 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
729 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2,
730 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
731 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91 },
732 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f,
733 0xa2, 0x2a, 0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
734 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00,
735 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
736 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, 0xc2, 0x3f, 0x45, 0x98 },
737 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac,
738 0xa1, 0x3f, 0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
739 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4,
740 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
741 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 0x4c, 0x34, 0xae, 0xe5 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000742 { 0x00 },
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200743 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 0x1c, 0x26, 0x7e, 0x43,
744 0x84, 0xb0, 0xf6, 0x00 },
745 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa,
746 0xc4, 0x87, 0x2a, 0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef,
747 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 0x7d,
748 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61, 0x9d, 0x18,
749 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24,
750 0xd9, 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
751 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4,
752 0x87, 0x2a, 0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
753 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00,
754 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
755 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 0xcc, 0xda, 0x27, 0x10 },
756 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 0xed, 0x24, 0xb3, 0x6e,
757 0x25, 0x32, 0x4d, 0xb8, 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
758 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, 0xfd, 0xdc, 0x29, 0xdf,
759 0x9a, 0x47, 0x1f, 0x75, 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
760 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, 0xa0, 0xf0, 0x62, 0xf7 },
761 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 0x48, 0x30, 0x16, 0x5a,
762 0x8f, 0xdc, 0xf9, 0xff, 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
763 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, 0x81, 0xe7, 0x90, 0x12,
764 0xaf, 0x34, 0xdd, 0xd9, 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
765 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000766 { 0x00 },
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200767 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3,
768 0xba, 0xf3, 0x9d, 0x18 },
769 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37,
770 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5,
771 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c,
772 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10,
773 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a,
774 0x0a, 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
775 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3,
776 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
777 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48,
778 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
779 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62 },
780 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b,
781 0xf1, 0x98, 0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
782 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3,
783 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
784 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, 0xf4, 0x7c, 0x9b, 0x1f },
785 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53,
786 0x65, 0x9e, 0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
787 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7,
788 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
789 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000790};
791
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200792static const unsigned char tag_test_data[MAX_TESTS * 3][16] = {
793 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57,
794 0xa4, 0xe7, 0x45, 0x5a },
795 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2,
796 0x12, 0x57, 0xbd, 0xdf },
797 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd,
798 0x2b, 0xa6, 0xfa, 0xb4 },
799 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a,
800 0xe7, 0x12, 0x1a, 0x47 },
801 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a,
802 0xac, 0xa2, 0xfc, 0xcb },
803 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c,
804 0x16, 0x99, 0xd0, 0x50 },
805 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 0xa0, 0x0e, 0xd1, 0xf3,
806 0x12, 0x57, 0x24, 0x35 },
807 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58,
808 0x75, 0x14, 0xf0, 0xfb },
809 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, 0xb1, 0x18, 0x02, 0x4d,
810 0xb8, 0x67, 0x4a, 0x14 },
811 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, 0x37, 0xba, 0x55, 0xbd,
812 0x6d, 0x27, 0x61, 0x8c },
813 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, 0x09, 0x4f, 0xcc, 0xa4,
814 0x0d, 0x35, 0x33, 0xf8 },
815 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3,
816 0xd3, 0x76, 0xa6, 0xd9 },
817 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1,
818 0xc4, 0xcb, 0x73, 0x8b },
819 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 0x26, 0x5b, 0x98, 0xb5,
820 0xd4, 0x8a, 0xb9, 0x19 },
821 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 0xec, 0x1a, 0x50, 0x22,
822 0x70, 0xe3, 0xcc, 0x6c },
823 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53,
824 0xbb, 0x2d, 0x55, 0x1b },
825 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13,
826 0xfe, 0x2e, 0xa8, 0xf2 },
827 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf,
828 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000829};
830
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200831int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000832{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000834 unsigned char buf[64];
835 unsigned char tag_buf[16];
836 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200838 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +0000839
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200840 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000841 int key_len = 128 + 64 * j;
842
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200843 for (i = 0; i < MAX_TESTS; i++) {
844 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100845
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200846 if (verbose != 0)
847 mbedtls_printf(" AES-GCM-%3d #%d (%s): ", key_len, i, "enc");
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200848
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200849 ret = mbedtls_gcm_setkey(
850 &ctx, cipher, key_test_data[key_index_test_data[i]], key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100851 /*
852 * AES-192 is an optional feature that may be unavailable when
853 * there is an alternative underlying implementation i.e. when
854 * MBEDTLS_AES_ALT is defined.
855 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200856 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
857 key_len == 192) {
858 mbedtls_printf("skipped\n");
859 break;
860 } else if (ret != 0) {
861 goto exit;
862 }
863
864 ret = mbedtls_gcm_crypt_and_tag(
865 &ctx, MBEDTLS_GCM_ENCRYPT, pt_len_test_data[i],
866 iv_test_data[iv_index_test_data[i]], iv_len_test_data[i],
867 additional_test_data[add_index_test_data[i]],
868 add_len_test_data[i], pt_test_data[pt_index_test_data[i]], buf,
869 16, tag_buf);
870# if defined(MBEDTLS_GCM_ALT)
871 /* Allow alternative implementations to only support 12-byte nonces.
872 */
873 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
874 iv_len_test_data[i] != 12) {
875 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100876 break;
877 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200878# endif /* defined(MBEDTLS_GCM_ALT) */
879 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100880 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000881
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200882 if (memcmp(buf, ct_test_data[j * 6 + i], pt_len_test_data[i]) !=
883 0 ||
884 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100885 ret = 1;
886 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000887 }
888
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200889 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200890
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200891 if (verbose != 0)
892 mbedtls_printf("passed\n");
Paul Bakker89e80c92012-03-20 13:50:09 +0000893
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200894 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100895
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200896 if (verbose != 0)
897 mbedtls_printf(" AES-GCM-%3d #%d (%s): ", key_len, i, "dec");
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200898
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200899 ret = mbedtls_gcm_setkey(
900 &ctx, cipher, key_test_data[key_index_test_data[i]], key_len);
901 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100902 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000903
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200904 ret = mbedtls_gcm_crypt_and_tag(
905 &ctx, MBEDTLS_GCM_DECRYPT, pt_len_test_data[i],
906 iv_test_data[iv_index_test_data[i]], iv_len_test_data[i],
907 additional_test_data[add_index_test_data[i]],
908 add_len_test_data[i], ct_test_data[j * 6 + i], buf, 16,
909 tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000910
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200911 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100912 goto exit;
913
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200914 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
915 pt_len_test_data[i]) != 0 ||
916 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100917 ret = 1;
918 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000919 }
920
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200921 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200922
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200923 if (verbose != 0)
924 mbedtls_printf("passed\n");
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200925
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200926 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100927
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200928 if (verbose != 0)
929 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ", key_len, i,
930 "enc");
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200931
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200932 ret = mbedtls_gcm_setkey(
933 &ctx, cipher, key_test_data[key_index_test_data[i]], key_len);
934 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100935 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200936
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200937 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
938 iv_test_data[iv_index_test_data[i]],
939 iv_len_test_data[i]);
940 if (ret != 0)
Gilles Peskine295fc132021-04-15 18:32:23 +0200941 goto exit;
942
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200943 ret = mbedtls_gcm_update_ad(
944 &ctx, additional_test_data[add_index_test_data[i]],
945 add_len_test_data[i]);
946 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100947 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200948
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200949 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100950 size_t rest_len = pt_len_test_data[i] - 32;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200951 ret = mbedtls_gcm_update(&ctx,
952 pt_test_data[pt_index_test_data[i]],
953 32, buf, sizeof(buf), &olen);
954 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100955 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200956 if (olen != 32)
Gilles Peskinea56c4482021-04-15 17:22:35 +0200957 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200958
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200959 ret = mbedtls_gcm_update(
960 &ctx, pt_test_data[pt_index_test_data[i]] + 32, rest_len,
961 buf + 32, sizeof(buf) - 32, &olen);
962 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100963 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200964 if (olen != rest_len)
Gilles Peskinea56c4482021-04-15 17:22:35 +0200965 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200966 } else {
967 ret = mbedtls_gcm_update(&ctx,
968 pt_test_data[pt_index_test_data[i]],
969 pt_len_test_data[i], buf, sizeof(buf),
970 &olen);
971 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100972 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200973 if (olen != pt_len_test_data[i])
Gilles Peskinea56c4482021-04-15 17:22:35 +0200974 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200975 }
976
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200977 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
978 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100979 goto exit;
980
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200981 if (memcmp(buf, ct_test_data[j * 6 + i], pt_len_test_data[i]) !=
982 0 ||
983 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100984 ret = 1;
985 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200986 }
987
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200988 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200989
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200990 if (verbose != 0)
991 mbedtls_printf("passed\n");
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200992
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200993 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100994
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200995 if (verbose != 0)
996 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ", key_len, i,
997 "dec");
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200998
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200999 ret = mbedtls_gcm_setkey(
1000 &ctx, cipher, key_test_data[key_index_test_data[i]], key_len);
1001 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001002 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001003
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001004 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1005 iv_test_data[iv_index_test_data[i]],
1006 iv_len_test_data[i]);
1007 if (ret != 0)
Gilles Peskine295fc132021-04-15 18:32:23 +02001008 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001009 ret = mbedtls_gcm_update_ad(
1010 &ctx, additional_test_data[add_index_test_data[i]],
1011 add_len_test_data[i]);
1012 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001013 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001014
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001015 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001016 size_t rest_len = pt_len_test_data[i] - 32;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001017 ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i], 32, buf,
1018 sizeof(buf), &olen);
1019 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001020 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001021 if (olen != 32)
Gilles Peskinea56c4482021-04-15 17:22:35 +02001022 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001023
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001024 ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i] + 32,
1025 rest_len, buf + 32, sizeof(buf) - 32,
1026 &olen);
1027 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001028 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001029 if (olen != rest_len)
Gilles Peskinea56c4482021-04-15 17:22:35 +02001030 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001031 } else {
1032 ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i],
1033 pt_len_test_data[i], buf, sizeof(buf),
1034 &olen);
1035 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001036 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001037 if (olen != pt_len_test_data[i])
Gilles Peskinea56c4482021-04-15 17:22:35 +02001038 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001039 }
1040
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001041 ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1042 if (ret != 0)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001043 goto exit;
1044
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001045 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1046 pt_len_test_data[i]) != 0 ||
1047 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001048 ret = 1;
1049 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001050 }
1051
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001052 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001053
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001054 if (verbose != 0)
1055 mbedtls_printf("passed\n");
Paul Bakker89e80c92012-03-20 13:50:09 +00001056 }
1057 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001058
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001059 if (verbose != 0)
1060 mbedtls_printf("\n");
Paul Bakker89e80c92012-03-20 13:50:09 +00001061
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001062 ret = 0;
1063
1064exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001065 if (ret != 0) {
1066 if (verbose != 0)
1067 mbedtls_printf("failed\n");
1068 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001069 }
1070
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001071 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001072}
1073
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001074# endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001076#endif /* MBEDTLS_GCM_C */