xref: /optee_os/lib/libmbedtls/mbedtls/library/gcm.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  NIST SP800-38D compliant GCM implementation
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander 
20817466cbSJens Wiklander /*
21817466cbSJens Wiklander  * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
22817466cbSJens Wiklander  *
23817466cbSJens Wiklander  * See also:
24817466cbSJens Wiklander  * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
25817466cbSJens Wiklander  *
26817466cbSJens Wiklander  * We use the algorithm described as Shoup's method with 4-bit tables in
27817466cbSJens Wiklander  * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
28817466cbSJens Wiklander  */
29817466cbSJens Wiklander 
307901324dSJerome Forissier #include "common.h"
31817466cbSJens Wiklander 
32817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
33817466cbSJens Wiklander 
34817466cbSJens Wiklander #include "mbedtls/gcm.h"
35*32b31808SJens Wiklander #include "mbedtls/platform.h"
363d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
3711fa71b9SJerome Forissier #include "mbedtls/error.h"
38817466cbSJens Wiklander 
39817466cbSJens Wiklander #include <string.h>
40817466cbSJens Wiklander 
41817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C)
42*32b31808SJens Wiklander #include "aesni.h"
43817466cbSJens Wiklander #endif
44817466cbSJens Wiklander 
45*32b31808SJens Wiklander #if defined(MBEDTLS_AESCE_C)
46*32b31808SJens Wiklander #include "aesce.h"
47*32b31808SJens Wiklander #endif
48817466cbSJens Wiklander 
493d3b0591SJens Wiklander #if !defined(MBEDTLS_GCM_ALT)
503d3b0591SJens Wiklander 
51817466cbSJens Wiklander /*
52817466cbSJens Wiklander  * Initialize a context
53817466cbSJens Wiklander  */
54817466cbSJens Wiklander void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
55817466cbSJens Wiklander {
56817466cbSJens Wiklander     memset(ctx, 0, sizeof(mbedtls_gcm_context));
57817466cbSJens Wiklander }
58817466cbSJens Wiklander 
59817466cbSJens Wiklander /*
60817466cbSJens Wiklander  * Precompute small multiples of H, that is set
61817466cbSJens Wiklander  *      HH[i] || HL[i] = H times i,
62817466cbSJens Wiklander  * where i is seen as a field element as in [MGV], ie high-order bits
63817466cbSJens Wiklander  * correspond to low powers of P. The result is stored in the same way, that
64817466cbSJens Wiklander  * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
65817466cbSJens Wiklander  * corresponds to P^127.
66817466cbSJens Wiklander  */
67817466cbSJens Wiklander static int gcm_gen_table(mbedtls_gcm_context *ctx)
68817466cbSJens Wiklander {
69817466cbSJens Wiklander     int ret, i, j;
70817466cbSJens Wiklander     uint64_t hi, lo;
71817466cbSJens Wiklander     uint64_t vl, vh;
72817466cbSJens Wiklander     unsigned char h[16];
73817466cbSJens Wiklander     size_t olen = 0;
74817466cbSJens Wiklander 
75817466cbSJens Wiklander     memset(h, 0, 16);
76*32b31808SJens Wiklander     if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
77*32b31808SJens Wiklander         return ret;
78*32b31808SJens Wiklander     }
79817466cbSJens Wiklander 
80817466cbSJens Wiklander     /* pack h as two 64-bits ints, big-endian */
81039e02dfSJerome Forissier     hi = MBEDTLS_GET_UINT32_BE(h,  0);
82039e02dfSJerome Forissier     lo = MBEDTLS_GET_UINT32_BE(h,  4);
83817466cbSJens Wiklander     vh = (uint64_t) hi << 32 | lo;
84817466cbSJens Wiklander 
85039e02dfSJerome Forissier     hi = MBEDTLS_GET_UINT32_BE(h,  8);
86039e02dfSJerome Forissier     lo = MBEDTLS_GET_UINT32_BE(h,  12);
87817466cbSJens Wiklander     vl = (uint64_t) hi << 32 | lo;
88817466cbSJens Wiklander 
89817466cbSJens Wiklander     /* 8 = 1000 corresponds to 1 in GF(2^128) */
90817466cbSJens Wiklander     ctx->HL[8] = vl;
91817466cbSJens Wiklander     ctx->HH[8] = vh;
92817466cbSJens Wiklander 
93*32b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE)
94817466cbSJens Wiklander     /* With CLMUL support, we need only h, not the rest of the table */
95*32b31808SJens Wiklander     if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
96*32b31808SJens Wiklander         return 0;
97*32b31808SJens Wiklander     }
98*32b31808SJens Wiklander #endif
99*32b31808SJens Wiklander 
100*32b31808SJens Wiklander #if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
101*32b31808SJens Wiklander     if (mbedtls_aesce_has_support()) {
102*32b31808SJens Wiklander         return 0;
103*32b31808SJens Wiklander     }
104817466cbSJens Wiklander #endif
105817466cbSJens Wiklander 
106817466cbSJens Wiklander     /* 0 corresponds to 0 in GF(2^128) */
107817466cbSJens Wiklander     ctx->HH[0] = 0;
108817466cbSJens Wiklander     ctx->HL[0] = 0;
109817466cbSJens Wiklander 
110*32b31808SJens Wiklander     for (i = 4; i > 0; i >>= 1) {
111817466cbSJens Wiklander         uint32_t T = (vl & 1) * 0xe1000000U;
112817466cbSJens Wiklander         vl  = (vh << 63) | (vl >> 1);
113817466cbSJens Wiklander         vh  = (vh >> 1) ^ ((uint64_t) T << 32);
114817466cbSJens Wiklander 
115817466cbSJens Wiklander         ctx->HL[i] = vl;
116817466cbSJens Wiklander         ctx->HH[i] = vh;
117817466cbSJens Wiklander     }
118817466cbSJens Wiklander 
119*32b31808SJens Wiklander     for (i = 2; i <= 8; i *= 2) {
120817466cbSJens Wiklander         uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
121817466cbSJens Wiklander         vh = *HiH;
122817466cbSJens Wiklander         vl = *HiL;
123*32b31808SJens Wiklander         for (j = 1; j < i; j++) {
124817466cbSJens Wiklander             HiH[j] = vh ^ ctx->HH[j];
125817466cbSJens Wiklander             HiL[j] = vl ^ ctx->HL[j];
126817466cbSJens Wiklander         }
127817466cbSJens Wiklander     }
128817466cbSJens Wiklander 
129*32b31808SJens Wiklander     return 0;
130817466cbSJens Wiklander }
131817466cbSJens Wiklander 
132817466cbSJens Wiklander int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
133817466cbSJens Wiklander                        mbedtls_cipher_id_t cipher,
134817466cbSJens Wiklander                        const unsigned char *key,
135817466cbSJens Wiklander                        unsigned int keybits)
136817466cbSJens Wiklander {
13711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
138817466cbSJens Wiklander     const mbedtls_cipher_info_t *cipher_info;
139817466cbSJens Wiklander 
140*32b31808SJens Wiklander     if (keybits != 128 && keybits != 192 && keybits != 256) {
141*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BAD_INPUT;
142*32b31808SJens Wiklander     }
1433d3b0591SJens Wiklander 
14411fa71b9SJerome Forissier     cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
14511fa71b9SJerome Forissier                                                   MBEDTLS_MODE_ECB);
146*32b31808SJens Wiklander     if (cipher_info == NULL) {
147*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BAD_INPUT;
148*32b31808SJens Wiklander     }
149817466cbSJens Wiklander 
150*32b31808SJens Wiklander     if (cipher_info->block_size != 16) {
151*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BAD_INPUT;
152*32b31808SJens Wiklander     }
153817466cbSJens Wiklander 
154817466cbSJens Wiklander     mbedtls_cipher_free(&ctx->cipher_ctx);
155817466cbSJens Wiklander 
156*32b31808SJens Wiklander     if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
157*32b31808SJens Wiklander         return ret;
158817466cbSJens Wiklander     }
159817466cbSJens Wiklander 
160*32b31808SJens Wiklander     if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
161*32b31808SJens Wiklander                                      MBEDTLS_ENCRYPT)) != 0) {
162*32b31808SJens Wiklander         return ret;
163*32b31808SJens Wiklander     }
164817466cbSJens Wiklander 
165*32b31808SJens Wiklander     if ((ret = gcm_gen_table(ctx)) != 0) {
166*32b31808SJens Wiklander         return ret;
167*32b31808SJens Wiklander     }
168*32b31808SJens Wiklander 
169*32b31808SJens Wiklander     return 0;
170817466cbSJens Wiklander }
171817466cbSJens Wiklander 
172817466cbSJens Wiklander /*
173817466cbSJens Wiklander  * Shoup's method for multiplication use this table with
174817466cbSJens Wiklander  *      last4[x] = x times P^128
175817466cbSJens Wiklander  * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
176817466cbSJens Wiklander  */
177817466cbSJens Wiklander static const uint64_t last4[16] =
178817466cbSJens Wiklander {
179817466cbSJens Wiklander     0x0000, 0x1c20, 0x3840, 0x2460,
180817466cbSJens Wiklander     0x7080, 0x6ca0, 0x48c0, 0x54e0,
181817466cbSJens Wiklander     0xe100, 0xfd20, 0xd940, 0xc560,
182817466cbSJens Wiklander     0x9180, 0x8da0, 0xa9c0, 0xb5e0
183817466cbSJens Wiklander };
184817466cbSJens Wiklander 
185817466cbSJens Wiklander /*
186817466cbSJens Wiklander  * Sets output to x times H using the precomputed tables.
187817466cbSJens Wiklander  * x and output are seen as elements of GF(2^128) as in [MGV].
188817466cbSJens Wiklander  */
189817466cbSJens Wiklander static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
190817466cbSJens Wiklander                      unsigned char output[16])
191817466cbSJens Wiklander {
192817466cbSJens Wiklander     int i = 0;
193817466cbSJens Wiklander     unsigned char lo, hi, rem;
194817466cbSJens Wiklander     uint64_t zh, zl;
195817466cbSJens Wiklander 
196*32b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE)
197817466cbSJens Wiklander     if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
198817466cbSJens Wiklander         unsigned char h[16];
199817466cbSJens Wiklander 
200*32b31808SJens Wiklander         /* mbedtls_aesni_gcm_mult needs big-endian input */
201039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h,  0);
202039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE(ctx->HH[8],       h,  4);
203039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h,  8);
204039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE(ctx->HL[8],       h, 12);
205817466cbSJens Wiklander 
206817466cbSJens Wiklander         mbedtls_aesni_gcm_mult(output, x, h);
207817466cbSJens Wiklander         return;
208817466cbSJens Wiklander     }
209*32b31808SJens Wiklander #endif /* MBEDTLS_AESNI_HAVE_CODE */
210*32b31808SJens Wiklander 
211*32b31808SJens Wiklander #if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
212*32b31808SJens Wiklander     if (mbedtls_aesce_has_support()) {
213*32b31808SJens Wiklander         unsigned char h[16];
214*32b31808SJens Wiklander 
215*32b31808SJens Wiklander         /* mbedtls_aesce_gcm_mult needs big-endian input */
216*32b31808SJens Wiklander         MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h,  0);
217*32b31808SJens Wiklander         MBEDTLS_PUT_UINT32_BE(ctx->HH[8],       h,  4);
218*32b31808SJens Wiklander         MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h,  8);
219*32b31808SJens Wiklander         MBEDTLS_PUT_UINT32_BE(ctx->HL[8],       h, 12);
220*32b31808SJens Wiklander 
221*32b31808SJens Wiklander         mbedtls_aesce_gcm_mult(output, x, h);
222*32b31808SJens Wiklander         return;
223*32b31808SJens Wiklander     }
224*32b31808SJens Wiklander #endif
225817466cbSJens Wiklander 
226817466cbSJens Wiklander     lo = x[15] & 0xf;
227817466cbSJens Wiklander 
228817466cbSJens Wiklander     zh = ctx->HH[lo];
229817466cbSJens Wiklander     zl = ctx->HL[lo];
230817466cbSJens Wiklander 
231*32b31808SJens Wiklander     for (i = 15; i >= 0; i--) {
232817466cbSJens Wiklander         lo = x[i] & 0xf;
23311fa71b9SJerome Forissier         hi = (x[i] >> 4) & 0xf;
234817466cbSJens Wiklander 
235*32b31808SJens Wiklander         if (i != 15) {
236817466cbSJens Wiklander             rem = (unsigned char) zl & 0xf;
237817466cbSJens Wiklander             zl = (zh << 60) | (zl >> 4);
238817466cbSJens Wiklander             zh = (zh >> 4);
239817466cbSJens Wiklander             zh ^= (uint64_t) last4[rem] << 48;
240817466cbSJens Wiklander             zh ^= ctx->HH[lo];
241817466cbSJens Wiklander             zl ^= ctx->HL[lo];
242817466cbSJens Wiklander 
243817466cbSJens Wiklander         }
244817466cbSJens Wiklander 
245817466cbSJens Wiklander         rem = (unsigned char) zl & 0xf;
246817466cbSJens Wiklander         zl = (zh << 60) | (zl >> 4);
247817466cbSJens Wiklander         zh = (zh >> 4);
248817466cbSJens Wiklander         zh ^= (uint64_t) last4[rem] << 48;
249817466cbSJens Wiklander         zh ^= ctx->HH[hi];
250817466cbSJens Wiklander         zl ^= ctx->HL[hi];
251817466cbSJens Wiklander     }
252817466cbSJens Wiklander 
253039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
254039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(zh, output, 4);
255039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
256039e02dfSJerome Forissier     MBEDTLS_PUT_UINT32_BE(zl, output, 12);
257817466cbSJens Wiklander }
258817466cbSJens Wiklander 
259817466cbSJens Wiklander int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
260817466cbSJens Wiklander                        int mode,
261*32b31808SJens Wiklander                        const unsigned char *iv, size_t iv_len)
262817466cbSJens Wiklander {
26311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
264817466cbSJens Wiklander     unsigned char work_buf[16];
265817466cbSJens Wiklander     const unsigned char *p;
266817466cbSJens Wiklander     size_t use_len, olen = 0;
267039e02dfSJerome Forissier     uint64_t iv_bits;
268817466cbSJens Wiklander 
269*32b31808SJens Wiklander     /* IV is limited to 2^64 bits, so 2^61 bytes */
270817466cbSJens Wiklander     /* IV is not allowed to be zero length */
271*32b31808SJens Wiklander     if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
272*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BAD_INPUT;
273817466cbSJens Wiklander     }
274817466cbSJens Wiklander 
275817466cbSJens Wiklander     memset(ctx->y, 0x00, sizeof(ctx->y));
276817466cbSJens Wiklander     memset(ctx->buf, 0x00, sizeof(ctx->buf));
277817466cbSJens Wiklander 
278817466cbSJens Wiklander     ctx->mode = mode;
279817466cbSJens Wiklander     ctx->len = 0;
280817466cbSJens Wiklander     ctx->add_len = 0;
281817466cbSJens Wiklander 
282*32b31808SJens Wiklander     if (iv_len == 12) {
283817466cbSJens Wiklander         memcpy(ctx->y, iv, iv_len);
284817466cbSJens Wiklander         ctx->y[15] = 1;
285*32b31808SJens Wiklander     } else {
286817466cbSJens Wiklander         memset(work_buf, 0x00, 16);
287039e02dfSJerome Forissier         iv_bits = (uint64_t) iv_len * 8;
288039e02dfSJerome Forissier         MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
289817466cbSJens Wiklander 
290817466cbSJens Wiklander         p = iv;
291*32b31808SJens Wiklander         while (iv_len > 0) {
292817466cbSJens Wiklander             use_len = (iv_len < 16) ? iv_len : 16;
293817466cbSJens Wiklander 
294*32b31808SJens Wiklander             mbedtls_xor(ctx->y, ctx->y, p, use_len);
295817466cbSJens Wiklander 
296817466cbSJens Wiklander             gcm_mult(ctx, ctx->y, ctx->y);
297817466cbSJens Wiklander 
298817466cbSJens Wiklander             iv_len -= use_len;
299817466cbSJens Wiklander             p += use_len;
300817466cbSJens Wiklander         }
301817466cbSJens Wiklander 
302*32b31808SJens Wiklander         mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
303817466cbSJens Wiklander 
304817466cbSJens Wiklander         gcm_mult(ctx, ctx->y, ctx->y);
305817466cbSJens Wiklander     }
306817466cbSJens Wiklander 
30711fa71b9SJerome Forissier     if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
308*32b31808SJens Wiklander                                      ctx->base_ectr, &olen)) != 0) {
309*32b31808SJens Wiklander         return ret;
310817466cbSJens Wiklander     }
311817466cbSJens Wiklander 
312*32b31808SJens Wiklander     return 0;
313*32b31808SJens Wiklander }
314*32b31808SJens Wiklander 
315*32b31808SJens Wiklander /**
316*32b31808SJens Wiklander  * mbedtls_gcm_context::buf contains the partial state of the computation of
317*32b31808SJens Wiklander  * the authentication tag.
318*32b31808SJens Wiklander  * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
319*32b31808SJens Wiklander  * different stages of the computation:
320*32b31808SJens Wiklander  *     * len == 0 && add_len == 0:      initial state
321*32b31808SJens Wiklander  *     * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
322*32b31808SJens Wiklander  *                                      a partial block of AD that has been
323*32b31808SJens Wiklander  *                                      xored in but not yet multiplied in.
324*32b31808SJens Wiklander  *     * len == 0 && add_len % 16 == 0: the authentication tag is correct if
325*32b31808SJens Wiklander  *                                      the data ends now.
326*32b31808SJens Wiklander  *     * len % 16 != 0:                 the first `len % 16` bytes have
327*32b31808SJens Wiklander  *                                      a partial block of ciphertext that has
328*32b31808SJens Wiklander  *                                      been xored in but not yet multiplied in.
329*32b31808SJens Wiklander  *     * len > 0 && len % 16 == 0:      the authentication tag is correct if
330*32b31808SJens Wiklander  *                                      the data ends now.
331*32b31808SJens Wiklander  */
332*32b31808SJens Wiklander int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
333*32b31808SJens Wiklander                           const unsigned char *add, size_t add_len)
334817466cbSJens Wiklander {
335*32b31808SJens Wiklander     const unsigned char *p;
336*32b31808SJens Wiklander     size_t use_len, offset;
337817466cbSJens Wiklander 
338*32b31808SJens Wiklander     /* IV is limited to 2^64 bits, so 2^61 bytes */
339*32b31808SJens Wiklander     if ((uint64_t) add_len >> 61 != 0) {
340*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BAD_INPUT;
341*32b31808SJens Wiklander     }
342817466cbSJens Wiklander 
343*32b31808SJens Wiklander     offset = ctx->add_len % 16;
344*32b31808SJens Wiklander     p = add;
345*32b31808SJens Wiklander 
346*32b31808SJens Wiklander     if (offset != 0) {
347*32b31808SJens Wiklander         use_len = 16 - offset;
348*32b31808SJens Wiklander         if (use_len > add_len) {
349*32b31808SJens Wiklander             use_len = add_len;
350*32b31808SJens Wiklander         }
351*32b31808SJens Wiklander 
352*32b31808SJens Wiklander         mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
353*32b31808SJens Wiklander 
354*32b31808SJens Wiklander         if (offset + use_len == 16) {
355817466cbSJens Wiklander             gcm_mult(ctx, ctx->buf, ctx->buf);
356*32b31808SJens Wiklander         }
357817466cbSJens Wiklander 
358*32b31808SJens Wiklander         ctx->add_len += use_len;
359817466cbSJens Wiklander         add_len -= use_len;
360817466cbSJens Wiklander         p += use_len;
361817466cbSJens Wiklander     }
362817466cbSJens Wiklander 
363*32b31808SJens Wiklander     ctx->add_len += add_len;
364817466cbSJens Wiklander 
365*32b31808SJens Wiklander     while (add_len >= 16) {
366*32b31808SJens Wiklander         mbedtls_xor(ctx->buf, ctx->buf, p, 16);
367817466cbSJens Wiklander 
368817466cbSJens Wiklander         gcm_mult(ctx, ctx->buf, ctx->buf);
369817466cbSJens Wiklander 
370*32b31808SJens Wiklander         add_len -= 16;
371*32b31808SJens Wiklander         p += 16;
372*32b31808SJens Wiklander     }
373*32b31808SJens Wiklander 
374*32b31808SJens Wiklander     if (add_len > 0) {
375*32b31808SJens Wiklander         mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
376*32b31808SJens Wiklander     }
377*32b31808SJens Wiklander 
378*32b31808SJens Wiklander     return 0;
379*32b31808SJens Wiklander }
380*32b31808SJens Wiklander 
381*32b31808SJens Wiklander /* Increment the counter. */
382*32b31808SJens Wiklander static void gcm_incr(unsigned char y[16])
383*32b31808SJens Wiklander {
384*32b31808SJens Wiklander     size_t i;
385*32b31808SJens Wiklander     for (i = 16; i > 12; i--) {
386*32b31808SJens Wiklander         if (++y[i - 1] != 0) {
387*32b31808SJens Wiklander             break;
388*32b31808SJens Wiklander         }
389*32b31808SJens Wiklander     }
390*32b31808SJens Wiklander }
391*32b31808SJens Wiklander 
392*32b31808SJens Wiklander /* Calculate and apply the encryption mask. Process use_len bytes of data,
393*32b31808SJens Wiklander  * starting at position offset in the mask block. */
394*32b31808SJens Wiklander static int gcm_mask(mbedtls_gcm_context *ctx,
395*32b31808SJens Wiklander                     unsigned char ectr[16],
396*32b31808SJens Wiklander                     size_t offset, size_t use_len,
397*32b31808SJens Wiklander                     const unsigned char *input,
398*32b31808SJens Wiklander                     unsigned char *output)
399*32b31808SJens Wiklander {
400*32b31808SJens Wiklander     size_t olen = 0;
401*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
402*32b31808SJens Wiklander 
403*32b31808SJens Wiklander     if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
404*32b31808SJens Wiklander                                      &olen)) != 0) {
405*32b31808SJens Wiklander         mbedtls_platform_zeroize(ectr, 16);
406*32b31808SJens Wiklander         return ret;
407*32b31808SJens Wiklander     }
408*32b31808SJens Wiklander 
409*32b31808SJens Wiklander     if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
410*32b31808SJens Wiklander         mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
411*32b31808SJens Wiklander     }
412*32b31808SJens Wiklander     mbedtls_xor(output, ectr + offset, input, use_len);
413*32b31808SJens Wiklander     if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
414*32b31808SJens Wiklander         mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
415*32b31808SJens Wiklander     }
416*32b31808SJens Wiklander 
417*32b31808SJens Wiklander     return 0;
418*32b31808SJens Wiklander }
419*32b31808SJens Wiklander 
420*32b31808SJens Wiklander int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
421*32b31808SJens Wiklander                        const unsigned char *input, size_t input_length,
422*32b31808SJens Wiklander                        unsigned char *output, size_t output_size,
423*32b31808SJens Wiklander                        size_t *output_length)
424*32b31808SJens Wiklander {
425*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
426*32b31808SJens Wiklander     const unsigned char *p = input;
427*32b31808SJens Wiklander     unsigned char *out_p = output;
428*32b31808SJens Wiklander     size_t offset;
429*32b31808SJens Wiklander     unsigned char ectr[16] = { 0 };
430*32b31808SJens Wiklander 
431*32b31808SJens Wiklander     if (output_size < input_length) {
432*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
433*32b31808SJens Wiklander     }
434*32b31808SJens Wiklander     *output_length = input_length;
435*32b31808SJens Wiklander 
436*32b31808SJens Wiklander     /* Exit early if input_length==0 so that we don't do any pointer arithmetic
437*32b31808SJens Wiklander      * on a potentially null pointer.
438*32b31808SJens Wiklander      * Returning early also means that the last partial block of AD remains
439*32b31808SJens Wiklander      * untouched for mbedtls_gcm_finish */
440*32b31808SJens Wiklander     if (input_length == 0) {
441*32b31808SJens Wiklander         return 0;
442*32b31808SJens Wiklander     }
443*32b31808SJens Wiklander 
444*32b31808SJens Wiklander     if (output > input && (size_t) (output - input) < input_length) {
445*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BAD_INPUT;
446*32b31808SJens Wiklander     }
447*32b31808SJens Wiklander 
448*32b31808SJens Wiklander     /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
449*32b31808SJens Wiklander      * Also check for possible overflow */
450*32b31808SJens Wiklander     if (ctx->len + input_length < ctx->len ||
451*32b31808SJens Wiklander         (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
452*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BAD_INPUT;
453*32b31808SJens Wiklander     }
454*32b31808SJens Wiklander 
455*32b31808SJens Wiklander     if (ctx->len == 0 && ctx->add_len % 16 != 0) {
456*32b31808SJens Wiklander         gcm_mult(ctx, ctx->buf, ctx->buf);
457*32b31808SJens Wiklander     }
458*32b31808SJens Wiklander 
459*32b31808SJens Wiklander     offset = ctx->len % 16;
460*32b31808SJens Wiklander     if (offset != 0) {
461*32b31808SJens Wiklander         size_t use_len = 16 - offset;
462*32b31808SJens Wiklander         if (use_len > input_length) {
463*32b31808SJens Wiklander             use_len = input_length;
464*32b31808SJens Wiklander         }
465*32b31808SJens Wiklander 
466*32b31808SJens Wiklander         if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
467*32b31808SJens Wiklander             return ret;
468*32b31808SJens Wiklander         }
469*32b31808SJens Wiklander 
470*32b31808SJens Wiklander         if (offset + use_len == 16) {
471*32b31808SJens Wiklander             gcm_mult(ctx, ctx->buf, ctx->buf);
472*32b31808SJens Wiklander         }
473*32b31808SJens Wiklander 
474*32b31808SJens Wiklander         ctx->len += use_len;
475*32b31808SJens Wiklander         input_length -= use_len;
476817466cbSJens Wiklander         p += use_len;
477817466cbSJens Wiklander         out_p += use_len;
478817466cbSJens Wiklander     }
479817466cbSJens Wiklander 
480*32b31808SJens Wiklander     ctx->len += input_length;
481*32b31808SJens Wiklander 
482*32b31808SJens Wiklander     while (input_length >= 16) {
483*32b31808SJens Wiklander         gcm_incr(ctx->y);
484*32b31808SJens Wiklander         if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
485*32b31808SJens Wiklander             return ret;
486*32b31808SJens Wiklander         }
487*32b31808SJens Wiklander 
488*32b31808SJens Wiklander         gcm_mult(ctx, ctx->buf, ctx->buf);
489*32b31808SJens Wiklander 
490*32b31808SJens Wiklander         input_length -= 16;
491*32b31808SJens Wiklander         p += 16;
492*32b31808SJens Wiklander         out_p += 16;
493*32b31808SJens Wiklander     }
494*32b31808SJens Wiklander 
495*32b31808SJens Wiklander     if (input_length > 0) {
496*32b31808SJens Wiklander         gcm_incr(ctx->y);
497*32b31808SJens Wiklander         if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
498*32b31808SJens Wiklander             return ret;
499*32b31808SJens Wiklander         }
500*32b31808SJens Wiklander     }
501*32b31808SJens Wiklander 
502*32b31808SJens Wiklander     mbedtls_platform_zeroize(ectr, sizeof(ectr));
503*32b31808SJens Wiklander     return 0;
504817466cbSJens Wiklander }
505817466cbSJens Wiklander 
506817466cbSJens Wiklander int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
507*32b31808SJens Wiklander                        unsigned char *output, size_t output_size,
508*32b31808SJens Wiklander                        size_t *output_length,
509*32b31808SJens Wiklander                        unsigned char *tag, size_t tag_len)
510817466cbSJens Wiklander {
511817466cbSJens Wiklander     unsigned char work_buf[16];
5123d3b0591SJens Wiklander     uint64_t orig_len;
5133d3b0591SJens Wiklander     uint64_t orig_add_len;
5143d3b0591SJens Wiklander 
515*32b31808SJens Wiklander     /* We never pass any output in finish(). The output parameter exists only
516*32b31808SJens Wiklander      * for the sake of alternative implementations. */
517*32b31808SJens Wiklander     (void) output;
518*32b31808SJens Wiklander     (void) output_size;
519*32b31808SJens Wiklander     *output_length = 0;
5203d3b0591SJens Wiklander 
5213d3b0591SJens Wiklander     orig_len = ctx->len * 8;
5223d3b0591SJens Wiklander     orig_add_len = ctx->add_len * 8;
523817466cbSJens Wiklander 
524*32b31808SJens Wiklander     if (ctx->len == 0 && ctx->add_len % 16 != 0) {
525*32b31808SJens Wiklander         gcm_mult(ctx, ctx->buf, ctx->buf);
526*32b31808SJens Wiklander     }
527*32b31808SJens Wiklander 
528*32b31808SJens Wiklander     if (tag_len > 16 || tag_len < 4) {
529*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_BAD_INPUT;
530*32b31808SJens Wiklander     }
531*32b31808SJens Wiklander 
532*32b31808SJens Wiklander     if (ctx->len % 16 != 0) {
533*32b31808SJens Wiklander         gcm_mult(ctx, ctx->buf, ctx->buf);
534*32b31808SJens Wiklander     }
535817466cbSJens Wiklander 
536817466cbSJens Wiklander     memcpy(tag, ctx->base_ectr, tag_len);
537817466cbSJens Wiklander 
538*32b31808SJens Wiklander     if (orig_len || orig_add_len) {
539817466cbSJens Wiklander         memset(work_buf, 0x00, 16);
540817466cbSJens Wiklander 
541039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
542039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
543039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE((orig_len     >> 32), work_buf, 8);
544039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
545817466cbSJens Wiklander 
546*32b31808SJens Wiklander         mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
547817466cbSJens Wiklander 
548817466cbSJens Wiklander         gcm_mult(ctx, ctx->buf, ctx->buf);
549817466cbSJens Wiklander 
550*32b31808SJens Wiklander         mbedtls_xor(tag, tag, ctx->buf, tag_len);
551817466cbSJens Wiklander     }
552817466cbSJens Wiklander 
553*32b31808SJens Wiklander     return 0;
554817466cbSJens Wiklander }
555817466cbSJens Wiklander 
556817466cbSJens Wiklander int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
557817466cbSJens Wiklander                               int mode,
558817466cbSJens Wiklander                               size_t length,
559817466cbSJens Wiklander                               const unsigned char *iv,
560817466cbSJens Wiklander                               size_t iv_len,
561817466cbSJens Wiklander                               const unsigned char *add,
562817466cbSJens Wiklander                               size_t add_len,
563817466cbSJens Wiklander                               const unsigned char *input,
564817466cbSJens Wiklander                               unsigned char *output,
565817466cbSJens Wiklander                               size_t tag_len,
566817466cbSJens Wiklander                               unsigned char *tag)
567817466cbSJens Wiklander {
56811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
569*32b31808SJens Wiklander     size_t olen;
570817466cbSJens Wiklander 
571*32b31808SJens Wiklander     if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
572*32b31808SJens Wiklander         return ret;
573*32b31808SJens Wiklander     }
5743d3b0591SJens Wiklander 
575*32b31808SJens Wiklander     if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
576*32b31808SJens Wiklander         return ret;
577*32b31808SJens Wiklander     }
578817466cbSJens Wiklander 
579*32b31808SJens Wiklander     if ((ret = mbedtls_gcm_update(ctx, input, length,
580*32b31808SJens Wiklander                                   output, length, &olen)) != 0) {
581*32b31808SJens Wiklander         return ret;
582*32b31808SJens Wiklander     }
583817466cbSJens Wiklander 
584*32b31808SJens Wiklander     if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
585*32b31808SJens Wiklander         return ret;
586*32b31808SJens Wiklander     }
587817466cbSJens Wiklander 
588*32b31808SJens Wiklander     return 0;
589817466cbSJens Wiklander }
590817466cbSJens Wiklander 
591817466cbSJens Wiklander int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
592817466cbSJens Wiklander                              size_t length,
593817466cbSJens Wiklander                              const unsigned char *iv,
594817466cbSJens Wiklander                              size_t iv_len,
595817466cbSJens Wiklander                              const unsigned char *add,
596817466cbSJens Wiklander                              size_t add_len,
597817466cbSJens Wiklander                              const unsigned char *tag,
598817466cbSJens Wiklander                              size_t tag_len,
599817466cbSJens Wiklander                              const unsigned char *input,
600817466cbSJens Wiklander                              unsigned char *output)
601817466cbSJens Wiklander {
60211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
603817466cbSJens Wiklander     unsigned char check_tag[16];
604817466cbSJens Wiklander     size_t i;
605817466cbSJens Wiklander     int diff;
606817466cbSJens Wiklander 
607817466cbSJens Wiklander     if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
608817466cbSJens Wiklander                                          iv, iv_len, add, add_len,
609*32b31808SJens Wiklander                                          input, output, tag_len, check_tag)) != 0) {
610*32b31808SJens Wiklander         return ret;
611817466cbSJens Wiklander     }
612817466cbSJens Wiklander 
613817466cbSJens Wiklander     /* Check tag in "constant-time" */
614*32b31808SJens Wiklander     for (diff = 0, i = 0; i < tag_len; i++) {
615817466cbSJens Wiklander         diff |= tag[i] ^ check_tag[i];
616817466cbSJens Wiklander     }
617817466cbSJens Wiklander 
618*32b31808SJens Wiklander     if (diff != 0) {
619*32b31808SJens Wiklander         mbedtls_platform_zeroize(output, length);
620*32b31808SJens Wiklander         return MBEDTLS_ERR_GCM_AUTH_FAILED;
621*32b31808SJens Wiklander     }
622*32b31808SJens Wiklander 
623*32b31808SJens Wiklander     return 0;
624817466cbSJens Wiklander }
625817466cbSJens Wiklander 
626817466cbSJens Wiklander void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
627817466cbSJens Wiklander {
628*32b31808SJens Wiklander     if (ctx == NULL) {
6293d3b0591SJens Wiklander         return;
630*32b31808SJens Wiklander     }
631817466cbSJens Wiklander     mbedtls_cipher_free(&ctx->cipher_ctx);
6323d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
633817466cbSJens Wiklander }
634817466cbSJens Wiklander 
6353d3b0591SJens Wiklander #endif /* !MBEDTLS_GCM_ALT */
6363d3b0591SJens Wiklander 
637817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
638817466cbSJens Wiklander /*
639817466cbSJens Wiklander  * AES-GCM test vectors from:
640817466cbSJens Wiklander  *
641817466cbSJens Wiklander  * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
642817466cbSJens Wiklander  */
643817466cbSJens Wiklander #define MAX_TESTS   6
644817466cbSJens Wiklander 
64511fa71b9SJerome Forissier static const int key_index_test_data[MAX_TESTS] =
646817466cbSJens Wiklander { 0, 0, 1, 1, 1, 1 };
647817466cbSJens Wiklander 
64811fa71b9SJerome Forissier static const unsigned char key_test_data[MAX_TESTS][32] =
649817466cbSJens Wiklander {
650817466cbSJens Wiklander     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
654817466cbSJens Wiklander     { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
655817466cbSJens Wiklander       0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
656817466cbSJens Wiklander       0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
657817466cbSJens Wiklander       0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
658817466cbSJens Wiklander };
659817466cbSJens Wiklander 
66011fa71b9SJerome Forissier static const size_t iv_len_test_data[MAX_TESTS] =
661817466cbSJens Wiklander { 12, 12, 12, 12, 8, 60 };
662817466cbSJens Wiklander 
66311fa71b9SJerome Forissier static const int iv_index_test_data[MAX_TESTS] =
664817466cbSJens Wiklander { 0, 0, 1, 1, 1, 2 };
665817466cbSJens Wiklander 
66611fa71b9SJerome Forissier static const unsigned char iv_test_data[MAX_TESTS][64] =
667817466cbSJens Wiklander {
668817466cbSJens Wiklander     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00 },
670817466cbSJens Wiklander     { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
671817466cbSJens Wiklander       0xde, 0xca, 0xf8, 0x88 },
672817466cbSJens Wiklander     { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
673817466cbSJens Wiklander       0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
674817466cbSJens Wiklander       0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
675817466cbSJens Wiklander       0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
676817466cbSJens Wiklander       0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
677817466cbSJens Wiklander       0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
678817466cbSJens Wiklander       0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
679817466cbSJens Wiklander       0xa6, 0x37, 0xb3, 0x9b },
680817466cbSJens Wiklander };
681817466cbSJens Wiklander 
68211fa71b9SJerome Forissier static const size_t add_len_test_data[MAX_TESTS] =
683817466cbSJens Wiklander { 0, 0, 0, 20, 20, 20 };
684817466cbSJens Wiklander 
68511fa71b9SJerome Forissier static const int add_index_test_data[MAX_TESTS] =
686817466cbSJens Wiklander { 0, 0, 0, 1, 1, 1 };
687817466cbSJens Wiklander 
68811fa71b9SJerome Forissier static const unsigned char additional_test_data[MAX_TESTS][64] =
689817466cbSJens Wiklander {
690817466cbSJens Wiklander     { 0x00 },
691817466cbSJens Wiklander     { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
692817466cbSJens Wiklander       0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
693817466cbSJens Wiklander       0xab, 0xad, 0xda, 0xd2 },
694817466cbSJens Wiklander };
695817466cbSJens Wiklander 
69611fa71b9SJerome Forissier static const size_t pt_len_test_data[MAX_TESTS] =
697817466cbSJens Wiklander { 0, 16, 64, 60, 60, 60 };
698817466cbSJens Wiklander 
69911fa71b9SJerome Forissier static const int pt_index_test_data[MAX_TESTS] =
700817466cbSJens Wiklander { 0, 0, 1, 1, 1, 1 };
701817466cbSJens Wiklander 
70211fa71b9SJerome Forissier static const unsigned char pt_test_data[MAX_TESTS][64] =
703817466cbSJens Wiklander {
704817466cbSJens Wiklander     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
706817466cbSJens Wiklander     { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
707817466cbSJens Wiklander       0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
708817466cbSJens Wiklander       0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
709817466cbSJens Wiklander       0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
710817466cbSJens Wiklander       0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
711817466cbSJens Wiklander       0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
712817466cbSJens Wiklander       0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
713817466cbSJens Wiklander       0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
714817466cbSJens Wiklander };
715817466cbSJens Wiklander 
71611fa71b9SJerome Forissier static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
717817466cbSJens Wiklander {
718817466cbSJens Wiklander     { 0x00 },
719817466cbSJens Wiklander     { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
720817466cbSJens Wiklander       0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
721817466cbSJens Wiklander     { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
722817466cbSJens Wiklander       0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
723817466cbSJens Wiklander       0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
724817466cbSJens Wiklander       0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
725817466cbSJens Wiklander       0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
726817466cbSJens Wiklander       0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
727817466cbSJens Wiklander       0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
728817466cbSJens Wiklander       0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
729817466cbSJens Wiklander     { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
730817466cbSJens Wiklander       0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
731817466cbSJens Wiklander       0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
732817466cbSJens Wiklander       0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
733817466cbSJens Wiklander       0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
734817466cbSJens Wiklander       0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
735817466cbSJens Wiklander       0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
736817466cbSJens Wiklander       0x3d, 0x58, 0xe0, 0x91 },
737817466cbSJens Wiklander     { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
738817466cbSJens Wiklander       0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
739817466cbSJens Wiklander       0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
740817466cbSJens Wiklander       0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
741817466cbSJens Wiklander       0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
742817466cbSJens Wiklander       0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
743817466cbSJens Wiklander       0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
744817466cbSJens Wiklander       0xc2, 0x3f, 0x45, 0x98 },
745817466cbSJens Wiklander     { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
746817466cbSJens Wiklander       0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
747817466cbSJens Wiklander       0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
748817466cbSJens Wiklander       0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
749817466cbSJens Wiklander       0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
750817466cbSJens Wiklander       0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
751817466cbSJens Wiklander       0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
752817466cbSJens Wiklander       0x4c, 0x34, 0xae, 0xe5 },
753817466cbSJens Wiklander     { 0x00 },
754817466cbSJens Wiklander     { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
755817466cbSJens Wiklander       0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
756817466cbSJens Wiklander     { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
757817466cbSJens Wiklander       0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
758817466cbSJens Wiklander       0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
759817466cbSJens Wiklander       0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
760817466cbSJens Wiklander       0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
761817466cbSJens Wiklander       0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
762817466cbSJens Wiklander       0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
763817466cbSJens Wiklander       0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
764817466cbSJens Wiklander     { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
765817466cbSJens Wiklander       0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
766817466cbSJens Wiklander       0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
767817466cbSJens Wiklander       0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
768817466cbSJens Wiklander       0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
769817466cbSJens Wiklander       0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
770817466cbSJens Wiklander       0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
771817466cbSJens Wiklander       0xcc, 0xda, 0x27, 0x10 },
772817466cbSJens Wiklander     { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
773817466cbSJens Wiklander       0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
774817466cbSJens Wiklander       0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
775817466cbSJens Wiklander       0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
776817466cbSJens Wiklander       0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
777817466cbSJens Wiklander       0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
778817466cbSJens Wiklander       0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
779817466cbSJens Wiklander       0xa0, 0xf0, 0x62, 0xf7 },
780817466cbSJens Wiklander     { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
781817466cbSJens Wiklander       0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
782817466cbSJens Wiklander       0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
783817466cbSJens Wiklander       0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
784817466cbSJens Wiklander       0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
785817466cbSJens Wiklander       0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
786817466cbSJens Wiklander       0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
787817466cbSJens Wiklander       0xe9, 0xb7, 0x37, 0x3b },
788817466cbSJens Wiklander     { 0x00 },
789817466cbSJens Wiklander     { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
790817466cbSJens Wiklander       0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
791817466cbSJens Wiklander     { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
792817466cbSJens Wiklander       0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
793817466cbSJens Wiklander       0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
794817466cbSJens Wiklander       0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
795817466cbSJens Wiklander       0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
796817466cbSJens Wiklander       0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
797817466cbSJens Wiklander       0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
798817466cbSJens Wiklander       0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
799817466cbSJens Wiklander     { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
800817466cbSJens Wiklander       0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
801817466cbSJens Wiklander       0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
802817466cbSJens Wiklander       0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
803817466cbSJens Wiklander       0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
804817466cbSJens Wiklander       0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
805817466cbSJens Wiklander       0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
806817466cbSJens Wiklander       0xbc, 0xc9, 0xf6, 0x62 },
807817466cbSJens Wiklander     { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
808817466cbSJens Wiklander       0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
809817466cbSJens Wiklander       0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
810817466cbSJens Wiklander       0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
811817466cbSJens Wiklander       0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
812817466cbSJens Wiklander       0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
813817466cbSJens Wiklander       0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
814817466cbSJens Wiklander       0xf4, 0x7c, 0x9b, 0x1f },
815817466cbSJens Wiklander     { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
816817466cbSJens Wiklander       0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
817817466cbSJens Wiklander       0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
818817466cbSJens Wiklander       0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
819817466cbSJens Wiklander       0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
820817466cbSJens Wiklander       0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
821817466cbSJens Wiklander       0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
822817466cbSJens Wiklander       0x44, 0xae, 0x7e, 0x3f },
823817466cbSJens Wiklander };
824817466cbSJens Wiklander 
82511fa71b9SJerome Forissier static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
826817466cbSJens Wiklander {
827817466cbSJens Wiklander     { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
828817466cbSJens Wiklander       0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
829817466cbSJens Wiklander     { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
830817466cbSJens Wiklander       0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
831817466cbSJens Wiklander     { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
832817466cbSJens Wiklander       0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
833817466cbSJens Wiklander     { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
834817466cbSJens Wiklander       0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
835817466cbSJens Wiklander     { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
836817466cbSJens Wiklander       0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
837817466cbSJens Wiklander     { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
838817466cbSJens Wiklander       0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
839817466cbSJens Wiklander     { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
840817466cbSJens Wiklander       0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
841817466cbSJens Wiklander     { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
842817466cbSJens Wiklander       0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
843817466cbSJens Wiklander     { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
844817466cbSJens Wiklander       0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
845817466cbSJens Wiklander     { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
846817466cbSJens Wiklander       0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
847817466cbSJens Wiklander     { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
848817466cbSJens Wiklander       0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
849817466cbSJens Wiklander     { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
850817466cbSJens Wiklander       0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
851817466cbSJens Wiklander     { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
852817466cbSJens Wiklander       0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
853817466cbSJens Wiklander     { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
854817466cbSJens Wiklander       0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
855817466cbSJens Wiklander     { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
856817466cbSJens Wiklander       0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
857817466cbSJens Wiklander     { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
858817466cbSJens Wiklander       0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
859817466cbSJens Wiklander     { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
860817466cbSJens Wiklander       0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
861817466cbSJens Wiklander     { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
862817466cbSJens Wiklander       0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
863817466cbSJens Wiklander };
864817466cbSJens Wiklander 
865817466cbSJens Wiklander int mbedtls_gcm_self_test(int verbose)
866817466cbSJens Wiklander {
867817466cbSJens Wiklander     mbedtls_gcm_context ctx;
868817466cbSJens Wiklander     unsigned char buf[64];
869817466cbSJens Wiklander     unsigned char tag_buf[16];
870817466cbSJens Wiklander     int i, j, ret;
871817466cbSJens Wiklander     mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
872*32b31808SJens Wiklander     size_t olen;
873817466cbSJens Wiklander 
874*32b31808SJens Wiklander     if (verbose != 0) {
875*32b31808SJens Wiklander #if defined(MBEDTLS_GCM_ALT)
876*32b31808SJens Wiklander         mbedtls_printf("  GCM note: alternative implementation.\n");
877*32b31808SJens Wiklander #else /* MBEDTLS_GCM_ALT */
878*32b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE)
879*32b31808SJens Wiklander         if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
880*32b31808SJens Wiklander             mbedtls_printf("  GCM note: using AESNI.\n");
881*32b31808SJens Wiklander         } else
882*32b31808SJens Wiklander #endif
883*32b31808SJens Wiklander         mbedtls_printf("  GCM note: built-in implementation.\n");
884*32b31808SJens Wiklander #endif /* MBEDTLS_GCM_ALT */
885*32b31808SJens Wiklander     }
886*32b31808SJens Wiklander 
887*32b31808SJens Wiklander     for (j = 0; j < 3; j++) {
888817466cbSJens Wiklander         int key_len = 128 + 64 * j;
889817466cbSJens Wiklander 
890*32b31808SJens Wiklander         for (i = 0; i < MAX_TESTS; i++) {
8913d3b0591SJens Wiklander             mbedtls_gcm_init(&ctx);
8923d3b0591SJens Wiklander 
893*32b31808SJens Wiklander             if (verbose != 0) {
894817466cbSJens Wiklander                 mbedtls_printf("  AES-GCM-%3d #%d (%s): ",
895817466cbSJens Wiklander                                key_len, i, "enc");
896*32b31808SJens Wiklander             }
897817466cbSJens Wiklander 
89811fa71b9SJerome Forissier             ret = mbedtls_gcm_setkey(&ctx, cipher,
89911fa71b9SJerome Forissier                                      key_test_data[key_index_test_data[i]],
9003d3b0591SJens Wiklander                                      key_len);
9013d3b0591SJens Wiklander             /*
9023d3b0591SJens Wiklander              * AES-192 is an optional feature that may be unavailable when
9033d3b0591SJens Wiklander              * there is an alternative underlying implementation i.e. when
9043d3b0591SJens Wiklander              * MBEDTLS_AES_ALT is defined.
9053d3b0591SJens Wiklander              */
906*32b31808SJens Wiklander             if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
9073d3b0591SJens Wiklander                 mbedtls_printf("skipped\n");
9083d3b0591SJens Wiklander                 break;
909*32b31808SJens Wiklander             } else if (ret != 0) {
9103d3b0591SJens Wiklander                 goto exit;
9113d3b0591SJens Wiklander             }
912817466cbSJens Wiklander 
913817466cbSJens Wiklander             ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
91411fa71b9SJerome Forissier                                             pt_len_test_data[i],
91511fa71b9SJerome Forissier                                             iv_test_data[iv_index_test_data[i]],
91611fa71b9SJerome Forissier                                             iv_len_test_data[i],
91711fa71b9SJerome Forissier                                             additional_test_data[add_index_test_data[i]],
91811fa71b9SJerome Forissier                                             add_len_test_data[i],
91911fa71b9SJerome Forissier                                             pt_test_data[pt_index_test_data[i]],
92011fa71b9SJerome Forissier                                             buf, 16, tag_buf);
9217901324dSJerome Forissier #if defined(MBEDTLS_GCM_ALT)
9227901324dSJerome Forissier             /* Allow alternative implementations to only support 12-byte nonces. */
9237901324dSJerome Forissier             if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
924*32b31808SJens Wiklander                 iv_len_test_data[i] != 12) {
9257901324dSJerome Forissier                 mbedtls_printf("skipped\n");
9267901324dSJerome Forissier                 break;
9277901324dSJerome Forissier             }
9287901324dSJerome Forissier #endif /* defined(MBEDTLS_GCM_ALT) */
929*32b31808SJens Wiklander             if (ret != 0) {
9303d3b0591SJens Wiklander                 goto exit;
931*32b31808SJens Wiklander             }
932817466cbSJens Wiklander 
93311fa71b9SJerome Forissier             if (memcmp(buf, ct_test_data[j * 6 + i],
93411fa71b9SJerome Forissier                        pt_len_test_data[i]) != 0 ||
935*32b31808SJens Wiklander                 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
9363d3b0591SJens Wiklander                 ret = 1;
9373d3b0591SJens Wiklander                 goto exit;
938817466cbSJens Wiklander             }
939817466cbSJens Wiklander 
940817466cbSJens Wiklander             mbedtls_gcm_free(&ctx);
941817466cbSJens Wiklander 
942*32b31808SJens Wiklander             if (verbose != 0) {
943817466cbSJens Wiklander                 mbedtls_printf("passed\n");
944*32b31808SJens Wiklander             }
945817466cbSJens Wiklander 
9463d3b0591SJens Wiklander             mbedtls_gcm_init(&ctx);
9473d3b0591SJens Wiklander 
948*32b31808SJens Wiklander             if (verbose != 0) {
949817466cbSJens Wiklander                 mbedtls_printf("  AES-GCM-%3d #%d (%s): ",
950817466cbSJens Wiklander                                key_len, i, "dec");
951*32b31808SJens Wiklander             }
952817466cbSJens Wiklander 
95311fa71b9SJerome Forissier             ret = mbedtls_gcm_setkey(&ctx, cipher,
95411fa71b9SJerome Forissier                                      key_test_data[key_index_test_data[i]],
9553d3b0591SJens Wiklander                                      key_len);
956*32b31808SJens Wiklander             if (ret != 0) {
9573d3b0591SJens Wiklander                 goto exit;
958*32b31808SJens Wiklander             }
959817466cbSJens Wiklander 
960817466cbSJens Wiklander             ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
96111fa71b9SJerome Forissier                                             pt_len_test_data[i],
96211fa71b9SJerome Forissier                                             iv_test_data[iv_index_test_data[i]],
96311fa71b9SJerome Forissier                                             iv_len_test_data[i],
96411fa71b9SJerome Forissier                                             additional_test_data[add_index_test_data[i]],
96511fa71b9SJerome Forissier                                             add_len_test_data[i],
96611fa71b9SJerome Forissier                                             ct_test_data[j * 6 + i], buf, 16, tag_buf);
967817466cbSJens Wiklander 
968*32b31808SJens Wiklander             if (ret != 0) {
9693d3b0591SJens Wiklander                 goto exit;
970*32b31808SJens Wiklander             }
9713d3b0591SJens Wiklander 
97211fa71b9SJerome Forissier             if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
97311fa71b9SJerome Forissier                        pt_len_test_data[i]) != 0 ||
974*32b31808SJens Wiklander                 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
9753d3b0591SJens Wiklander                 ret = 1;
9763d3b0591SJens Wiklander                 goto exit;
977817466cbSJens Wiklander             }
978817466cbSJens Wiklander 
979817466cbSJens Wiklander             mbedtls_gcm_free(&ctx);
980817466cbSJens Wiklander 
981*32b31808SJens Wiklander             if (verbose != 0) {
982817466cbSJens Wiklander                 mbedtls_printf("passed\n");
983*32b31808SJens Wiklander             }
984817466cbSJens Wiklander 
9853d3b0591SJens Wiklander             mbedtls_gcm_init(&ctx);
9863d3b0591SJens Wiklander 
987*32b31808SJens Wiklander             if (verbose != 0) {
988817466cbSJens Wiklander                 mbedtls_printf("  AES-GCM-%3d #%d split (%s): ",
989817466cbSJens Wiklander                                key_len, i, "enc");
990*32b31808SJens Wiklander             }
991817466cbSJens Wiklander 
99211fa71b9SJerome Forissier             ret = mbedtls_gcm_setkey(&ctx, cipher,
99311fa71b9SJerome Forissier                                      key_test_data[key_index_test_data[i]],
9943d3b0591SJens Wiklander                                      key_len);
995*32b31808SJens Wiklander             if (ret != 0) {
9963d3b0591SJens Wiklander                 goto exit;
997*32b31808SJens Wiklander             }
998817466cbSJens Wiklander 
999817466cbSJens Wiklander             ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
100011fa71b9SJerome Forissier                                      iv_test_data[iv_index_test_data[i]],
1001*32b31808SJens Wiklander                                      iv_len_test_data[i]);
1002*32b31808SJens Wiklander             if (ret != 0) {
1003*32b31808SJens Wiklander                 goto exit;
1004*32b31808SJens Wiklander             }
1005*32b31808SJens Wiklander 
1006*32b31808SJens Wiklander             ret = mbedtls_gcm_update_ad(&ctx,
100711fa71b9SJerome Forissier                                         additional_test_data[add_index_test_data[i]],
100811fa71b9SJerome Forissier                                         add_len_test_data[i]);
1009*32b31808SJens Wiklander             if (ret != 0) {
10103d3b0591SJens Wiklander                 goto exit;
1011*32b31808SJens Wiklander             }
1012817466cbSJens Wiklander 
1013*32b31808SJens Wiklander             if (pt_len_test_data[i] > 32) {
101411fa71b9SJerome Forissier                 size_t rest_len = pt_len_test_data[i] - 32;
1015*32b31808SJens Wiklander                 ret = mbedtls_gcm_update(&ctx,
101611fa71b9SJerome Forissier                                          pt_test_data[pt_index_test_data[i]],
1017*32b31808SJens Wiklander                                          32,
1018*32b31808SJens Wiklander                                          buf, sizeof(buf), &olen);
1019*32b31808SJens Wiklander                 if (ret != 0) {
10203d3b0591SJens Wiklander                     goto exit;
1021*32b31808SJens Wiklander                 }
1022*32b31808SJens Wiklander                 if (olen != 32) {
1023*32b31808SJens Wiklander                     goto exit;
1024*32b31808SJens Wiklander                 }
1025817466cbSJens Wiklander 
1026*32b31808SJens Wiklander                 ret = mbedtls_gcm_update(&ctx,
102711fa71b9SJerome Forissier                                          pt_test_data[pt_index_test_data[i]] + 32,
1028*32b31808SJens Wiklander                                          rest_len,
1029*32b31808SJens Wiklander                                          buf + 32, sizeof(buf) - 32, &olen);
1030*32b31808SJens Wiklander                 if (ret != 0) {
10313d3b0591SJens Wiklander                     goto exit;
1032817466cbSJens Wiklander                 }
1033*32b31808SJens Wiklander                 if (olen != rest_len) {
10343d3b0591SJens Wiklander                     goto exit;
1035817466cbSJens Wiklander                 }
1036*32b31808SJens Wiklander             } else {
1037*32b31808SJens Wiklander                 ret = mbedtls_gcm_update(&ctx,
1038*32b31808SJens Wiklander                                          pt_test_data[pt_index_test_data[i]],
1039*32b31808SJens Wiklander                                          pt_len_test_data[i],
1040*32b31808SJens Wiklander                                          buf, sizeof(buf), &olen);
1041*32b31808SJens Wiklander                 if (ret != 0) {
1042*32b31808SJens Wiklander                     goto exit;
1043*32b31808SJens Wiklander                 }
1044*32b31808SJens Wiklander                 if (olen != pt_len_test_data[i]) {
1045*32b31808SJens Wiklander                     goto exit;
1046*32b31808SJens Wiklander                 }
1047*32b31808SJens Wiklander             }
1048817466cbSJens Wiklander 
1049*32b31808SJens Wiklander             ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1050*32b31808SJens Wiklander             if (ret != 0) {
10513d3b0591SJens Wiklander                 goto exit;
1052*32b31808SJens Wiklander             }
10533d3b0591SJens Wiklander 
105411fa71b9SJerome Forissier             if (memcmp(buf, ct_test_data[j * 6 + i],
105511fa71b9SJerome Forissier                        pt_len_test_data[i]) != 0 ||
1056*32b31808SJens Wiklander                 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
10573d3b0591SJens Wiklander                 ret = 1;
10583d3b0591SJens Wiklander                 goto exit;
1059817466cbSJens Wiklander             }
1060817466cbSJens Wiklander 
1061817466cbSJens Wiklander             mbedtls_gcm_free(&ctx);
1062817466cbSJens Wiklander 
1063*32b31808SJens Wiklander             if (verbose != 0) {
1064817466cbSJens Wiklander                 mbedtls_printf("passed\n");
1065*32b31808SJens Wiklander             }
1066817466cbSJens Wiklander 
10673d3b0591SJens Wiklander             mbedtls_gcm_init(&ctx);
10683d3b0591SJens Wiklander 
1069*32b31808SJens Wiklander             if (verbose != 0) {
1070817466cbSJens Wiklander                 mbedtls_printf("  AES-GCM-%3d #%d split (%s): ",
1071817466cbSJens Wiklander                                key_len, i, "dec");
1072*32b31808SJens Wiklander             }
1073817466cbSJens Wiklander 
107411fa71b9SJerome Forissier             ret = mbedtls_gcm_setkey(&ctx, cipher,
107511fa71b9SJerome Forissier                                      key_test_data[key_index_test_data[i]],
10763d3b0591SJens Wiklander                                      key_len);
1077*32b31808SJens Wiklander             if (ret != 0) {
10783d3b0591SJens Wiklander                 goto exit;
1079*32b31808SJens Wiklander             }
1080817466cbSJens Wiklander 
1081817466cbSJens Wiklander             ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
108211fa71b9SJerome Forissier                                      iv_test_data[iv_index_test_data[i]],
1083*32b31808SJens Wiklander                                      iv_len_test_data[i]);
1084*32b31808SJens Wiklander             if (ret != 0) {
1085*32b31808SJens Wiklander                 goto exit;
1086*32b31808SJens Wiklander             }
1087*32b31808SJens Wiklander             ret = mbedtls_gcm_update_ad(&ctx,
108811fa71b9SJerome Forissier                                         additional_test_data[add_index_test_data[i]],
108911fa71b9SJerome Forissier                                         add_len_test_data[i]);
1090*32b31808SJens Wiklander             if (ret != 0) {
10913d3b0591SJens Wiklander                 goto exit;
1092*32b31808SJens Wiklander             }
1093817466cbSJens Wiklander 
1094*32b31808SJens Wiklander             if (pt_len_test_data[i] > 32) {
109511fa71b9SJerome Forissier                 size_t rest_len = pt_len_test_data[i] - 32;
1096*32b31808SJens Wiklander                 ret = mbedtls_gcm_update(&ctx,
1097*32b31808SJens Wiklander                                          ct_test_data[j * 6 + i], 32,
1098*32b31808SJens Wiklander                                          buf, sizeof(buf), &olen);
1099*32b31808SJens Wiklander                 if (ret != 0) {
11003d3b0591SJens Wiklander                     goto exit;
1101*32b31808SJens Wiklander                 }
1102*32b31808SJens Wiklander                 if (olen != 32) {
1103*32b31808SJens Wiklander                     goto exit;
1104*32b31808SJens Wiklander                 }
1105817466cbSJens Wiklander 
1106*32b31808SJens Wiklander                 ret = mbedtls_gcm_update(&ctx,
110711fa71b9SJerome Forissier                                          ct_test_data[j * 6 + i] + 32,
1108*32b31808SJens Wiklander                                          rest_len,
1109*32b31808SJens Wiklander                                          buf + 32, sizeof(buf) - 32, &olen);
1110*32b31808SJens Wiklander                 if (ret != 0) {
11113d3b0591SJens Wiklander                     goto exit;
1112817466cbSJens Wiklander                 }
1113*32b31808SJens Wiklander                 if (olen != rest_len) {
11143d3b0591SJens Wiklander                     goto exit;
1115817466cbSJens Wiklander                 }
1116*32b31808SJens Wiklander             } else {
1117*32b31808SJens Wiklander                 ret = mbedtls_gcm_update(&ctx,
1118*32b31808SJens Wiklander                                          ct_test_data[j * 6 + i],
1119*32b31808SJens Wiklander                                          pt_len_test_data[i],
1120*32b31808SJens Wiklander                                          buf, sizeof(buf), &olen);
1121*32b31808SJens Wiklander                 if (ret != 0) {
1122*32b31808SJens Wiklander                     goto exit;
1123*32b31808SJens Wiklander                 }
1124*32b31808SJens Wiklander                 if (olen != pt_len_test_data[i]) {
1125*32b31808SJens Wiklander                     goto exit;
1126*32b31808SJens Wiklander                 }
1127*32b31808SJens Wiklander             }
1128817466cbSJens Wiklander 
1129*32b31808SJens Wiklander             ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1130*32b31808SJens Wiklander             if (ret != 0) {
11313d3b0591SJens Wiklander                 goto exit;
1132*32b31808SJens Wiklander             }
11333d3b0591SJens Wiklander 
113411fa71b9SJerome Forissier             if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
113511fa71b9SJerome Forissier                        pt_len_test_data[i]) != 0 ||
1136*32b31808SJens Wiklander                 memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
11373d3b0591SJens Wiklander                 ret = 1;
11383d3b0591SJens Wiklander                 goto exit;
1139817466cbSJens Wiklander             }
1140817466cbSJens Wiklander 
1141817466cbSJens Wiklander             mbedtls_gcm_free(&ctx);
1142817466cbSJens Wiklander 
1143*32b31808SJens Wiklander             if (verbose != 0) {
1144817466cbSJens Wiklander                 mbedtls_printf("passed\n");
1145817466cbSJens Wiklander             }
1146817466cbSJens Wiklander         }
1147*32b31808SJens Wiklander     }
1148817466cbSJens Wiklander 
1149*32b31808SJens Wiklander     if (verbose != 0) {
1150817466cbSJens Wiklander         mbedtls_printf("\n");
1151*32b31808SJens Wiklander     }
1152817466cbSJens Wiklander 
11533d3b0591SJens Wiklander     ret = 0;
11543d3b0591SJens Wiklander 
11553d3b0591SJens Wiklander exit:
1156*32b31808SJens Wiklander     if (ret != 0) {
1157*32b31808SJens Wiklander         if (verbose != 0) {
11583d3b0591SJens Wiklander             mbedtls_printf("failed\n");
1159*32b31808SJens Wiklander         }
11603d3b0591SJens Wiklander         mbedtls_gcm_free(&ctx);
11613d3b0591SJens Wiklander     }
11623d3b0591SJens Wiklander 
1163*32b31808SJens Wiklander     return ret;
1164817466cbSJens Wiklander }
1165817466cbSJens Wiklander 
1166817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
1167817466cbSJens Wiklander 
1168817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */
1169