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