blob: e722313f151569d9b26fb83db91e1e58bd75ed55 [file] [log] [blame]
Edison Ai7b079202018-02-28 15:01:47 +08001// SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02002/**
3 * \file cipher.c
4 *
5 * \brief Generic cipher wrapper for mbed TLS
6 *
7 * \author Adriaan de Jong <dejong@fox-it.com>
8 *
9 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Jens Wiklander817466c2018-05-22 13:49:31 +020010 *
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may
12 * not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 *
23 * This file is part of mbed TLS (https://tls.mbed.org)
24 */
25
26#if !defined(MBEDTLS_CONFIG_FILE)
27#include "mbedtls/config.h"
28#else
29#include MBEDTLS_CONFIG_FILE
30#endif
31
32#if defined(MBEDTLS_CIPHER_C)
33
34#include "mbedtls/cipher.h"
35#include "mbedtls/cipher_internal.h"
Jens Wiklander50a57cf2019-03-13 10:41:54 +010036#include "mbedtls/platform_util.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020037
38#include <stdlib.h>
39#include <string.h>
40
Jens Wiklander50a57cf2019-03-13 10:41:54 +010041#if defined(MBEDTLS_CHACHAPOLY_C)
42#include "mbedtls/chachapoly.h"
43#endif
44
Jens Wiklander817466c2018-05-22 13:49:31 +020045#if defined(MBEDTLS_GCM_C)
46#include "mbedtls/gcm.h"
47#endif
48
49#if defined(MBEDTLS_CCM_C)
50#include "mbedtls/ccm.h"
51#endif
52
Jens Wiklander50a57cf2019-03-13 10:41:54 +010053#if defined(MBEDTLS_CHACHA20_C)
54#include "mbedtls/chacha20.h"
55#endif
56
Jens Wiklander817466c2018-05-22 13:49:31 +020057#if defined(MBEDTLS_CMAC_C)
58#include "mbedtls/cmac.h"
59#endif
60
61#if defined(MBEDTLS_PLATFORM_C)
62#include "mbedtls/platform.h"
63#else
64#define mbedtls_calloc calloc
65#define mbedtls_free free
66#endif
67
Jens Wiklander50a57cf2019-03-13 10:41:54 +010068#define CIPHER_VALIDATE_RET( cond ) \
69 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA )
70#define CIPHER_VALIDATE( cond ) \
71 MBEDTLS_INTERNAL_VALIDATE( cond )
Jens Wiklander817466c2018-05-22 13:49:31 +020072
Jens Wiklander50a57cf2019-03-13 10:41:54 +010073#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
74/* Compare the contents of two buffers in constant time.
75 * Returns 0 if the contents are bitwise identical, otherwise returns
76 * a non-zero value.
77 * This is currently only used by GCM and ChaCha20+Poly1305.
78 */
79static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len )
80{
81 const unsigned char *p1 = (const unsigned char*) v1;
82 const unsigned char *p2 = (const unsigned char*) v2;
83 size_t i;
84 unsigned char diff;
85
86 for( diff = 0, i = 0; i < len; i++ )
87 diff |= p1[i] ^ p2[i];
88
89 return( (int)diff );
Jens Wiklander817466c2018-05-22 13:49:31 +020090}
Jens Wiklander50a57cf2019-03-13 10:41:54 +010091#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +020092
93static int supported_init = 0;
94
95const int *mbedtls_cipher_list( void )
96{
97 const mbedtls_cipher_definition_t *def;
98 int *type;
99
100 if( ! supported_init )
101 {
102 def = mbedtls_cipher_definitions;
103 type = mbedtls_cipher_supported;
104
105 while( def->type != 0 )
106 *type++ = (*def++).type;
107
108 *type = 0;
109
110 supported_init = 1;
111 }
112
113 return( mbedtls_cipher_supported );
114}
115
116const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type )
117{
118 const mbedtls_cipher_definition_t *def;
119
120 for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
121 if( def->type == cipher_type )
122 return( def->info );
123
124 return( NULL );
125}
126
127const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name )
128{
129 const mbedtls_cipher_definition_t *def;
130
131 if( NULL == cipher_name )
132 return( NULL );
133
134 for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
135 if( ! strcmp( def->info->name, cipher_name ) )
136 return( def->info );
137
138 return( NULL );
139}
140
141const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
142 int key_bitlen,
143 const mbedtls_cipher_mode_t mode )
144{
145 const mbedtls_cipher_definition_t *def;
146
147 for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
148 if( def->info->base->cipher == cipher_id &&
149 def->info->key_bitlen == (unsigned) key_bitlen &&
150 def->info->mode == mode )
151 return( def->info );
152
153 return( NULL );
154}
155
156void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
157{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100158 CIPHER_VALIDATE( ctx != NULL );
Jens Wiklander817466c2018-05-22 13:49:31 +0200159 memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
160}
161
162void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
163{
164 if( ctx == NULL )
165 return;
166
167#if defined(MBEDTLS_CMAC_C)
168 if( ctx->cmac_ctx )
169 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100170 mbedtls_platform_zeroize( ctx->cmac_ctx,
171 sizeof( mbedtls_cmac_context_t ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200172 mbedtls_free( ctx->cmac_ctx );
173 }
174#endif
175
176 if( ctx->cipher_ctx )
177 ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
178
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100179 mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200180}
181
Edison Aiac347342018-12-19 15:36:28 +0800182int mbedtls_cipher_clone( mbedtls_cipher_context_t *dst,
183 const mbedtls_cipher_context_t *src )
184{
185 if( dst == NULL || dst->cipher_info == NULL ||
186 src == NULL || src->cipher_info == NULL)
187 {
188 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
189 }
190
191 dst->cipher_info = src->cipher_info;
192 dst->key_bitlen = src->key_bitlen;
193 dst->operation = src->operation;
194#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
195 dst->add_padding = src->add_padding;
196 dst->get_padding = src->get_padding;
197#endif
198 memcpy( dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH );
199 dst->unprocessed_len = src->unprocessed_len;
200 memcpy( dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH );
201 dst->iv_size = src->iv_size;
202 if( dst->cipher_info->base->ctx_clone_func )
203 dst->cipher_info->base->ctx_clone_func( dst->cipher_ctx, src->cipher_ctx );
204
205#if defined(MBEDTLS_CMAC_C)
206 if( dst->cmac_ctx != NULL && src->cmac_ctx != NULL )
207 memcpy( dst->cmac_ctx, src->cmac_ctx, sizeof( mbedtls_cmac_context_t ) );
208#endif
209 return( 0 );
210}
211
Jens Wiklander817466c2018-05-22 13:49:31 +0200212int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
213{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100214 CIPHER_VALIDATE_RET( ctx != NULL );
215 if( cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200216 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
217
218 memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
219
220 if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
221 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
222
223 ctx->cipher_info = cipher_info;
224
225#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
226 /*
227 * Ignore possible errors caused by a cipher mode that doesn't use padding
228 */
229#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
230 (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 );
231#else
232 (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE );
233#endif
234#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
235
236 return( 0 );
237}
238
Edison Aiac347342018-12-19 15:36:28 +0800239int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
240{
241 if( NULL == cipher_info || NULL == ctx )
242 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
243
244 ctx->cipher_info = cipher_info;
245 return( 0 );
246}
247
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100248int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
249 const unsigned char *key,
250 int key_bitlen,
251 const mbedtls_operation_t operation )
Jens Wiklander817466c2018-05-22 13:49:31 +0200252{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100253 CIPHER_VALIDATE_RET( ctx != NULL );
254 CIPHER_VALIDATE_RET( key != NULL );
255 CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT ||
256 operation == MBEDTLS_DECRYPT );
257 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200258 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
259
260 if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
261 (int) ctx->cipher_info->key_bitlen != key_bitlen )
262 {
263 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
264 }
265
266 ctx->key_bitlen = key_bitlen;
267 ctx->operation = operation;
268
269 /*
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100270 * For OFB, CFB and CTR mode always use the encryption key schedule
Jens Wiklander817466c2018-05-22 13:49:31 +0200271 */
272 if( MBEDTLS_ENCRYPT == operation ||
273 MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100274 MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200275 MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
276 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100277 return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
278 ctx->key_bitlen ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200279 }
280
281 if( MBEDTLS_DECRYPT == operation )
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100282 return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
283 ctx->key_bitlen ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200284
285 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
286}
287
288int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100289 const unsigned char *iv,
290 size_t iv_len )
Jens Wiklander817466c2018-05-22 13:49:31 +0200291{
292 size_t actual_iv_size;
293
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100294 CIPHER_VALIDATE_RET( ctx != NULL );
295 CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
296 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200297 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
298
299 /* avoid buffer overflow in ctx->iv */
300 if( iv_len > MBEDTLS_MAX_IV_LENGTH )
301 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
302
303 if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 )
304 actual_iv_size = iv_len;
305 else
306 {
307 actual_iv_size = ctx->cipher_info->iv_size;
308
309 /* avoid reading past the end of input buffer */
310 if( actual_iv_size > iv_len )
311 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
312 }
313
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100314#if defined(MBEDTLS_CHACHA20_C)
315 if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
316 {
317 if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
318 iv,
319 0U ) ) /* Initial counter value */
320 {
321 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
322 }
323 }
324#endif
325
326 if ( actual_iv_size != 0 )
327 {
328 memcpy( ctx->iv, iv, actual_iv_size );
329 ctx->iv_size = actual_iv_size;
330 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200331
332 return( 0 );
333}
334
335int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
336{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100337 CIPHER_VALIDATE_RET( ctx != NULL );
338 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200339 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
340
341 ctx->unprocessed_len = 0;
342
343 return( 0 );
344}
345
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100346#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200347int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
348 const unsigned char *ad, size_t ad_len )
349{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100350 CIPHER_VALIDATE_RET( ctx != NULL );
351 CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
352 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200353 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
354
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100355#if defined(MBEDTLS_GCM_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200356 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
357 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100358 return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
359 ctx->iv, ctx->iv_size, ad, ad_len ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200360 }
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100361#endif
362
363#if defined(MBEDTLS_CHACHAPOLY_C)
364 if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
365 {
366 int result;
367 mbedtls_chachapoly_mode_t mode;
368
369 mode = ( ctx->operation == MBEDTLS_ENCRYPT )
370 ? MBEDTLS_CHACHAPOLY_ENCRYPT
371 : MBEDTLS_CHACHAPOLY_DECRYPT;
372
373 result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
374 ctx->iv,
375 mode );
376 if ( result != 0 )
377 return( result );
378
379 return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
380 ad, ad_len ) );
381 }
382#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200383
384 return( 0 );
385}
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100386#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +0200387
388int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
389 size_t ilen, unsigned char *output, size_t *olen )
390{
391 int ret;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100392 size_t block_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200393
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100394 CIPHER_VALIDATE_RET( ctx != NULL );
395 CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
396 CIPHER_VALIDATE_RET( output != NULL );
397 CIPHER_VALIDATE_RET( olen != NULL );
398 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200399 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Jens Wiklander817466c2018-05-22 13:49:31 +0200400
401 *olen = 0;
402 block_size = mbedtls_cipher_get_block_size( ctx );
403
404 if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
405 {
406 if( ilen != block_size )
407 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
408
409 *olen = ilen;
410
411 if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
412 ctx->operation, input, output ) ) )
413 {
414 return( ret );
415 }
416
417 return( 0 );
418 }
419
420#if defined(MBEDTLS_GCM_C)
421 if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
422 {
423 *olen = ilen;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100424 return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
425 output ) );
426 }
427#endif
428
429#if defined(MBEDTLS_CHACHAPOLY_C)
430 if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
431 {
432 *olen = ilen;
433 return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
434 ilen, input, output ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200435 }
436#endif
437
438 if ( 0 == block_size )
439 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100440 return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
Jens Wiklander817466c2018-05-22 13:49:31 +0200441 }
442
443 if( input == output &&
444 ( ctx->unprocessed_len != 0 || ilen % block_size ) )
445 {
446 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
447 }
448
449#if defined(MBEDTLS_CIPHER_MODE_CBC)
450 if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
451 {
452 size_t copy_len = 0;
453
454 /*
455 * If there is not enough data for a full block, cache it.
456 */
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100457 if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
Jens Wiklander817466c2018-05-22 13:49:31 +0200458 ilen <= block_size - ctx->unprocessed_len ) ||
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100459 ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
460 ilen < block_size - ctx->unprocessed_len ) ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200461 ( ctx->operation == MBEDTLS_ENCRYPT &&
462 ilen < block_size - ctx->unprocessed_len ) )
463 {
464 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
465 ilen );
466
467 ctx->unprocessed_len += ilen;
468 return( 0 );
469 }
470
471 /*
472 * Process cached data first
473 */
474 if( 0 != ctx->unprocessed_len )
475 {
476 copy_len = block_size - ctx->unprocessed_len;
477
478 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
479 copy_len );
480
481 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
482 ctx->operation, block_size, ctx->iv,
483 ctx->unprocessed_data, output ) ) )
484 {
485 return( ret );
486 }
487
488 *olen += block_size;
489 output += block_size;
490 ctx->unprocessed_len = 0;
491
492 input += copy_len;
493 ilen -= copy_len;
494 }
495
496 /*
497 * Cache final, incomplete block
498 */
499 if( 0 != ilen )
500 {
501 if( 0 == block_size )
502 {
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100503 return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
Jens Wiklander817466c2018-05-22 13:49:31 +0200504 }
505
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100506 /* Encryption: only cache partial blocks
507 * Decryption w/ padding: always keep at least one whole block
508 * Decryption w/o padding: only cache partial blocks
509 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200510 copy_len = ilen % block_size;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100511 if( copy_len == 0 &&
512 ctx->operation == MBEDTLS_DECRYPT &&
513 NULL != ctx->add_padding)
514 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200515 copy_len = block_size;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100516 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200517
518 memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
519 copy_len );
520
521 ctx->unprocessed_len += copy_len;
522 ilen -= copy_len;
523 }
524
525 /*
526 * Process remaining full blocks
527 */
528 if( ilen )
529 {
530 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
531 ctx->operation, ilen, ctx->iv, input, output ) ) )
532 {
533 return( ret );
534 }
535
536 *olen += ilen;
537 }
538
539 return( 0 );
540 }
541#endif /* MBEDTLS_CIPHER_MODE_CBC */
542
543#if defined(MBEDTLS_CIPHER_MODE_CFB)
544 if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB )
545 {
546 if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
547 ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
548 input, output ) ) )
549 {
550 return( ret );
551 }
552
553 *olen = ilen;
554
555 return( 0 );
556 }
557#endif /* MBEDTLS_CIPHER_MODE_CFB */
558
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100559#if defined(MBEDTLS_CIPHER_MODE_OFB)
560 if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
561 {
562 if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
563 ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
564 {
565 return( ret );
566 }
567
568 *olen = ilen;
569
570 return( 0 );
571 }
572#endif /* MBEDTLS_CIPHER_MODE_OFB */
573
Jens Wiklander817466c2018-05-22 13:49:31 +0200574#if defined(MBEDTLS_CIPHER_MODE_CTR)
575 if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
576 {
577 if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
578 ilen, &ctx->unprocessed_len, ctx->iv,
579 ctx->unprocessed_data, input, output ) ) )
580 {
581 return( ret );
582 }
583
584 *olen = ilen;
585
586 return( 0 );
587 }
588#endif /* MBEDTLS_CIPHER_MODE_CTR */
589
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100590#if defined(MBEDTLS_CIPHER_MODE_XTS)
591 if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
592 {
593 if( ctx->unprocessed_len > 0 ) {
594 /* We can only process an entire data unit at a time. */
595 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
596 }
597
598 ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
599 ctx->operation, ilen, ctx->iv, input, output );
600 if( ret != 0 )
601 {
602 return( ret );
603 }
604
605 *olen = ilen;
606
607 return( 0 );
608 }
609#endif /* MBEDTLS_CIPHER_MODE_XTS */
610
Jens Wiklander817466c2018-05-22 13:49:31 +0200611#if defined(MBEDTLS_CIPHER_MODE_STREAM)
612 if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
613 {
614 if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
615 ilen, input, output ) ) )
616 {
617 return( ret );
618 }
619
620 *olen = ilen;
621
622 return( 0 );
623 }
624#endif /* MBEDTLS_CIPHER_MODE_STREAM */
625
626 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
627}
628
629#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
630#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
631/*
632 * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
633 */
634static void add_pkcs_padding( unsigned char *output, size_t output_len,
635 size_t data_len )
636{
637 size_t padding_len = output_len - data_len;
638 unsigned char i;
639
640 for( i = 0; i < padding_len; i++ )
641 output[data_len + i] = (unsigned char) padding_len;
642}
643
644static int get_pkcs_padding( unsigned char *input, size_t input_len,
645 size_t *data_len )
646{
647 size_t i, pad_idx;
648 unsigned char padding_len, bad = 0;
649
650 if( NULL == input || NULL == data_len )
651 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
652
653 padding_len = input[input_len - 1];
654 *data_len = input_len - padding_len;
655
656 /* Avoid logical || since it results in a branch */
657 bad |= padding_len > input_len;
658 bad |= padding_len == 0;
659
660 /* The number of bytes checked must be independent of padding_len,
661 * so pick input_len, which is usually 8 or 16 (one block) */
662 pad_idx = input_len - padding_len;
663 for( i = 0; i < input_len; i++ )
664 bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
665
666 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
667}
668#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
669
670#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
671/*
672 * One and zeros padding: fill with 80 00 ... 00
673 */
674static void add_one_and_zeros_padding( unsigned char *output,
675 size_t output_len, size_t data_len )
676{
677 size_t padding_len = output_len - data_len;
678 unsigned char i = 0;
679
680 output[data_len] = 0x80;
681 for( i = 1; i < padding_len; i++ )
682 output[data_len + i] = 0x00;
683}
684
685static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
686 size_t *data_len )
687{
688 size_t i;
689 unsigned char done = 0, prev_done, bad;
690
691 if( NULL == input || NULL == data_len )
692 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
693
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100694 bad = 0x80;
Jens Wiklander817466c2018-05-22 13:49:31 +0200695 *data_len = 0;
696 for( i = input_len; i > 0; i-- )
697 {
698 prev_done = done;
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100699 done |= ( input[i - 1] != 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200700 *data_len |= ( i - 1 ) * ( done != prev_done );
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100701 bad ^= input[i - 1] * ( done != prev_done );
Jens Wiklander817466c2018-05-22 13:49:31 +0200702 }
703
704 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
705
706}
707#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
708
709#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
710/*
711 * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
712 */
713static void add_zeros_and_len_padding( unsigned char *output,
714 size_t output_len, size_t data_len )
715{
716 size_t padding_len = output_len - data_len;
717 unsigned char i = 0;
718
719 for( i = 1; i < padding_len; i++ )
720 output[data_len + i - 1] = 0x00;
721 output[output_len - 1] = (unsigned char) padding_len;
722}
723
724static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
725 size_t *data_len )
726{
727 size_t i, pad_idx;
728 unsigned char padding_len, bad = 0;
729
730 if( NULL == input || NULL == data_len )
731 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
732
733 padding_len = input[input_len - 1];
734 *data_len = input_len - padding_len;
735
736 /* Avoid logical || since it results in a branch */
737 bad |= padding_len > input_len;
738 bad |= padding_len == 0;
739
740 /* The number of bytes checked must be independent of padding_len */
741 pad_idx = input_len - padding_len;
742 for( i = 0; i < input_len - 1; i++ )
743 bad |= input[i] * ( i >= pad_idx );
744
745 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
746}
747#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
748
749#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
750/*
751 * Zero padding: fill with 00 ... 00
752 */
753static void add_zeros_padding( unsigned char *output,
754 size_t output_len, size_t data_len )
755{
756 size_t i;
757
758 for( i = data_len; i < output_len; i++ )
759 output[i] = 0x00;
760}
761
762static int get_zeros_padding( unsigned char *input, size_t input_len,
763 size_t *data_len )
764{
765 size_t i;
766 unsigned char done = 0, prev_done;
767
768 if( NULL == input || NULL == data_len )
769 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
770
771 *data_len = 0;
772 for( i = input_len; i > 0; i-- )
773 {
774 prev_done = done;
775 done |= ( input[i-1] != 0 );
776 *data_len |= i * ( done != prev_done );
777 }
778
779 return( 0 );
780}
781#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
782
783/*
784 * No padding: don't pad :)
785 *
786 * There is no add_padding function (check for NULL in mbedtls_cipher_finish)
787 * but a trivial get_padding function
788 */
789static int get_no_padding( unsigned char *input, size_t input_len,
790 size_t *data_len )
791{
792 if( NULL == input || NULL == data_len )
793 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
794
795 *data_len = input_len;
796
797 return( 0 );
798}
799#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
800
801int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
802 unsigned char *output, size_t *olen )
803{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100804 CIPHER_VALIDATE_RET( ctx != NULL );
805 CIPHER_VALIDATE_RET( output != NULL );
806 CIPHER_VALIDATE_RET( olen != NULL );
807 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200808 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
809
810 *olen = 0;
811
812 if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100813 MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200814 MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
815 MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100816 MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200817 MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
818 {
819 return( 0 );
820 }
821
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100822 if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) ||
823 ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
824 {
825 return( 0 );
826 }
827
Jens Wiklander817466c2018-05-22 13:49:31 +0200828 if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
829 {
830 if( ctx->unprocessed_len != 0 )
831 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
832
833 return( 0 );
834 }
835
836#if defined(MBEDTLS_CIPHER_MODE_CBC)
837 if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
838 {
839 int ret = 0;
840
841 if( MBEDTLS_ENCRYPT == ctx->operation )
842 {
843 /* check for 'no padding' mode */
844 if( NULL == ctx->add_padding )
845 {
846 if( 0 != ctx->unprocessed_len )
847 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
848
849 return( 0 );
850 }
851
852 ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ),
853 ctx->unprocessed_len );
854 }
855 else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
856 {
857 /*
858 * For decrypt operations, expect a full block,
859 * or an empty block if no padding
860 */
861 if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
862 return( 0 );
863
864 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
865 }
866
867 /* cipher block */
868 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
869 ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv,
870 ctx->unprocessed_data, output ) ) )
871 {
872 return( ret );
873 }
874
875 /* Set output size for decryption */
876 if( MBEDTLS_DECRYPT == ctx->operation )
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100877 return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
878 olen ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200879
880 /* Set output size for encryption */
881 *olen = mbedtls_cipher_get_block_size( ctx );
882 return( 0 );
883 }
884#else
885 ((void) output);
886#endif /* MBEDTLS_CIPHER_MODE_CBC */
887
888 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
889}
890
891#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100892int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
893 mbedtls_cipher_padding_t mode )
Jens Wiklander817466c2018-05-22 13:49:31 +0200894{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100895 CIPHER_VALIDATE_RET( ctx != NULL );
896
897 if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
Jens Wiklander817466c2018-05-22 13:49:31 +0200898 {
899 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
900 }
901
902 switch( mode )
903 {
904#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
905 case MBEDTLS_PADDING_PKCS7:
906 ctx->add_padding = add_pkcs_padding;
907 ctx->get_padding = get_pkcs_padding;
908 break;
909#endif
910#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
911 case MBEDTLS_PADDING_ONE_AND_ZEROS:
912 ctx->add_padding = add_one_and_zeros_padding;
913 ctx->get_padding = get_one_and_zeros_padding;
914 break;
915#endif
916#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
917 case MBEDTLS_PADDING_ZEROS_AND_LEN:
918 ctx->add_padding = add_zeros_and_len_padding;
919 ctx->get_padding = get_zeros_and_len_padding;
920 break;
921#endif
922#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
923 case MBEDTLS_PADDING_ZEROS:
924 ctx->add_padding = add_zeros_padding;
925 ctx->get_padding = get_zeros_padding;
926 break;
927#endif
928 case MBEDTLS_PADDING_NONE:
929 ctx->add_padding = NULL;
930 ctx->get_padding = get_no_padding;
931 break;
932
933 default:
934 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
935 }
936
937 return( 0 );
938}
939#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
940
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100941#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200942int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
943 unsigned char *tag, size_t tag_len )
944{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100945 CIPHER_VALIDATE_RET( ctx != NULL );
946 CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
947 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200948 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
949
950 if( MBEDTLS_ENCRYPT != ctx->operation )
951 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
952
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100953#if defined(MBEDTLS_GCM_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200954 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100955 return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
956 tag, tag_len ) );
957#endif
958
959#if defined(MBEDTLS_CHACHAPOLY_C)
960 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
961 {
962 /* Don't allow truncated MAC for Poly1305 */
963 if ( tag_len != 16U )
964 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
965
966 return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
967 tag ) );
968 }
969#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200970
971 return( 0 );
972}
973
974int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
975 const unsigned char *tag, size_t tag_len )
976{
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100977 unsigned char check_tag[16];
Jens Wiklander817466c2018-05-22 13:49:31 +0200978 int ret;
979
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100980 CIPHER_VALIDATE_RET( ctx != NULL );
981 CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
982 if( ctx->cipher_info == NULL )
983 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
984
985 if( MBEDTLS_DECRYPT != ctx->operation )
Jens Wiklander817466c2018-05-22 13:49:31 +0200986 {
987 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
988 }
989
Jens Wiklander50a57cf2019-03-13 10:41:54 +0100990#if defined(MBEDTLS_GCM_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200991 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
992 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200993 if( tag_len > sizeof( check_tag ) )
994 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
995
996 if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
997 check_tag, tag_len ) ) )
998 {
999 return( ret );
1000 }
1001
1002 /* Check the tag in "constant-time" */
Jens Wiklander50a57cf2019-03-13 10:41:54 +01001003 if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +02001004 return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
1005
1006 return( 0 );
1007 }
Jens Wiklander50a57cf2019-03-13 10:41:54 +01001008#endif /* MBEDTLS_GCM_C */
1009
1010#if defined(MBEDTLS_CHACHAPOLY_C)
1011 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
1012 {
1013 /* Don't allow truncated MAC for Poly1305 */
1014 if ( tag_len != sizeof( check_tag ) )
1015 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1016
1017 ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
1018 check_tag );
1019 if ( ret != 0 )
1020 {
1021 return( ret );
1022 }
1023
1024 /* Check the tag in "constant-time" */
1025 if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
1026 return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
1027
1028 return( 0 );
1029 }
1030#endif /* MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +02001031
1032 return( 0 );
1033}
Jens Wiklander50a57cf2019-03-13 10:41:54 +01001034#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +02001035
1036/*
1037 * Packet-oriented wrapper for non-AEAD modes
1038 */
1039int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
1040 const unsigned char *iv, size_t iv_len,
1041 const unsigned char *input, size_t ilen,
1042 unsigned char *output, size_t *olen )
1043{
1044 int ret;
1045 size_t finish_olen;
1046
Jens Wiklander50a57cf2019-03-13 10:41:54 +01001047 CIPHER_VALIDATE_RET( ctx != NULL );
1048 CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
1049 CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
1050 CIPHER_VALIDATE_RET( output != NULL );
1051 CIPHER_VALIDATE_RET( olen != NULL );
1052
Jens Wiklander817466c2018-05-22 13:49:31 +02001053 if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
1054 return( ret );
1055
1056 if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
1057 return( ret );
1058
1059 if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
1060 return( ret );
1061
1062 if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
1063 return( ret );
1064
1065 *olen += finish_olen;
1066
1067 return( 0 );
1068}
1069
1070#if defined(MBEDTLS_CIPHER_MODE_AEAD)
1071/*
1072 * Packet-oriented encryption for AEAD modes
1073 */
1074int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
1075 const unsigned char *iv, size_t iv_len,
1076 const unsigned char *ad, size_t ad_len,
1077 const unsigned char *input, size_t ilen,
1078 unsigned char *output, size_t *olen,
1079 unsigned char *tag, size_t tag_len )
1080{
Jens Wiklander50a57cf2019-03-13 10:41:54 +01001081 CIPHER_VALIDATE_RET( ctx != NULL );
1082 CIPHER_VALIDATE_RET( iv != NULL );
1083 CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
1084 CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
1085 CIPHER_VALIDATE_RET( output != NULL );
1086 CIPHER_VALIDATE_RET( olen != NULL );
1087 CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
1088
Jens Wiklander817466c2018-05-22 13:49:31 +02001089#if defined(MBEDTLS_GCM_C)
1090 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
1091 {
1092 *olen = ilen;
1093 return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen,
1094 iv, iv_len, ad, ad_len, input, output,
1095 tag_len, tag ) );
1096 }
1097#endif /* MBEDTLS_GCM_C */
1098#if defined(MBEDTLS_CCM_C)
1099 if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
1100 {
1101 *olen = ilen;
1102 return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
1103 iv, iv_len, ad, ad_len, input, output,
1104 tag, tag_len ) );
1105 }
1106#endif /* MBEDTLS_CCM_C */
Jens Wiklander50a57cf2019-03-13 10:41:54 +01001107#if defined(MBEDTLS_CHACHAPOLY_C)
1108 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
1109 {
1110 /* ChachaPoly has fixed length nonce and MAC (tag) */
1111 if ( ( iv_len != ctx->cipher_info->iv_size ) ||
1112 ( tag_len != 16U ) )
1113 {
1114 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1115 }
1116
1117 *olen = ilen;
1118 return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx,
1119 ilen, iv, ad, ad_len, input, output, tag ) );
1120 }
1121#endif /* MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +02001122
1123 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1124}
1125
1126/*
1127 * Packet-oriented decryption for AEAD modes
1128 */
1129int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
1130 const unsigned char *iv, size_t iv_len,
1131 const unsigned char *ad, size_t ad_len,
1132 const unsigned char *input, size_t ilen,
1133 unsigned char *output, size_t *olen,
1134 const unsigned char *tag, size_t tag_len )
1135{
Jens Wiklander50a57cf2019-03-13 10:41:54 +01001136 CIPHER_VALIDATE_RET( ctx != NULL );
1137 CIPHER_VALIDATE_RET( iv != NULL );
1138 CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
1139 CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
1140 CIPHER_VALIDATE_RET( output != NULL );
1141 CIPHER_VALIDATE_RET( olen != NULL );
1142 CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
1143
Jens Wiklander817466c2018-05-22 13:49:31 +02001144#if defined(MBEDTLS_GCM_C)
1145 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
1146 {
1147 int ret;
1148
1149 *olen = ilen;
1150 ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
1151 iv, iv_len, ad, ad_len,
1152 tag, tag_len, input, output );
1153
1154 if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED )
1155 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1156
1157 return( ret );
1158 }
1159#endif /* MBEDTLS_GCM_C */
1160#if defined(MBEDTLS_CCM_C)
1161 if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
1162 {
1163 int ret;
1164
1165 *olen = ilen;
1166 ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
1167 iv, iv_len, ad, ad_len,
1168 input, output, tag, tag_len );
1169
1170 if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
1171 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1172
1173 return( ret );
1174 }
1175#endif /* MBEDTLS_CCM_C */
Jens Wiklander50a57cf2019-03-13 10:41:54 +01001176#if defined(MBEDTLS_CHACHAPOLY_C)
1177 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
1178 {
1179 int ret;
1180
1181 /* ChachaPoly has fixed length nonce and MAC (tag) */
1182 if ( ( iv_len != ctx->cipher_info->iv_size ) ||
1183 ( tag_len != 16U ) )
1184 {
1185 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1186 }
1187
1188 *olen = ilen;
1189 ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen,
1190 iv, ad, ad_len, tag, input, output );
1191
1192 if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED )
1193 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1194
1195 return( ret );
1196 }
1197#endif /* MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +02001198
1199 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1200}
1201#endif /* MBEDTLS_CIPHER_MODE_AEAD */
1202
1203#endif /* MBEDTLS_CIPHER_C */