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