xref: /optee_os/lib/libmbedtls/mbedtls/library/gcm.c (revision 817466cb476de705a8e3dabe1ef165fe27a18c2f)
1*817466cbSJens Wiklander /*
2*817466cbSJens Wiklander  *  NIST SP800-38D compliant GCM implementation
3*817466cbSJens Wiklander  *
4*817466cbSJens Wiklander  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5*817466cbSJens Wiklander  *  SPDX-License-Identifier: Apache-2.0
6*817466cbSJens Wiklander  *
7*817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8*817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9*817466cbSJens Wiklander  *  You may obtain a copy of the License at
10*817466cbSJens Wiklander  *
11*817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12*817466cbSJens Wiklander  *
13*817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14*817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15*817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17*817466cbSJens Wiklander  *  limitations under the License.
18*817466cbSJens Wiklander  *
19*817466cbSJens Wiklander  *  This file is part of mbed TLS (https://tls.mbed.org)
20*817466cbSJens Wiklander  */
21*817466cbSJens Wiklander 
22*817466cbSJens Wiklander /*
23*817466cbSJens Wiklander  * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
24*817466cbSJens Wiklander  *
25*817466cbSJens Wiklander  * See also:
26*817466cbSJens Wiklander  * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
27*817466cbSJens Wiklander  *
28*817466cbSJens Wiklander  * We use the algorithm described as Shoup's method with 4-bit tables in
29*817466cbSJens Wiklander  * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
30*817466cbSJens Wiklander  */
31*817466cbSJens Wiklander 
32*817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE)
33*817466cbSJens Wiklander #include "mbedtls/config.h"
34*817466cbSJens Wiklander #else
35*817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE
36*817466cbSJens Wiklander #endif
37*817466cbSJens Wiklander 
38*817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
39*817466cbSJens Wiklander 
40*817466cbSJens Wiklander #include "mbedtls/gcm.h"
41*817466cbSJens Wiklander 
42*817466cbSJens Wiklander #include <string.h>
43*817466cbSJens Wiklander 
44*817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C)
45*817466cbSJens Wiklander #include "mbedtls/aesni.h"
46*817466cbSJens Wiklander #endif
47*817466cbSJens Wiklander 
48*817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
49*817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
50*817466cbSJens Wiklander #include "mbedtls/platform.h"
51*817466cbSJens Wiklander #else
52*817466cbSJens Wiklander #include <stdio.h>
53*817466cbSJens Wiklander #define mbedtls_printf printf
54*817466cbSJens Wiklander #endif /* MBEDTLS_PLATFORM_C */
55*817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
56*817466cbSJens Wiklander 
57*817466cbSJens Wiklander /*
58*817466cbSJens Wiklander  * 32-bit integer manipulation macros (big endian)
59*817466cbSJens Wiklander  */
60*817466cbSJens Wiklander #ifndef GET_UINT32_BE
61*817466cbSJens Wiklander #define GET_UINT32_BE(n,b,i)                            \
62*817466cbSJens Wiklander {                                                       \
63*817466cbSJens Wiklander     (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
64*817466cbSJens Wiklander         | ( (uint32_t) (b)[(i) + 1] << 16 )             \
65*817466cbSJens Wiklander         | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
66*817466cbSJens Wiklander         | ( (uint32_t) (b)[(i) + 3]       );            \
67*817466cbSJens Wiklander }
68*817466cbSJens Wiklander #endif
69*817466cbSJens Wiklander 
70*817466cbSJens Wiklander #ifndef PUT_UINT32_BE
71*817466cbSJens Wiklander #define PUT_UINT32_BE(n,b,i)                            \
72*817466cbSJens Wiklander {                                                       \
73*817466cbSJens Wiklander     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
74*817466cbSJens Wiklander     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
75*817466cbSJens Wiklander     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
76*817466cbSJens Wiklander     (b)[(i) + 3] = (unsigned char) ( (n)       );       \
77*817466cbSJens Wiklander }
78*817466cbSJens Wiklander #endif
79*817466cbSJens Wiklander 
80*817466cbSJens Wiklander /* Implementation that should never be optimized out by the compiler */
81*817466cbSJens Wiklander static void mbedtls_zeroize( void *v, size_t n ) {
82*817466cbSJens Wiklander     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
83*817466cbSJens Wiklander }
84*817466cbSJens Wiklander 
85*817466cbSJens Wiklander /*
86*817466cbSJens Wiklander  * Initialize a context
87*817466cbSJens Wiklander  */
88*817466cbSJens Wiklander void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
89*817466cbSJens Wiklander {
90*817466cbSJens Wiklander     memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
91*817466cbSJens Wiklander }
92*817466cbSJens Wiklander 
93*817466cbSJens Wiklander /*
94*817466cbSJens Wiklander  * Precompute small multiples of H, that is set
95*817466cbSJens Wiklander  *      HH[i] || HL[i] = H times i,
96*817466cbSJens Wiklander  * where i is seen as a field element as in [MGV], ie high-order bits
97*817466cbSJens Wiklander  * correspond to low powers of P. The result is stored in the same way, that
98*817466cbSJens Wiklander  * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
99*817466cbSJens Wiklander  * corresponds to P^127.
100*817466cbSJens Wiklander  */
101*817466cbSJens Wiklander static int gcm_gen_table( mbedtls_gcm_context *ctx )
102*817466cbSJens Wiklander {
103*817466cbSJens Wiklander     int ret, i, j;
104*817466cbSJens Wiklander     uint64_t hi, lo;
105*817466cbSJens Wiklander     uint64_t vl, vh;
106*817466cbSJens Wiklander     unsigned char h[16];
107*817466cbSJens Wiklander     size_t olen = 0;
108*817466cbSJens Wiklander 
109*817466cbSJens Wiklander     memset( h, 0, 16 );
110*817466cbSJens Wiklander     if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
111*817466cbSJens Wiklander         return( ret );
112*817466cbSJens Wiklander 
113*817466cbSJens Wiklander     /* pack h as two 64-bits ints, big-endian */
114*817466cbSJens Wiklander     GET_UINT32_BE( hi, h,  0  );
115*817466cbSJens Wiklander     GET_UINT32_BE( lo, h,  4  );
116*817466cbSJens Wiklander     vh = (uint64_t) hi << 32 | lo;
117*817466cbSJens Wiklander 
118*817466cbSJens Wiklander     GET_UINT32_BE( hi, h,  8  );
119*817466cbSJens Wiklander     GET_UINT32_BE( lo, h,  12 );
120*817466cbSJens Wiklander     vl = (uint64_t) hi << 32 | lo;
121*817466cbSJens Wiklander 
122*817466cbSJens Wiklander     /* 8 = 1000 corresponds to 1 in GF(2^128) */
123*817466cbSJens Wiklander     ctx->HL[8] = vl;
124*817466cbSJens Wiklander     ctx->HH[8] = vh;
125*817466cbSJens Wiklander 
126*817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
127*817466cbSJens Wiklander     /* With CLMUL support, we need only h, not the rest of the table */
128*817466cbSJens Wiklander     if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
129*817466cbSJens Wiklander         return( 0 );
130*817466cbSJens Wiklander #endif
131*817466cbSJens Wiklander 
132*817466cbSJens Wiklander     /* 0 corresponds to 0 in GF(2^128) */
133*817466cbSJens Wiklander     ctx->HH[0] = 0;
134*817466cbSJens Wiklander     ctx->HL[0] = 0;
135*817466cbSJens Wiklander 
136*817466cbSJens Wiklander     for( i = 4; i > 0; i >>= 1 )
137*817466cbSJens Wiklander     {
138*817466cbSJens Wiklander         uint32_t T = ( vl & 1 ) * 0xe1000000U;
139*817466cbSJens Wiklander         vl  = ( vh << 63 ) | ( vl >> 1 );
140*817466cbSJens Wiklander         vh  = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
141*817466cbSJens Wiklander 
142*817466cbSJens Wiklander         ctx->HL[i] = vl;
143*817466cbSJens Wiklander         ctx->HH[i] = vh;
144*817466cbSJens Wiklander     }
145*817466cbSJens Wiklander 
146*817466cbSJens Wiklander     for( i = 2; i <= 8; i *= 2 )
147*817466cbSJens Wiklander     {
148*817466cbSJens Wiklander         uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
149*817466cbSJens Wiklander         vh = *HiH;
150*817466cbSJens Wiklander         vl = *HiL;
151*817466cbSJens Wiklander         for( j = 1; j < i; j++ )
152*817466cbSJens Wiklander         {
153*817466cbSJens Wiklander             HiH[j] = vh ^ ctx->HH[j];
154*817466cbSJens Wiklander             HiL[j] = vl ^ ctx->HL[j];
155*817466cbSJens Wiklander         }
156*817466cbSJens Wiklander     }
157*817466cbSJens Wiklander 
158*817466cbSJens Wiklander     return( 0 );
159*817466cbSJens Wiklander }
160*817466cbSJens Wiklander 
161*817466cbSJens Wiklander int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
162*817466cbSJens Wiklander                         mbedtls_cipher_id_t cipher,
163*817466cbSJens Wiklander                         const unsigned char *key,
164*817466cbSJens Wiklander                         unsigned int keybits )
165*817466cbSJens Wiklander {
166*817466cbSJens Wiklander     int ret;
167*817466cbSJens Wiklander     const mbedtls_cipher_info_t *cipher_info;
168*817466cbSJens Wiklander 
169*817466cbSJens Wiklander     cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
170*817466cbSJens Wiklander     if( cipher_info == NULL )
171*817466cbSJens Wiklander         return( MBEDTLS_ERR_GCM_BAD_INPUT );
172*817466cbSJens Wiklander 
173*817466cbSJens Wiklander     if( cipher_info->block_size != 16 )
174*817466cbSJens Wiklander         return( MBEDTLS_ERR_GCM_BAD_INPUT );
175*817466cbSJens Wiklander 
176*817466cbSJens Wiklander     mbedtls_cipher_free( &ctx->cipher_ctx );
177*817466cbSJens Wiklander 
178*817466cbSJens Wiklander     if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
179*817466cbSJens Wiklander         return( ret );
180*817466cbSJens Wiklander 
181*817466cbSJens Wiklander     if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
182*817466cbSJens Wiklander                                MBEDTLS_ENCRYPT ) ) != 0 )
183*817466cbSJens Wiklander     {
184*817466cbSJens Wiklander         return( ret );
185*817466cbSJens Wiklander     }
186*817466cbSJens Wiklander 
187*817466cbSJens Wiklander     if( ( ret = gcm_gen_table( ctx ) ) != 0 )
188*817466cbSJens Wiklander         return( ret );
189*817466cbSJens Wiklander 
190*817466cbSJens Wiklander     return( 0 );
191*817466cbSJens Wiklander }
192*817466cbSJens Wiklander 
193*817466cbSJens Wiklander /*
194*817466cbSJens Wiklander  * Shoup's method for multiplication use this table with
195*817466cbSJens Wiklander  *      last4[x] = x times P^128
196*817466cbSJens Wiklander  * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
197*817466cbSJens Wiklander  */
198*817466cbSJens Wiklander static const uint64_t last4[16] =
199*817466cbSJens Wiklander {
200*817466cbSJens Wiklander     0x0000, 0x1c20, 0x3840, 0x2460,
201*817466cbSJens Wiklander     0x7080, 0x6ca0, 0x48c0, 0x54e0,
202*817466cbSJens Wiklander     0xe100, 0xfd20, 0xd940, 0xc560,
203*817466cbSJens Wiklander     0x9180, 0x8da0, 0xa9c0, 0xb5e0
204*817466cbSJens Wiklander };
205*817466cbSJens Wiklander 
206*817466cbSJens Wiklander /*
207*817466cbSJens Wiklander  * Sets output to x times H using the precomputed tables.
208*817466cbSJens Wiklander  * x and output are seen as elements of GF(2^128) as in [MGV].
209*817466cbSJens Wiklander  */
210*817466cbSJens Wiklander static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
211*817466cbSJens Wiklander                       unsigned char output[16] )
212*817466cbSJens Wiklander {
213*817466cbSJens Wiklander     int i = 0;
214*817466cbSJens Wiklander     unsigned char lo, hi, rem;
215*817466cbSJens Wiklander     uint64_t zh, zl;
216*817466cbSJens Wiklander 
217*817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
218*817466cbSJens Wiklander     if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
219*817466cbSJens Wiklander         unsigned char h[16];
220*817466cbSJens Wiklander 
221*817466cbSJens Wiklander         PUT_UINT32_BE( ctx->HH[8] >> 32, h,  0 );
222*817466cbSJens Wiklander         PUT_UINT32_BE( ctx->HH[8],       h,  4 );
223*817466cbSJens Wiklander         PUT_UINT32_BE( ctx->HL[8] >> 32, h,  8 );
224*817466cbSJens Wiklander         PUT_UINT32_BE( ctx->HL[8],       h, 12 );
225*817466cbSJens Wiklander 
226*817466cbSJens Wiklander         mbedtls_aesni_gcm_mult( output, x, h );
227*817466cbSJens Wiklander         return;
228*817466cbSJens Wiklander     }
229*817466cbSJens Wiklander #endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
230*817466cbSJens Wiklander 
231*817466cbSJens Wiklander     lo = x[15] & 0xf;
232*817466cbSJens Wiklander 
233*817466cbSJens Wiklander     zh = ctx->HH[lo];
234*817466cbSJens Wiklander     zl = ctx->HL[lo];
235*817466cbSJens Wiklander 
236*817466cbSJens Wiklander     for( i = 15; i >= 0; i-- )
237*817466cbSJens Wiklander     {
238*817466cbSJens Wiklander         lo = x[i] & 0xf;
239*817466cbSJens Wiklander         hi = x[i] >> 4;
240*817466cbSJens Wiklander 
241*817466cbSJens Wiklander         if( i != 15 )
242*817466cbSJens Wiklander         {
243*817466cbSJens Wiklander             rem = (unsigned char) zl & 0xf;
244*817466cbSJens Wiklander             zl = ( zh << 60 ) | ( zl >> 4 );
245*817466cbSJens Wiklander             zh = ( zh >> 4 );
246*817466cbSJens Wiklander             zh ^= (uint64_t) last4[rem] << 48;
247*817466cbSJens Wiklander             zh ^= ctx->HH[lo];
248*817466cbSJens Wiklander             zl ^= ctx->HL[lo];
249*817466cbSJens Wiklander 
250*817466cbSJens Wiklander         }
251*817466cbSJens Wiklander 
252*817466cbSJens Wiklander         rem = (unsigned char) zl & 0xf;
253*817466cbSJens Wiklander         zl = ( zh << 60 ) | ( zl >> 4 );
254*817466cbSJens Wiklander         zh = ( zh >> 4 );
255*817466cbSJens Wiklander         zh ^= (uint64_t) last4[rem] << 48;
256*817466cbSJens Wiklander         zh ^= ctx->HH[hi];
257*817466cbSJens Wiklander         zl ^= ctx->HL[hi];
258*817466cbSJens Wiklander     }
259*817466cbSJens Wiklander 
260*817466cbSJens Wiklander     PUT_UINT32_BE( zh >> 32, output, 0 );
261*817466cbSJens Wiklander     PUT_UINT32_BE( zh, output, 4 );
262*817466cbSJens Wiklander     PUT_UINT32_BE( zl >> 32, output, 8 );
263*817466cbSJens Wiklander     PUT_UINT32_BE( zl, output, 12 );
264*817466cbSJens Wiklander }
265*817466cbSJens Wiklander 
266*817466cbSJens Wiklander int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
267*817466cbSJens Wiklander                 int mode,
268*817466cbSJens Wiklander                 const unsigned char *iv,
269*817466cbSJens Wiklander                 size_t iv_len,
270*817466cbSJens Wiklander                 const unsigned char *add,
271*817466cbSJens Wiklander                 size_t add_len )
272*817466cbSJens Wiklander {
273*817466cbSJens Wiklander     int ret;
274*817466cbSJens Wiklander     unsigned char work_buf[16];
275*817466cbSJens Wiklander     size_t i;
276*817466cbSJens Wiklander     const unsigned char *p;
277*817466cbSJens Wiklander     size_t use_len, olen = 0;
278*817466cbSJens Wiklander 
279*817466cbSJens Wiklander     /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
280*817466cbSJens Wiklander     /* IV is not allowed to be zero length */
281*817466cbSJens Wiklander     if( iv_len == 0 ||
282*817466cbSJens Wiklander       ( (uint64_t) iv_len  ) >> 61 != 0 ||
283*817466cbSJens Wiklander       ( (uint64_t) add_len ) >> 61 != 0 )
284*817466cbSJens Wiklander     {
285*817466cbSJens Wiklander         return( MBEDTLS_ERR_GCM_BAD_INPUT );
286*817466cbSJens Wiklander     }
287*817466cbSJens Wiklander 
288*817466cbSJens Wiklander     memset( ctx->y, 0x00, sizeof(ctx->y) );
289*817466cbSJens Wiklander     memset( ctx->buf, 0x00, sizeof(ctx->buf) );
290*817466cbSJens Wiklander 
291*817466cbSJens Wiklander     ctx->mode = mode;
292*817466cbSJens Wiklander     ctx->len = 0;
293*817466cbSJens Wiklander     ctx->add_len = 0;
294*817466cbSJens Wiklander 
295*817466cbSJens Wiklander     if( iv_len == 12 )
296*817466cbSJens Wiklander     {
297*817466cbSJens Wiklander         memcpy( ctx->y, iv, iv_len );
298*817466cbSJens Wiklander         ctx->y[15] = 1;
299*817466cbSJens Wiklander     }
300*817466cbSJens Wiklander     else
301*817466cbSJens Wiklander     {
302*817466cbSJens Wiklander         memset( work_buf, 0x00, 16 );
303*817466cbSJens Wiklander         PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
304*817466cbSJens Wiklander 
305*817466cbSJens Wiklander         p = iv;
306*817466cbSJens Wiklander         while( iv_len > 0 )
307*817466cbSJens Wiklander         {
308*817466cbSJens Wiklander             use_len = ( iv_len < 16 ) ? iv_len : 16;
309*817466cbSJens Wiklander 
310*817466cbSJens Wiklander             for( i = 0; i < use_len; i++ )
311*817466cbSJens Wiklander                 ctx->y[i] ^= p[i];
312*817466cbSJens Wiklander 
313*817466cbSJens Wiklander             gcm_mult( ctx, ctx->y, ctx->y );
314*817466cbSJens Wiklander 
315*817466cbSJens Wiklander             iv_len -= use_len;
316*817466cbSJens Wiklander             p += use_len;
317*817466cbSJens Wiklander         }
318*817466cbSJens Wiklander 
319*817466cbSJens Wiklander         for( i = 0; i < 16; i++ )
320*817466cbSJens Wiklander             ctx->y[i] ^= work_buf[i];
321*817466cbSJens Wiklander 
322*817466cbSJens Wiklander         gcm_mult( ctx, ctx->y, ctx->y );
323*817466cbSJens Wiklander     }
324*817466cbSJens Wiklander 
325*817466cbSJens Wiklander     if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
326*817466cbSJens Wiklander                              &olen ) ) != 0 )
327*817466cbSJens Wiklander     {
328*817466cbSJens Wiklander         return( ret );
329*817466cbSJens Wiklander     }
330*817466cbSJens Wiklander 
331*817466cbSJens Wiklander     ctx->add_len = add_len;
332*817466cbSJens Wiklander     p = add;
333*817466cbSJens Wiklander     while( add_len > 0 )
334*817466cbSJens Wiklander     {
335*817466cbSJens Wiklander         use_len = ( add_len < 16 ) ? add_len : 16;
336*817466cbSJens Wiklander 
337*817466cbSJens Wiklander         for( i = 0; i < use_len; i++ )
338*817466cbSJens Wiklander             ctx->buf[i] ^= p[i];
339*817466cbSJens Wiklander 
340*817466cbSJens Wiklander         gcm_mult( ctx, ctx->buf, ctx->buf );
341*817466cbSJens Wiklander 
342*817466cbSJens Wiklander         add_len -= use_len;
343*817466cbSJens Wiklander         p += use_len;
344*817466cbSJens Wiklander     }
345*817466cbSJens Wiklander 
346*817466cbSJens Wiklander     return( 0 );
347*817466cbSJens Wiklander }
348*817466cbSJens Wiklander 
349*817466cbSJens Wiklander int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
350*817466cbSJens Wiklander                 size_t length,
351*817466cbSJens Wiklander                 const unsigned char *input,
352*817466cbSJens Wiklander                 unsigned char *output )
353*817466cbSJens Wiklander {
354*817466cbSJens Wiklander     int ret;
355*817466cbSJens Wiklander     unsigned char ectr[16];
356*817466cbSJens Wiklander     size_t i;
357*817466cbSJens Wiklander     const unsigned char *p;
358*817466cbSJens Wiklander     unsigned char *out_p = output;
359*817466cbSJens Wiklander     size_t use_len, olen = 0;
360*817466cbSJens Wiklander 
361*817466cbSJens Wiklander     if( output > input && (size_t) ( output - input ) < length )
362*817466cbSJens Wiklander         return( MBEDTLS_ERR_GCM_BAD_INPUT );
363*817466cbSJens Wiklander 
364*817466cbSJens Wiklander     /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
365*817466cbSJens Wiklander      * Also check for possible overflow */
366*817466cbSJens Wiklander     if( ctx->len + length < ctx->len ||
367*817466cbSJens Wiklander         (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
368*817466cbSJens Wiklander     {
369*817466cbSJens Wiklander         return( MBEDTLS_ERR_GCM_BAD_INPUT );
370*817466cbSJens Wiklander     }
371*817466cbSJens Wiklander 
372*817466cbSJens Wiklander     ctx->len += length;
373*817466cbSJens Wiklander 
374*817466cbSJens Wiklander     p = input;
375*817466cbSJens Wiklander     while( length > 0 )
376*817466cbSJens Wiklander     {
377*817466cbSJens Wiklander         use_len = ( length < 16 ) ? length : 16;
378*817466cbSJens Wiklander 
379*817466cbSJens Wiklander         for( i = 16; i > 12; i-- )
380*817466cbSJens Wiklander             if( ++ctx->y[i - 1] != 0 )
381*817466cbSJens Wiklander                 break;
382*817466cbSJens Wiklander 
383*817466cbSJens Wiklander         if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
384*817466cbSJens Wiklander                                    &olen ) ) != 0 )
385*817466cbSJens Wiklander         {
386*817466cbSJens Wiklander             return( ret );
387*817466cbSJens Wiklander         }
388*817466cbSJens Wiklander 
389*817466cbSJens Wiklander         for( i = 0; i < use_len; i++ )
390*817466cbSJens Wiklander         {
391*817466cbSJens Wiklander             if( ctx->mode == MBEDTLS_GCM_DECRYPT )
392*817466cbSJens Wiklander                 ctx->buf[i] ^= p[i];
393*817466cbSJens Wiklander             out_p[i] = ectr[i] ^ p[i];
394*817466cbSJens Wiklander             if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
395*817466cbSJens Wiklander                 ctx->buf[i] ^= out_p[i];
396*817466cbSJens Wiklander         }
397*817466cbSJens Wiklander 
398*817466cbSJens Wiklander         gcm_mult( ctx, ctx->buf, ctx->buf );
399*817466cbSJens Wiklander 
400*817466cbSJens Wiklander         length -= use_len;
401*817466cbSJens Wiklander         p += use_len;
402*817466cbSJens Wiklander         out_p += use_len;
403*817466cbSJens Wiklander     }
404*817466cbSJens Wiklander 
405*817466cbSJens Wiklander     return( 0 );
406*817466cbSJens Wiklander }
407*817466cbSJens Wiklander 
408*817466cbSJens Wiklander int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
409*817466cbSJens Wiklander                 unsigned char *tag,
410*817466cbSJens Wiklander                 size_t tag_len )
411*817466cbSJens Wiklander {
412*817466cbSJens Wiklander     unsigned char work_buf[16];
413*817466cbSJens Wiklander     size_t i;
414*817466cbSJens Wiklander     uint64_t orig_len = ctx->len * 8;
415*817466cbSJens Wiklander     uint64_t orig_add_len = ctx->add_len * 8;
416*817466cbSJens Wiklander 
417*817466cbSJens Wiklander     if( tag_len > 16 || tag_len < 4 )
418*817466cbSJens Wiklander         return( MBEDTLS_ERR_GCM_BAD_INPUT );
419*817466cbSJens Wiklander 
420*817466cbSJens Wiklander     memcpy( tag, ctx->base_ectr, tag_len );
421*817466cbSJens Wiklander 
422*817466cbSJens Wiklander     if( orig_len || orig_add_len )
423*817466cbSJens Wiklander     {
424*817466cbSJens Wiklander         memset( work_buf, 0x00, 16 );
425*817466cbSJens Wiklander 
426*817466cbSJens Wiklander         PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0  );
427*817466cbSJens Wiklander         PUT_UINT32_BE( ( orig_add_len       ), work_buf, 4  );
428*817466cbSJens Wiklander         PUT_UINT32_BE( ( orig_len     >> 32 ), work_buf, 8  );
429*817466cbSJens Wiklander         PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
430*817466cbSJens Wiklander 
431*817466cbSJens Wiklander         for( i = 0; i < 16; i++ )
432*817466cbSJens Wiklander             ctx->buf[i] ^= work_buf[i];
433*817466cbSJens Wiklander 
434*817466cbSJens Wiklander         gcm_mult( ctx, ctx->buf, ctx->buf );
435*817466cbSJens Wiklander 
436*817466cbSJens Wiklander         for( i = 0; i < tag_len; i++ )
437*817466cbSJens Wiklander             tag[i] ^= ctx->buf[i];
438*817466cbSJens Wiklander     }
439*817466cbSJens Wiklander 
440*817466cbSJens Wiklander     return( 0 );
441*817466cbSJens Wiklander }
442*817466cbSJens Wiklander 
443*817466cbSJens Wiklander int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
444*817466cbSJens Wiklander                        int mode,
445*817466cbSJens Wiklander                        size_t length,
446*817466cbSJens Wiklander                        const unsigned char *iv,
447*817466cbSJens Wiklander                        size_t iv_len,
448*817466cbSJens Wiklander                        const unsigned char *add,
449*817466cbSJens Wiklander                        size_t add_len,
450*817466cbSJens Wiklander                        const unsigned char *input,
451*817466cbSJens Wiklander                        unsigned char *output,
452*817466cbSJens Wiklander                        size_t tag_len,
453*817466cbSJens Wiklander                        unsigned char *tag )
454*817466cbSJens Wiklander {
455*817466cbSJens Wiklander     int ret;
456*817466cbSJens Wiklander 
457*817466cbSJens Wiklander     if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
458*817466cbSJens Wiklander         return( ret );
459*817466cbSJens Wiklander 
460*817466cbSJens Wiklander     if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
461*817466cbSJens Wiklander         return( ret );
462*817466cbSJens Wiklander 
463*817466cbSJens Wiklander     if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
464*817466cbSJens Wiklander         return( ret );
465*817466cbSJens Wiklander 
466*817466cbSJens Wiklander     return( 0 );
467*817466cbSJens Wiklander }
468*817466cbSJens Wiklander 
469*817466cbSJens Wiklander int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
470*817466cbSJens Wiklander                       size_t length,
471*817466cbSJens Wiklander                       const unsigned char *iv,
472*817466cbSJens Wiklander                       size_t iv_len,
473*817466cbSJens Wiklander                       const unsigned char *add,
474*817466cbSJens Wiklander                       size_t add_len,
475*817466cbSJens Wiklander                       const unsigned char *tag,
476*817466cbSJens Wiklander                       size_t tag_len,
477*817466cbSJens Wiklander                       const unsigned char *input,
478*817466cbSJens Wiklander                       unsigned char *output )
479*817466cbSJens Wiklander {
480*817466cbSJens Wiklander     int ret;
481*817466cbSJens Wiklander     unsigned char check_tag[16];
482*817466cbSJens Wiklander     size_t i;
483*817466cbSJens Wiklander     int diff;
484*817466cbSJens Wiklander 
485*817466cbSJens Wiklander     if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
486*817466cbSJens Wiklander                                    iv, iv_len, add, add_len,
487*817466cbSJens Wiklander                                    input, output, tag_len, check_tag ) ) != 0 )
488*817466cbSJens Wiklander     {
489*817466cbSJens Wiklander         return( ret );
490*817466cbSJens Wiklander     }
491*817466cbSJens Wiklander 
492*817466cbSJens Wiklander     /* Check tag in "constant-time" */
493*817466cbSJens Wiklander     for( diff = 0, i = 0; i < tag_len; i++ )
494*817466cbSJens Wiklander         diff |= tag[i] ^ check_tag[i];
495*817466cbSJens Wiklander 
496*817466cbSJens Wiklander     if( diff != 0 )
497*817466cbSJens Wiklander     {
498*817466cbSJens Wiklander         mbedtls_zeroize( output, length );
499*817466cbSJens Wiklander         return( MBEDTLS_ERR_GCM_AUTH_FAILED );
500*817466cbSJens Wiklander     }
501*817466cbSJens Wiklander 
502*817466cbSJens Wiklander     return( 0 );
503*817466cbSJens Wiklander }
504*817466cbSJens Wiklander 
505*817466cbSJens Wiklander void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
506*817466cbSJens Wiklander {
507*817466cbSJens Wiklander     mbedtls_cipher_free( &ctx->cipher_ctx );
508*817466cbSJens Wiklander     mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
509*817466cbSJens Wiklander }
510*817466cbSJens Wiklander 
511*817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
512*817466cbSJens Wiklander /*
513*817466cbSJens Wiklander  * AES-GCM test vectors from:
514*817466cbSJens Wiklander  *
515*817466cbSJens Wiklander  * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
516*817466cbSJens Wiklander  */
517*817466cbSJens Wiklander #define MAX_TESTS   6
518*817466cbSJens Wiklander 
519*817466cbSJens Wiklander static const int key_index[MAX_TESTS] =
520*817466cbSJens Wiklander     { 0, 0, 1, 1, 1, 1 };
521*817466cbSJens Wiklander 
522*817466cbSJens Wiklander static const unsigned char key[MAX_TESTS][32] =
523*817466cbSJens Wiklander {
524*817466cbSJens Wiklander     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525*817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526*817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527*817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
528*817466cbSJens Wiklander     { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
529*817466cbSJens Wiklander       0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
530*817466cbSJens Wiklander       0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
531*817466cbSJens Wiklander       0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
532*817466cbSJens Wiklander };
533*817466cbSJens Wiklander 
534*817466cbSJens Wiklander static const size_t iv_len[MAX_TESTS] =
535*817466cbSJens Wiklander     { 12, 12, 12, 12, 8, 60 };
536*817466cbSJens Wiklander 
537*817466cbSJens Wiklander static const int iv_index[MAX_TESTS] =
538*817466cbSJens Wiklander     { 0, 0, 1, 1, 1, 2 };
539*817466cbSJens Wiklander 
540*817466cbSJens Wiklander static const unsigned char iv[MAX_TESTS][64] =
541*817466cbSJens Wiklander {
542*817466cbSJens Wiklander     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543*817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00 },
544*817466cbSJens Wiklander     { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
545*817466cbSJens Wiklander       0xde, 0xca, 0xf8, 0x88 },
546*817466cbSJens Wiklander     { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
547*817466cbSJens Wiklander       0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
548*817466cbSJens Wiklander       0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
549*817466cbSJens Wiklander       0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
550*817466cbSJens Wiklander       0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
551*817466cbSJens Wiklander       0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
552*817466cbSJens Wiklander       0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
553*817466cbSJens Wiklander       0xa6, 0x37, 0xb3, 0x9b },
554*817466cbSJens Wiklander };
555*817466cbSJens Wiklander 
556*817466cbSJens Wiklander static const size_t add_len[MAX_TESTS] =
557*817466cbSJens Wiklander     { 0, 0, 0, 20, 20, 20 };
558*817466cbSJens Wiklander 
559*817466cbSJens Wiklander static const int add_index[MAX_TESTS] =
560*817466cbSJens Wiklander     { 0, 0, 0, 1, 1, 1 };
561*817466cbSJens Wiklander 
562*817466cbSJens Wiklander static const unsigned char additional[MAX_TESTS][64] =
563*817466cbSJens Wiklander {
564*817466cbSJens Wiklander     { 0x00 },
565*817466cbSJens Wiklander     { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
566*817466cbSJens Wiklander       0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
567*817466cbSJens Wiklander       0xab, 0xad, 0xda, 0xd2 },
568*817466cbSJens Wiklander };
569*817466cbSJens Wiklander 
570*817466cbSJens Wiklander static const size_t pt_len[MAX_TESTS] =
571*817466cbSJens Wiklander     { 0, 16, 64, 60, 60, 60 };
572*817466cbSJens Wiklander 
573*817466cbSJens Wiklander static const int pt_index[MAX_TESTS] =
574*817466cbSJens Wiklander     { 0, 0, 1, 1, 1, 1 };
575*817466cbSJens Wiklander 
576*817466cbSJens Wiklander static const unsigned char pt[MAX_TESTS][64] =
577*817466cbSJens Wiklander {
578*817466cbSJens Wiklander     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579*817466cbSJens Wiklander       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
580*817466cbSJens Wiklander     { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
581*817466cbSJens Wiklander       0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
582*817466cbSJens Wiklander       0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
583*817466cbSJens Wiklander       0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
584*817466cbSJens Wiklander       0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
585*817466cbSJens Wiklander       0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
586*817466cbSJens Wiklander       0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
587*817466cbSJens Wiklander       0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
588*817466cbSJens Wiklander };
589*817466cbSJens Wiklander 
590*817466cbSJens Wiklander static const unsigned char ct[MAX_TESTS * 3][64] =
591*817466cbSJens Wiklander {
592*817466cbSJens Wiklander     { 0x00 },
593*817466cbSJens Wiklander     { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
594*817466cbSJens Wiklander       0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
595*817466cbSJens Wiklander     { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
596*817466cbSJens Wiklander       0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
597*817466cbSJens Wiklander       0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
598*817466cbSJens Wiklander       0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
599*817466cbSJens Wiklander       0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
600*817466cbSJens Wiklander       0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
601*817466cbSJens Wiklander       0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
602*817466cbSJens Wiklander       0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
603*817466cbSJens Wiklander     { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
604*817466cbSJens Wiklander       0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
605*817466cbSJens Wiklander       0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
606*817466cbSJens Wiklander       0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
607*817466cbSJens Wiklander       0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
608*817466cbSJens Wiklander       0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
609*817466cbSJens Wiklander       0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
610*817466cbSJens Wiklander       0x3d, 0x58, 0xe0, 0x91 },
611*817466cbSJens Wiklander     { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
612*817466cbSJens Wiklander       0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
613*817466cbSJens Wiklander       0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
614*817466cbSJens Wiklander       0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
615*817466cbSJens Wiklander       0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
616*817466cbSJens Wiklander       0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
617*817466cbSJens Wiklander       0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
618*817466cbSJens Wiklander       0xc2, 0x3f, 0x45, 0x98 },
619*817466cbSJens Wiklander     { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
620*817466cbSJens Wiklander       0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
621*817466cbSJens Wiklander       0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
622*817466cbSJens Wiklander       0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
623*817466cbSJens Wiklander       0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
624*817466cbSJens Wiklander       0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
625*817466cbSJens Wiklander       0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
626*817466cbSJens Wiklander       0x4c, 0x34, 0xae, 0xe5 },
627*817466cbSJens Wiklander     { 0x00 },
628*817466cbSJens Wiklander     { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
629*817466cbSJens Wiklander       0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
630*817466cbSJens Wiklander     { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
631*817466cbSJens Wiklander       0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
632*817466cbSJens Wiklander       0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
633*817466cbSJens Wiklander       0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
634*817466cbSJens Wiklander       0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
635*817466cbSJens Wiklander       0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
636*817466cbSJens Wiklander       0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
637*817466cbSJens Wiklander       0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
638*817466cbSJens Wiklander     { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
639*817466cbSJens Wiklander       0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
640*817466cbSJens Wiklander       0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
641*817466cbSJens Wiklander       0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
642*817466cbSJens Wiklander       0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
643*817466cbSJens Wiklander       0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
644*817466cbSJens Wiklander       0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
645*817466cbSJens Wiklander       0xcc, 0xda, 0x27, 0x10 },
646*817466cbSJens Wiklander     { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
647*817466cbSJens Wiklander       0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
648*817466cbSJens Wiklander       0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
649*817466cbSJens Wiklander       0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
650*817466cbSJens Wiklander       0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
651*817466cbSJens Wiklander       0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
652*817466cbSJens Wiklander       0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
653*817466cbSJens Wiklander       0xa0, 0xf0, 0x62, 0xf7 },
654*817466cbSJens Wiklander     { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
655*817466cbSJens Wiklander       0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
656*817466cbSJens Wiklander       0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
657*817466cbSJens Wiklander       0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
658*817466cbSJens Wiklander       0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
659*817466cbSJens Wiklander       0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
660*817466cbSJens Wiklander       0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
661*817466cbSJens Wiklander       0xe9, 0xb7, 0x37, 0x3b },
662*817466cbSJens Wiklander     { 0x00 },
663*817466cbSJens Wiklander     { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
664*817466cbSJens Wiklander       0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
665*817466cbSJens Wiklander     { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
666*817466cbSJens Wiklander       0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
667*817466cbSJens Wiklander       0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
668*817466cbSJens Wiklander       0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
669*817466cbSJens Wiklander       0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
670*817466cbSJens Wiklander       0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
671*817466cbSJens Wiklander       0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
672*817466cbSJens Wiklander       0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
673*817466cbSJens Wiklander     { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
674*817466cbSJens Wiklander       0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
675*817466cbSJens Wiklander       0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
676*817466cbSJens Wiklander       0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
677*817466cbSJens Wiklander       0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
678*817466cbSJens Wiklander       0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
679*817466cbSJens Wiklander       0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
680*817466cbSJens Wiklander       0xbc, 0xc9, 0xf6, 0x62 },
681*817466cbSJens Wiklander     { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
682*817466cbSJens Wiklander       0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
683*817466cbSJens Wiklander       0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
684*817466cbSJens Wiklander       0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
685*817466cbSJens Wiklander       0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
686*817466cbSJens Wiklander       0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
687*817466cbSJens Wiklander       0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
688*817466cbSJens Wiklander       0xf4, 0x7c, 0x9b, 0x1f },
689*817466cbSJens Wiklander     { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
690*817466cbSJens Wiklander       0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
691*817466cbSJens Wiklander       0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
692*817466cbSJens Wiklander       0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
693*817466cbSJens Wiklander       0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
694*817466cbSJens Wiklander       0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
695*817466cbSJens Wiklander       0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
696*817466cbSJens Wiklander       0x44, 0xae, 0x7e, 0x3f },
697*817466cbSJens Wiklander };
698*817466cbSJens Wiklander 
699*817466cbSJens Wiklander static const unsigned char tag[MAX_TESTS * 3][16] =
700*817466cbSJens Wiklander {
701*817466cbSJens Wiklander     { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
702*817466cbSJens Wiklander       0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
703*817466cbSJens Wiklander     { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
704*817466cbSJens Wiklander       0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
705*817466cbSJens Wiklander     { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
706*817466cbSJens Wiklander       0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
707*817466cbSJens Wiklander     { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
708*817466cbSJens Wiklander       0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
709*817466cbSJens Wiklander     { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
710*817466cbSJens Wiklander       0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
711*817466cbSJens Wiklander     { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
712*817466cbSJens Wiklander       0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
713*817466cbSJens Wiklander     { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
714*817466cbSJens Wiklander       0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
715*817466cbSJens Wiklander     { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
716*817466cbSJens Wiklander       0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
717*817466cbSJens Wiklander     { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
718*817466cbSJens Wiklander       0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
719*817466cbSJens Wiklander     { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
720*817466cbSJens Wiklander       0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
721*817466cbSJens Wiklander     { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
722*817466cbSJens Wiklander       0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
723*817466cbSJens Wiklander     { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
724*817466cbSJens Wiklander       0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
725*817466cbSJens Wiklander     { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
726*817466cbSJens Wiklander       0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
727*817466cbSJens Wiklander     { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
728*817466cbSJens Wiklander       0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
729*817466cbSJens Wiklander     { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
730*817466cbSJens Wiklander       0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
731*817466cbSJens Wiklander     { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
732*817466cbSJens Wiklander       0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
733*817466cbSJens Wiklander     { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
734*817466cbSJens Wiklander       0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
735*817466cbSJens Wiklander     { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
736*817466cbSJens Wiklander       0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
737*817466cbSJens Wiklander };
738*817466cbSJens Wiklander 
739*817466cbSJens Wiklander int mbedtls_gcm_self_test( int verbose )
740*817466cbSJens Wiklander {
741*817466cbSJens Wiklander     mbedtls_gcm_context ctx;
742*817466cbSJens Wiklander     unsigned char buf[64];
743*817466cbSJens Wiklander     unsigned char tag_buf[16];
744*817466cbSJens Wiklander     int i, j, ret;
745*817466cbSJens Wiklander     mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
746*817466cbSJens Wiklander 
747*817466cbSJens Wiklander     mbedtls_gcm_init( &ctx );
748*817466cbSJens Wiklander 
749*817466cbSJens Wiklander     for( j = 0; j < 3; j++ )
750*817466cbSJens Wiklander     {
751*817466cbSJens Wiklander         int key_len = 128 + 64 * j;
752*817466cbSJens Wiklander 
753*817466cbSJens Wiklander         for( i = 0; i < MAX_TESTS; i++ )
754*817466cbSJens Wiklander         {
755*817466cbSJens Wiklander             if( verbose != 0 )
756*817466cbSJens Wiklander                 mbedtls_printf( "  AES-GCM-%3d #%d (%s): ",
757*817466cbSJens Wiklander                                  key_len, i, "enc" );
758*817466cbSJens Wiklander 
759*817466cbSJens Wiklander             mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
760*817466cbSJens Wiklander 
761*817466cbSJens Wiklander             ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
762*817466cbSJens Wiklander                                      pt_len[i],
763*817466cbSJens Wiklander                                      iv[iv_index[i]], iv_len[i],
764*817466cbSJens Wiklander                                      additional[add_index[i]], add_len[i],
765*817466cbSJens Wiklander                                      pt[pt_index[i]], buf, 16, tag_buf );
766*817466cbSJens Wiklander 
767*817466cbSJens Wiklander             if( ret != 0 ||
768*817466cbSJens Wiklander                 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
769*817466cbSJens Wiklander                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
770*817466cbSJens Wiklander             {
771*817466cbSJens Wiklander                 if( verbose != 0 )
772*817466cbSJens Wiklander                     mbedtls_printf( "failed\n" );
773*817466cbSJens Wiklander 
774*817466cbSJens Wiklander                 return( 1 );
775*817466cbSJens Wiklander             }
776*817466cbSJens Wiklander 
777*817466cbSJens Wiklander             mbedtls_gcm_free( &ctx );
778*817466cbSJens Wiklander 
779*817466cbSJens Wiklander             if( verbose != 0 )
780*817466cbSJens Wiklander                 mbedtls_printf( "passed\n" );
781*817466cbSJens Wiklander 
782*817466cbSJens Wiklander             if( verbose != 0 )
783*817466cbSJens Wiklander                 mbedtls_printf( "  AES-GCM-%3d #%d (%s): ",
784*817466cbSJens Wiklander                                  key_len, i, "dec" );
785*817466cbSJens Wiklander 
786*817466cbSJens Wiklander             mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
787*817466cbSJens Wiklander 
788*817466cbSJens Wiklander             ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
789*817466cbSJens Wiklander                                      pt_len[i],
790*817466cbSJens Wiklander                                      iv[iv_index[i]], iv_len[i],
791*817466cbSJens Wiklander                                      additional[add_index[i]], add_len[i],
792*817466cbSJens Wiklander                                      ct[j * 6 + i], buf, 16, tag_buf );
793*817466cbSJens Wiklander 
794*817466cbSJens Wiklander             if( ret != 0 ||
795*817466cbSJens Wiklander                 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
796*817466cbSJens Wiklander                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
797*817466cbSJens Wiklander             {
798*817466cbSJens Wiklander                 if( verbose != 0 )
799*817466cbSJens Wiklander                     mbedtls_printf( "failed\n" );
800*817466cbSJens Wiklander 
801*817466cbSJens Wiklander                 return( 1 );
802*817466cbSJens Wiklander             }
803*817466cbSJens Wiklander 
804*817466cbSJens Wiklander             mbedtls_gcm_free( &ctx );
805*817466cbSJens Wiklander 
806*817466cbSJens Wiklander             if( verbose != 0 )
807*817466cbSJens Wiklander                 mbedtls_printf( "passed\n" );
808*817466cbSJens Wiklander 
809*817466cbSJens Wiklander             if( verbose != 0 )
810*817466cbSJens Wiklander                 mbedtls_printf( "  AES-GCM-%3d #%d split (%s): ",
811*817466cbSJens Wiklander                                  key_len, i, "enc" );
812*817466cbSJens Wiklander 
813*817466cbSJens Wiklander             mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
814*817466cbSJens Wiklander 
815*817466cbSJens Wiklander             ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
816*817466cbSJens Wiklander                               iv[iv_index[i]], iv_len[i],
817*817466cbSJens Wiklander                               additional[add_index[i]], add_len[i] );
818*817466cbSJens Wiklander             if( ret != 0 )
819*817466cbSJens Wiklander             {
820*817466cbSJens Wiklander                 if( verbose != 0 )
821*817466cbSJens Wiklander                     mbedtls_printf( "failed\n" );
822*817466cbSJens Wiklander 
823*817466cbSJens Wiklander                 return( 1 );
824*817466cbSJens Wiklander             }
825*817466cbSJens Wiklander 
826*817466cbSJens Wiklander             if( pt_len[i] > 32 )
827*817466cbSJens Wiklander             {
828*817466cbSJens Wiklander                 size_t rest_len = pt_len[i] - 32;
829*817466cbSJens Wiklander                 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
830*817466cbSJens Wiklander                 if( ret != 0 )
831*817466cbSJens Wiklander                 {
832*817466cbSJens Wiklander                     if( verbose != 0 )
833*817466cbSJens Wiklander                         mbedtls_printf( "failed\n" );
834*817466cbSJens Wiklander 
835*817466cbSJens Wiklander                     return( 1 );
836*817466cbSJens Wiklander                 }
837*817466cbSJens Wiklander 
838*817466cbSJens Wiklander                 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
839*817466cbSJens Wiklander                                   buf + 32 );
840*817466cbSJens Wiklander                 if( ret != 0 )
841*817466cbSJens Wiklander                 {
842*817466cbSJens Wiklander                     if( verbose != 0 )
843*817466cbSJens Wiklander                         mbedtls_printf( "failed\n" );
844*817466cbSJens Wiklander 
845*817466cbSJens Wiklander                     return( 1 );
846*817466cbSJens Wiklander                 }
847*817466cbSJens Wiklander             }
848*817466cbSJens Wiklander             else
849*817466cbSJens Wiklander             {
850*817466cbSJens Wiklander                 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
851*817466cbSJens Wiklander                 if( ret != 0 )
852*817466cbSJens Wiklander                 {
853*817466cbSJens Wiklander                     if( verbose != 0 )
854*817466cbSJens Wiklander                         mbedtls_printf( "failed\n" );
855*817466cbSJens Wiklander 
856*817466cbSJens Wiklander                     return( 1 );
857*817466cbSJens Wiklander                 }
858*817466cbSJens Wiklander             }
859*817466cbSJens Wiklander 
860*817466cbSJens Wiklander             ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
861*817466cbSJens Wiklander             if( ret != 0 ||
862*817466cbSJens Wiklander                 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
863*817466cbSJens Wiklander                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
864*817466cbSJens Wiklander             {
865*817466cbSJens Wiklander                 if( verbose != 0 )
866*817466cbSJens Wiklander                     mbedtls_printf( "failed\n" );
867*817466cbSJens Wiklander 
868*817466cbSJens Wiklander                 return( 1 );
869*817466cbSJens Wiklander             }
870*817466cbSJens Wiklander 
871*817466cbSJens Wiklander             mbedtls_gcm_free( &ctx );
872*817466cbSJens Wiklander 
873*817466cbSJens Wiklander             if( verbose != 0 )
874*817466cbSJens Wiklander                 mbedtls_printf( "passed\n" );
875*817466cbSJens Wiklander 
876*817466cbSJens Wiklander             if( verbose != 0 )
877*817466cbSJens Wiklander                 mbedtls_printf( "  AES-GCM-%3d #%d split (%s): ",
878*817466cbSJens Wiklander                                  key_len, i, "dec" );
879*817466cbSJens Wiklander 
880*817466cbSJens Wiklander             mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
881*817466cbSJens Wiklander 
882*817466cbSJens Wiklander             ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
883*817466cbSJens Wiklander                               iv[iv_index[i]], iv_len[i],
884*817466cbSJens Wiklander                               additional[add_index[i]], add_len[i] );
885*817466cbSJens Wiklander             if( ret != 0 )
886*817466cbSJens Wiklander             {
887*817466cbSJens Wiklander                 if( verbose != 0 )
888*817466cbSJens Wiklander                     mbedtls_printf( "failed\n" );
889*817466cbSJens Wiklander 
890*817466cbSJens Wiklander                 return( 1 );
891*817466cbSJens Wiklander             }
892*817466cbSJens Wiklander 
893*817466cbSJens Wiklander             if( pt_len[i] > 32 )
894*817466cbSJens Wiklander             {
895*817466cbSJens Wiklander                 size_t rest_len = pt_len[i] - 32;
896*817466cbSJens Wiklander                 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
897*817466cbSJens Wiklander                 if( ret != 0 )
898*817466cbSJens Wiklander                 {
899*817466cbSJens Wiklander                     if( verbose != 0 )
900*817466cbSJens Wiklander                         mbedtls_printf( "failed\n" );
901*817466cbSJens Wiklander 
902*817466cbSJens Wiklander                     return( 1 );
903*817466cbSJens Wiklander                 }
904*817466cbSJens Wiklander 
905*817466cbSJens Wiklander                 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
906*817466cbSJens Wiklander                                   buf + 32 );
907*817466cbSJens Wiklander                 if( ret != 0 )
908*817466cbSJens Wiklander                 {
909*817466cbSJens Wiklander                     if( verbose != 0 )
910*817466cbSJens Wiklander                         mbedtls_printf( "failed\n" );
911*817466cbSJens Wiklander 
912*817466cbSJens Wiklander                     return( 1 );
913*817466cbSJens Wiklander                 }
914*817466cbSJens Wiklander             }
915*817466cbSJens Wiklander             else
916*817466cbSJens Wiklander             {
917*817466cbSJens Wiklander                 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
918*817466cbSJens Wiklander                 if( ret != 0 )
919*817466cbSJens Wiklander                 {
920*817466cbSJens Wiklander                     if( verbose != 0 )
921*817466cbSJens Wiklander                         mbedtls_printf( "failed\n" );
922*817466cbSJens Wiklander 
923*817466cbSJens Wiklander                     return( 1 );
924*817466cbSJens Wiklander                 }
925*817466cbSJens Wiklander             }
926*817466cbSJens Wiklander 
927*817466cbSJens Wiklander             ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
928*817466cbSJens Wiklander             if( ret != 0 ||
929*817466cbSJens Wiklander                 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
930*817466cbSJens Wiklander                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
931*817466cbSJens Wiklander             {
932*817466cbSJens Wiklander                 if( verbose != 0 )
933*817466cbSJens Wiklander                     mbedtls_printf( "failed\n" );
934*817466cbSJens Wiklander 
935*817466cbSJens Wiklander                 return( 1 );
936*817466cbSJens Wiklander             }
937*817466cbSJens Wiklander 
938*817466cbSJens Wiklander             mbedtls_gcm_free( &ctx );
939*817466cbSJens Wiklander 
940*817466cbSJens Wiklander             if( verbose != 0 )
941*817466cbSJens Wiklander                 mbedtls_printf( "passed\n" );
942*817466cbSJens Wiklander 
943*817466cbSJens Wiklander         }
944*817466cbSJens Wiklander     }
945*817466cbSJens Wiklander 
946*817466cbSJens Wiklander     if( verbose != 0 )
947*817466cbSJens Wiklander         mbedtls_printf( "\n" );
948*817466cbSJens Wiklander 
949*817466cbSJens Wiklander     return( 0 );
950*817466cbSJens Wiklander }
951*817466cbSJens Wiklander 
952*817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
953*817466cbSJens Wiklander 
954*817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */
955