blob: 71e7b2e9bc020d37ca26d922c109282312dd7324 [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker89e80c92012-03-20 13:50:09 +000018 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010019
Paul Bakker89e80c92012-03-20 13:50:09 +000020/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010021 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
22 *
23 * See also:
24 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
25 *
26 * We use the algorithm described as Shoup's method with 4-bit tables in
27 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000028 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010029
Gilles Peskinedb09ef62020-06-03 01:43:33 +020030#include "common.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/gcm.h"
Gilles Peskine7705a462022-09-15 20:14:22 +020035#include "mbedtls/platform.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050036#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000037#include "mbedtls/error.h"
Dave Rodgmanc2805202023-09-11 18:25:16 +010038#include "mbedtls/constant_time.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000039
Rich Evans00ab4702015-02-06 13:43:58 +000040#include <string.h>
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_AESNI_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010044#endif
45
Jaeden Amero15263302017-09-21 12:53:48 +010046#if !defined(MBEDTLS_GCM_ALT)
47
k-stachowiak8ffc92a2018-12-12 14:21:59 +010048/* Parameter validation macros */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010049#define GCM_VALIDATE_RET(cond) \
50 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_GCM_BAD_INPUT)
51#define GCM_VALIDATE(cond) \
52 MBEDTLS_INTERNAL_VALIDATE(cond)
k-stachowiak8ffc92a2018-12-12 14:21:59 +010053
Paul Bakker89e80c92012-03-20 13:50:09 +000054/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020055 * Initialize a context
56 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010057void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020058{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010059 GCM_VALIDATE(ctx != NULL);
60 memset(ctx, 0, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020061}
62
63/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010064 * Precompute small multiples of H, that is set
65 * HH[i] || HL[i] = H times i,
66 * where i is seen as a field element as in [MGV], ie high-order bits
67 * correspond to low powers of P. The result is stored in the same way, that
68 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
69 * corresponds to P^127.
70 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010071static int gcm_gen_table(mbedtls_gcm_context *ctx)
Paul Bakker89e80c92012-03-20 13:50:09 +000072{
Paul Bakker43aff2a2013-09-09 00:10:27 +020073 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000074 uint64_t hi, lo;
75 uint64_t vl, vh;
76 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020077 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020078
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010079 memset(h, 0, 16);
80 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
81 return ret;
82 }
Paul Bakker89e80c92012-03-20 13:50:09 +000083
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010084 /* pack h as two 64-bits ints, big-endian */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010085 hi = MBEDTLS_GET_UINT32_BE(h, 0);
86 lo = MBEDTLS_GET_UINT32_BE(h, 4);
Paul Bakker89e80c92012-03-20 13:50:09 +000087 vh = (uint64_t) hi << 32 | lo;
88
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010089 hi = MBEDTLS_GET_UINT32_BE(h, 8);
90 lo = MBEDTLS_GET_UINT32_BE(h, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +000091 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020092
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010093 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000094 ctx->HL[8] = vl;
95 ctx->HH[8] = vh;
96
Gilles Peskine5511a342023-03-10 22:29:32 +010097#if defined(MBEDTLS_AESNI_HAVE_CODE)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010098 /* With CLMUL support, we need only h, not the rest of the table */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010099 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
100 return 0;
101 }
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100102#endif
103
104 /* 0 corresponds to 0 in GF(2^128) */
105 ctx->HH[0] = 0;
106 ctx->HL[0] = 0;
107
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100108 for (i = 4; i > 0; i >>= 1) {
109 uint32_t T = (vl & 1) * 0xe1000000U;
110 vl = (vh << 63) | (vl >> 1);
111 vh = (vh >> 1) ^ ((uint64_t) T << 32);
Paul Bakker89e80c92012-03-20 13:50:09 +0000112
113 ctx->HL[i] = vl;
114 ctx->HH[i] = vh;
115 }
116
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100117 for (i = 2; i <= 8; i *= 2) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000118 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
119 vh = *HiH;
120 vl = *HiL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100121 for (j = 1; j < i; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000122 HiH[j] = vh ^ ctx->HH[j];
123 HiL[j] = vl ^ ctx->HL[j];
124 }
125 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200126
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100127 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000128}
129
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100130int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
131 mbedtls_cipher_id_t cipher,
132 const unsigned char *key,
133 unsigned int keybits)
Paul Bakker89e80c92012-03-20 13:50:09 +0000134{
Janos Follath24eed8d2019-11-22 13:21:35 +0000135 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000137
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100138 GCM_VALIDATE_RET(ctx != NULL);
139 GCM_VALIDATE_RET(key != NULL);
140 GCM_VALIDATE_RET(keybits == 128 || keybits == 192 || keybits == 256);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100141
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100142 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
143 MBEDTLS_MODE_ECB);
144 if (cipher_info == NULL) {
145 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200146 }
147
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100148 if (cipher_info->block_size != 16) {
149 return MBEDTLS_ERR_GCM_BAD_INPUT;
150 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000151
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 mbedtls_cipher_free(&ctx->cipher_ctx);
153
154 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
155 return ret;
156 }
157
158 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
159 MBEDTLS_ENCRYPT)) != 0) {
160 return ret;
161 }
162
163 if ((ret = gcm_gen_table(ctx)) != 0) {
164 return ret;
165 }
166
167 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000168}
169
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100170/*
171 * Shoup's method for multiplication use this table with
172 * last4[x] = x times P^128
173 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
174 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000175static const uint64_t last4[16] =
176{
177 0x0000, 0x1c20, 0x3840, 0x2460,
178 0x7080, 0x6ca0, 0x48c0, 0x54e0,
179 0xe100, 0xfd20, 0xd940, 0xc560,
180 0x9180, 0x8da0, 0xa9c0, 0xb5e0
181};
182
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100183/*
184 * Sets output to x times H using the precomputed tables.
185 * x and output are seen as elements of GF(2^128) as in [MGV].
186 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100187static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
188 unsigned char output[16])
Paul Bakker89e80c92012-03-20 13:50:09 +0000189{
190 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000191 unsigned char lo, hi, rem;
192 uint64_t zh, zl;
193
Gilles Peskine5511a342023-03-10 22:29:32 +0100194#if defined(MBEDTLS_AESNI_HAVE_CODE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100195 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100196 unsigned char h[16];
197
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100198 MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
199 MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
200 MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
201 MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100202
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 mbedtls_aesni_gcm_mult(output, x, h);
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100204 return;
205 }
Gilles Peskine5511a342023-03-10 22:29:32 +0100206#endif /* MBEDTLS_AESNI_HAVE_CODE */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100207
Paul Bakker89e80c92012-03-20 13:50:09 +0000208 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000209
210 zh = ctx->HH[lo];
211 zl = ctx->HL[lo];
212
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100213 for (i = 15; i >= 0; i--) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000214 lo = x[i] & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100215 hi = (x[i] >> 4) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000216
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100217 if (i != 15) {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000218 rem = (unsigned char) zl & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 zl = (zh << 60) | (zl >> 4);
220 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000221 zh ^= (uint64_t) last4[rem] << 48;
222 zh ^= ctx->HH[lo];
223 zl ^= ctx->HL[lo];
224
225 }
226
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000227 rem = (unsigned char) zl & 0xf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100228 zl = (zh << 60) | (zl >> 4);
229 zh = (zh >> 4);
Paul Bakker89e80c92012-03-20 13:50:09 +0000230 zh ^= (uint64_t) last4[rem] << 48;
231 zh ^= ctx->HH[hi];
232 zl ^= ctx->HL[hi];
233 }
234
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100235 MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
236 MBEDTLS_PUT_UINT32_BE(zh, output, 4);
237 MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
238 MBEDTLS_PUT_UINT32_BE(zl, output, 12);
Paul Bakker89e80c92012-03-20 13:50:09 +0000239}
240
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100241int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
242 int mode,
243 const unsigned char *iv,
244 size_t iv_len,
245 const unsigned char *add,
246 size_t add_len)
Paul Bakker89e80c92012-03-20 13:50:09 +0000247{
Janos Follath24eed8d2019-11-22 13:21:35 +0000248 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000249 unsigned char work_buf[16];
250 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000251 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200252 size_t use_len, olen = 0;
openluopworld5d5f5202021-11-05 00:13:43 +0800253 uint64_t iv_bits;
Paul Bakker89e80c92012-03-20 13:50:09 +0000254
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100255 GCM_VALIDATE_RET(ctx != NULL);
256 GCM_VALIDATE_RET(iv != NULL);
257 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100258
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200259 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200260 /* IV is not allowed to be zero length */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100261 if (iv_len == 0 ||
262 ((uint64_t) iv_len) >> 61 != 0 ||
263 ((uint64_t) add_len) >> 61 != 0) {
264 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200265 }
266
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100267 memset(ctx->y, 0x00, sizeof(ctx->y));
268 memset(ctx->buf, 0x00, sizeof(ctx->buf));
Paul Bakker52cf16c2013-07-26 13:55:38 +0200269
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200270 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200271 ctx->len = 0;
272 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000273
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100274 if (iv_len == 12) {
275 memcpy(ctx->y, iv, iv_len);
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200276 ctx->y[15] = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100277 } else {
278 memset(work_buf, 0x00, 16);
279 iv_bits = (uint64_t) iv_len * 8;
280 MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
Paul Bakker89e80c92012-03-20 13:50:09 +0000281
282 p = iv;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100283 while (iv_len > 0) {
284 use_len = (iv_len < 16) ? iv_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000285
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286 for (i = 0; i < use_len; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200287 ctx->y[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100288 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200289
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100290 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000291
292 iv_len -= use_len;
293 p += use_len;
294 }
295
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100296 for (i = 0; i < 16; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200297 ctx->y[i] ^= work_buf[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100298 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000299
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100300 gcm_mult(ctx, ctx->y, ctx->y);
Paul Bakker89e80c92012-03-20 13:50:09 +0000301 }
302
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100303 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
304 ctx->base_ectr, &olen)) != 0) {
305 return ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200306 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000307
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200308 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000309 p = add;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100310 while (add_len > 0) {
311 use_len = (add_len < 16) ? add_len : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000312
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 for (i = 0; i < use_len; i++) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200314 ctx->buf[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100315 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200316
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100317 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000318
319 add_len -= use_len;
320 p += use_len;
321 }
322
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100323 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200324}
325
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100326int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
327 size_t length,
328 const unsigned char *input,
329 unsigned char *output)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200330{
Janos Follath24eed8d2019-11-22 13:21:35 +0000331 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200332 unsigned char ectr[16];
333 size_t i;
334 const unsigned char *p;
335 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200336 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200337
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100338 GCM_VALIDATE_RET(ctx != NULL);
339 GCM_VALIDATE_RET(length == 0 || input != NULL);
340 GCM_VALIDATE_RET(length == 0 || output != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100341
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100342 if (output > input && (size_t) (output - input) < length) {
343 return MBEDTLS_ERR_GCM_BAD_INPUT;
344 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200345
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200346 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
347 * Also check for possible overflow */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100348 if (ctx->len + length < ctx->len ||
349 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull) {
350 return MBEDTLS_ERR_GCM_BAD_INPUT;
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200351 }
352
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200353 ctx->len += length;
354
Paul Bakker89e80c92012-03-20 13:50:09 +0000355 p = input;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100356 while (length > 0) {
357 use_len = (length < 16) ? length : 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000358
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100359 for (i = 16; i > 12; i--) {
360 if (++ctx->y[i - 1] != 0) {
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000361 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100362 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200363 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000364
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100365 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
366 &olen)) != 0) {
367 return ret;
368 }
369
370 for (i = 0; i < use_len; i++) {
371 if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200372 ctx->buf[i] ^= p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100373 }
Paul Bakker67f9d532012-10-23 11:49:05 +0000374 out_p[i] = ectr[i] ^ p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100375 if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200376 ctx->buf[i] ^= out_p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100377 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000378 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200379
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100380 gcm_mult(ctx, ctx->buf, ctx->buf);
Paul Bakker169b7f42013-06-25 14:58:00 +0200381
Paul Bakker89e80c92012-03-20 13:50:09 +0000382 length -= use_len;
383 p += use_len;
384 out_p += use_len;
385 }
386
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100387 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200388}
389
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100390int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
391 unsigned char *tag,
392 size_t tag_len)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200393{
394 unsigned char work_buf[16];
395 size_t i;
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100396 uint64_t orig_len;
397 uint64_t orig_add_len;
398
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100399 GCM_VALIDATE_RET(ctx != NULL);
400 GCM_VALIDATE_RET(tag != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100401
402 orig_len = ctx->len * 8;
403 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200404
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100405 if (tag_len > 16 || tag_len < 4) {
406 return MBEDTLS_ERR_GCM_BAD_INPUT;
Paul Bakker89e80c92012-03-20 13:50:09 +0000407 }
408
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100409 memcpy(tag, ctx->base_ectr, tag_len);
410
411 if (orig_len || orig_add_len) {
412 memset(work_buf, 0x00, 16);
413
414 MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
415 MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
416 MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
417 MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
418
419 for (i = 0; i < 16; i++) {
420 ctx->buf[i] ^= work_buf[i];
421 }
422
423 gcm_mult(ctx, ctx->buf, ctx->buf);
424
425 for (i = 0; i < tag_len; i++) {
426 tag[i] ^= ctx->buf[i];
427 }
428 }
429
430 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000431}
432
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100433int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
434 int mode,
435 size_t length,
436 const unsigned char *iv,
437 size_t iv_len,
438 const unsigned char *add,
439 size_t add_len,
440 const unsigned char *input,
441 unsigned char *output,
442 size_t tag_len,
443 unsigned char *tag)
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200444{
Janos Follath24eed8d2019-11-22 13:21:35 +0000445 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200446
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447 GCM_VALIDATE_RET(ctx != NULL);
448 GCM_VALIDATE_RET(iv != NULL);
449 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
450 GCM_VALIDATE_RET(length == 0 || input != NULL);
451 GCM_VALIDATE_RET(length == 0 || output != NULL);
452 GCM_VALIDATE_RET(tag != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100453
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100454 if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len, add, add_len)) != 0) {
455 return ret;
456 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200457
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100458 if ((ret = mbedtls_gcm_update(ctx, length, input, output)) != 0) {
459 return ret;
460 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200461
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100462 if ((ret = mbedtls_gcm_finish(ctx, tag, tag_len)) != 0) {
463 return ret;
464 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200465
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100466 return 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200467}
468
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100469int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
470 size_t length,
471 const unsigned char *iv,
472 size_t iv_len,
473 const unsigned char *add,
474 size_t add_len,
475 const unsigned char *tag,
476 size_t tag_len,
477 const unsigned char *input,
478 unsigned char *output)
Paul Bakker89e80c92012-03-20 13:50:09 +0000479{
Janos Follath24eed8d2019-11-22 13:21:35 +0000480 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000481 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200482 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000483
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100484 GCM_VALIDATE_RET(ctx != NULL);
485 GCM_VALIDATE_RET(iv != NULL);
486 GCM_VALIDATE_RET(add_len == 0 || add != NULL);
487 GCM_VALIDATE_RET(tag != NULL);
488 GCM_VALIDATE_RET(length == 0 || input != NULL);
489 GCM_VALIDATE_RET(length == 0 || output != NULL);
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100490
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100491 if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
492 iv, iv_len, add, add_len,
493 input, output, tag_len, check_tag)) != 0) {
494 return ret;
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100495 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000496
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200497 /* Check tag in "constant-time" */
Dave Rodgmanc2805202023-09-11 18:25:16 +0100498 diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
Paul Bakker89e80c92012-03-20 13:50:09 +0000499
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100500 if (diff != 0) {
501 mbedtls_platform_zeroize(output, length);
502 return MBEDTLS_ERR_GCM_AUTH_FAILED;
503 }
504
505 return 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000506}
507
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100508void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200509{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100510 if (ctx == NULL) {
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100511 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100512 }
513 mbedtls_cipher_free(&ctx->cipher_ctx);
514 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200515}
516
Jaeden Amero15263302017-09-21 12:53:48 +0100517#endif /* !MBEDTLS_GCM_ALT */
518
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000520/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200521 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000522 *
523 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
524 */
525#define MAX_TESTS 6
526
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100527static const int key_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100528{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000529
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100530static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000531{
532 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
536 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
537 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
538 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200539 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000540};
541
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100542static const size_t iv_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100543{ 12, 12, 12, 12, 8, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000544
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100545static const int iv_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100546{ 0, 0, 1, 1, 1, 2 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000547
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100548static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000549{
550 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00 },
552 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
553 0xde, 0xca, 0xf8, 0x88 },
554 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200555 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000556 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200557 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000558 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200559 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000560 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200561 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000562};
563
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100564static const size_t add_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100565{ 0, 0, 0, 20, 20, 20 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000566
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100567static const int add_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100568{ 0, 0, 0, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000569
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100570static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000571{
572 { 0x00 },
573 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200574 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000575 0xab, 0xad, 0xda, 0xd2 },
576};
577
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100578static const size_t pt_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100579{ 0, 16, 64, 60, 60, 60 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000580
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100581static const int pt_index_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100582{ 0, 0, 1, 1, 1, 1 };
Paul Bakker89e80c92012-03-20 13:50:09 +0000583
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100584static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000585{
586 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
588 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
589 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
590 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
591 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
592 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
593 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
594 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
595 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
596};
597
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100598static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000599{
600 { 0x00 },
601 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
602 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
603 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200604 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000605 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
610 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
611 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200614 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000615 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
618 0x3d, 0x58, 0xe0, 0x91 },
619 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200620 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000621 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200622 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000623 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200624 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000625 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
626 0xc2, 0x3f, 0x45, 0x98 },
627 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200628 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000629 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200630 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000631 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200632 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000633 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
634 0x4c, 0x34, 0xae, 0xe5 },
635 { 0x00 },
636 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200639 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000640 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200641 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
645 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
646 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
650 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
651 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000664 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200665 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000666 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200667 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000668 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200669 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000670 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200671 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
672 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
673 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
674 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
675 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
676 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
677 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
678 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
679 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
680 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
681 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
682 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
683 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
684 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
685 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
686 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
687 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
688 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200694 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000695 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200696 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000697 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200698 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000699 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200700 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000701 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200702 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000703 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200704 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000705};
706
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100707static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000708{
709 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
710 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
711 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
712 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
713 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200714 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000715 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
716 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
717 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
718 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
719 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
720 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
721 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
722 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
723 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
726 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
727 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000735 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200736 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000737 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000739 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200740 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000741 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200742 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000743 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200744 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000745};
746
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100747int mbedtls_gcm_self_test(int verbose)
Paul Bakker89e80c92012-03-20 13:50:09 +0000748{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000750 unsigned char buf[64];
751 unsigned char tag_buf[16];
752 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000754
Gilles Peskinede345782023-03-16 13:06:14 +0100755 if (verbose != 0) {
Gilles Peskine2c8ad942023-03-10 22:35:24 +0100756#if defined(MBEDTLS_GCM_ALT)
757 mbedtls_printf(" GCM note: alternative implementation.\n");
758#else /* MBEDTLS_GCM_ALT */
759#if defined(MBEDTLS_AESNI_HAVE_CODE)
760 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
Tom Cosgrove640b7612023-03-19 15:07:06 +0000761 mbedtls_printf(" GCM note: using AESNI via ");
762#if MBEDTLS_AESNI_HAVE_CODE == 1
763 mbedtls_printf("assembly");
764#elif MBEDTLS_AESNI_HAVE_CODE == 2
765 mbedtls_printf("intrinsics");
766#else
767 mbedtls_printf("(unknown)");
768#endif
769 mbedtls_printf(".\n");
Gilles Peskine2c8ad942023-03-10 22:35:24 +0100770 } else
771#endif
772 mbedtls_printf(" GCM note: built-in implementation.\n");
773#endif /* MBEDTLS_GCM_ALT */
774 }
775
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100776 for (j = 0; j < 3; j++) {
Paul Bakker89e80c92012-03-20 13:50:09 +0000777 int key_len = 128 + 64 * j;
778
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100779 for (i = 0; i < MAX_TESTS; i++) {
780 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100781
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100782 if (verbose != 0) {
783 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
784 key_len, i, "enc");
785 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200786
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100787 ret = mbedtls_gcm_setkey(&ctx, cipher,
788 key_test_data[key_index_test_data[i]],
789 key_len);
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100790 /*
791 * AES-192 is an optional feature that may be unavailable when
792 * there is an alternative underlying implementation i.e. when
793 * MBEDTLS_AES_ALT is defined.
794 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100795 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
796 mbedtls_printf("skipped\n");
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100797 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100798 } else if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100799 goto exit;
800 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000801
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100802 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
803 pt_len_test_data[i],
804 iv_test_data[iv_index_test_data[i]],
805 iv_len_test_data[i],
806 additional_test_data[add_index_test_data[i]],
807 add_len_test_data[i],
808 pt_test_data[pt_index_test_data[i]],
809 buf, 16, tag_buf);
Steven Cooreman2222d682021-01-11 18:45:22 +0100810#if defined(MBEDTLS_GCM_ALT)
811 /* Allow alternative implementations to only support 12-byte nonces. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100812 if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
813 iv_len_test_data[i] != 12) {
814 mbedtls_printf("skipped\n");
Steven Cooreman2222d682021-01-11 18:45:22 +0100815 break;
816 }
817#endif /* defined(MBEDTLS_GCM_ALT) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100818 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100819 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100820 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000821
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100822 if (memcmp(buf, ct_test_data[j * 6 + i],
823 pt_len_test_data[i]) != 0 ||
824 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100825 ret = 1;
826 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000827 }
828
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100829 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200830
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100831 if (verbose != 0) {
832 mbedtls_printf("passed\n");
833 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000834
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100835 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100836
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100837 if (verbose != 0) {
838 mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
839 key_len, i, "dec");
840 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200841
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100842 ret = mbedtls_gcm_setkey(&ctx, cipher,
843 key_test_data[key_index_test_data[i]],
844 key_len);
845 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100846 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100847 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000848
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100849 ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
850 pt_len_test_data[i],
851 iv_test_data[iv_index_test_data[i]],
852 iv_len_test_data[i],
853 additional_test_data[add_index_test_data[i]],
854 add_len_test_data[i],
855 ct_test_data[j * 6 + i], buf, 16, tag_buf);
Paul Bakker89e80c92012-03-20 13:50:09 +0000856
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100857 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100858 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100859 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100860
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100861 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
862 pt_len_test_data[i]) != 0 ||
863 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100864 ret = 1;
865 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000866 }
867
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100868 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200869
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100870 if (verbose != 0) {
871 mbedtls_printf("passed\n");
872 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200873
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100874 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100875
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100876 if (verbose != 0) {
877 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
878 key_len, i, "enc");
879 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200880
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100881 ret = mbedtls_gcm_setkey(&ctx, cipher,
882 key_test_data[key_index_test_data[i]],
883 key_len);
884 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100885 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100886 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200887
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100888 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
889 iv_test_data[iv_index_test_data[i]],
890 iv_len_test_data[i],
891 additional_test_data[add_index_test_data[i]],
892 add_len_test_data[i]);
893 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100894 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100895 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200896
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100897 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100898 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100899 ret = mbedtls_gcm_update(&ctx, 32,
900 pt_test_data[pt_index_test_data[i]],
901 buf);
902 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100903 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100904 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200905
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100906 ret = mbedtls_gcm_update(&ctx, rest_len,
907 pt_test_data[pt_index_test_data[i]] + 32,
908 buf + 32);
909 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100910 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100911 }
912 } else {
913 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
914 pt_test_data[pt_index_test_data[i]],
915 buf);
916 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100917 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100918 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200919 }
920
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100921 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
922 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100923 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100924 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100925
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100926 if (memcmp(buf, ct_test_data[j * 6 + i],
927 pt_len_test_data[i]) != 0 ||
928 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100929 ret = 1;
930 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200931 }
932
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100933 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200934
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100935 if (verbose != 0) {
936 mbedtls_printf("passed\n");
937 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200938
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100939 mbedtls_gcm_init(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100940
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100941 if (verbose != 0) {
942 mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
943 key_len, i, "dec");
944 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200945
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100946 ret = mbedtls_gcm_setkey(&ctx, cipher,
947 key_test_data[key_index_test_data[i]],
948 key_len);
949 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100950 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100951 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200952
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100953 ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
954 iv_test_data[iv_index_test_data[i]],
955 iv_len_test_data[i],
956 additional_test_data[add_index_test_data[i]],
957 add_len_test_data[i]);
958 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100959 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100960 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200961
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100962 if (pt_len_test_data[i] > 32) {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100963 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100964 ret = mbedtls_gcm_update(&ctx, 32, ct_test_data[j * 6 + i],
965 buf);
966 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100967 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100968 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200969
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100970 ret = mbedtls_gcm_update(&ctx, rest_len,
971 ct_test_data[j * 6 + i] + 32,
972 buf + 32);
973 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100974 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100975 }
976 } else {
977 ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i],
978 ct_test_data[j * 6 + i],
979 buf);
980 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100981 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100982 }
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200983 }
984
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100985 ret = mbedtls_gcm_finish(&ctx, tag_buf, 16);
986 if (ret != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100987 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100988 }
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100989
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100990 if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
991 pt_len_test_data[i]) != 0 ||
992 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100993 ret = 1;
994 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200995 }
996
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100997 mbedtls_gcm_free(&ctx);
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200998
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100999 if (verbose != 0) {
1000 mbedtls_printf("passed\n");
1001 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001002 }
1003 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001004
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001005 if (verbose != 0) {
1006 mbedtls_printf("\n");
1007 }
Paul Bakker89e80c92012-03-20 13:50:09 +00001008
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001009 ret = 0;
1010
1011exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001012 if (ret != 0) {
1013 if (verbose != 0) {
1014 mbedtls_printf("failed\n");
1015 }
1016 mbedtls_gcm_free(&ctx);
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001017 }
1018
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001019 return ret;
Paul Bakker89e80c92012-03-20 13:50:09 +00001020}
1021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024#endif /* MBEDTLS_GCM_C */