blob: 31123c5517e07f579567ef8ee072b6559c3f7419 [file] [log] [blame]
Edison Aic6672fd2018-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 Wiklander3d3b0592019-03-20 15:30:29 +010036#include "mbedtls/platform_util.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020037
38#include <stdlib.h>
39#include <string.h>
40
Jens Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +0100179 mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200180}
181
Edison Ai12484fc2018-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 Wiklander3d3b0592019-03-20 15:30:29 +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 Ai12484fc2018-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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +0100355#if defined(MBEDTLS_GCM_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200356 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
357 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +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 Wiklander3d3b0592019-03-20 15:30:29 +0100392 size_t block_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200393
Jens Wiklander3d3b0592019-03-20 15:30:29 +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 );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200403 if ( 0 == block_size )
404 {
405 return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
406 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200407
408 if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
409 {
410 if( ilen != block_size )
411 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
412
413 *olen = ilen;
414
415 if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
416 ctx->operation, input, output ) ) )
417 {
418 return( ret );
419 }
420
421 return( 0 );
422 }
423
424#if defined(MBEDTLS_GCM_C)
425 if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
426 {
427 *olen = ilen;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100428 return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
429 output ) );
430 }
431#endif
432
433#if defined(MBEDTLS_CHACHAPOLY_C)
434 if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
435 {
436 *olen = ilen;
437 return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
438 ilen, input, output ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200439 }
440#endif
441
Jens Wiklander817466c2018-05-22 13:49:31 +0200442 if( input == output &&
443 ( ctx->unprocessed_len != 0 || ilen % block_size ) )
444 {
445 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
446 }
447
448#if defined(MBEDTLS_CIPHER_MODE_CBC)
449 if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
450 {
451 size_t copy_len = 0;
452
453 /*
454 * If there is not enough data for a full block, cache it.
455 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100456 if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
Jens Wiklander817466c2018-05-22 13:49:31 +0200457 ilen <= block_size - ctx->unprocessed_len ) ||
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100458 ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
459 ilen < block_size - ctx->unprocessed_len ) ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200460 ( ctx->operation == MBEDTLS_ENCRYPT &&
461 ilen < block_size - ctx->unprocessed_len ) )
462 {
463 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
464 ilen );
465
466 ctx->unprocessed_len += ilen;
467 return( 0 );
468 }
469
470 /*
471 * Process cached data first
472 */
473 if( 0 != ctx->unprocessed_len )
474 {
475 copy_len = block_size - ctx->unprocessed_len;
476
477 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
478 copy_len );
479
480 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
481 ctx->operation, block_size, ctx->iv,
482 ctx->unprocessed_data, output ) ) )
483 {
484 return( ret );
485 }
486
487 *olen += block_size;
488 output += block_size;
489 ctx->unprocessed_len = 0;
490
491 input += copy_len;
492 ilen -= copy_len;
493 }
494
495 /*
496 * Cache final, incomplete block
497 */
498 if( 0 != ilen )
499 {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100500 /* Encryption: only cache partial blocks
501 * Decryption w/ padding: always keep at least one whole block
502 * Decryption w/o padding: only cache partial blocks
503 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200504 copy_len = ilen % block_size;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100505 if( copy_len == 0 &&
506 ctx->operation == MBEDTLS_DECRYPT &&
507 NULL != ctx->add_padding)
508 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200509 copy_len = block_size;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100510 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200511
512 memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
513 copy_len );
514
515 ctx->unprocessed_len += copy_len;
516 ilen -= copy_len;
517 }
518
519 /*
520 * Process remaining full blocks
521 */
522 if( ilen )
523 {
524 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
525 ctx->operation, ilen, ctx->iv, input, output ) ) )
526 {
527 return( ret );
528 }
529
530 *olen += ilen;
531 }
532
533 return( 0 );
534 }
535#endif /* MBEDTLS_CIPHER_MODE_CBC */
536
537#if defined(MBEDTLS_CIPHER_MODE_CFB)
538 if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB )
539 {
540 if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
541 ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
542 input, output ) ) )
543 {
544 return( ret );
545 }
546
547 *olen = ilen;
548
549 return( 0 );
550 }
551#endif /* MBEDTLS_CIPHER_MODE_CFB */
552
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100553#if defined(MBEDTLS_CIPHER_MODE_OFB)
554 if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
555 {
556 if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
557 ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
558 {
559 return( ret );
560 }
561
562 *olen = ilen;
563
564 return( 0 );
565 }
566#endif /* MBEDTLS_CIPHER_MODE_OFB */
567
Jens Wiklander817466c2018-05-22 13:49:31 +0200568#if defined(MBEDTLS_CIPHER_MODE_CTR)
569 if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
570 {
571 if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
572 ilen, &ctx->unprocessed_len, ctx->iv,
573 ctx->unprocessed_data, input, output ) ) )
574 {
575 return( ret );
576 }
577
578 *olen = ilen;
579
580 return( 0 );
581 }
582#endif /* MBEDTLS_CIPHER_MODE_CTR */
583
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100584#if defined(MBEDTLS_CIPHER_MODE_XTS)
585 if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
586 {
587 if( ctx->unprocessed_len > 0 ) {
588 /* We can only process an entire data unit at a time. */
589 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
590 }
591
592 ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
593 ctx->operation, ilen, ctx->iv, input, output );
594 if( ret != 0 )
595 {
596 return( ret );
597 }
598
599 *olen = ilen;
600
601 return( 0 );
602 }
603#endif /* MBEDTLS_CIPHER_MODE_XTS */
604
Jens Wiklander817466c2018-05-22 13:49:31 +0200605#if defined(MBEDTLS_CIPHER_MODE_STREAM)
606 if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
607 {
608 if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
609 ilen, input, output ) ) )
610 {
611 return( ret );
612 }
613
614 *olen = ilen;
615
616 return( 0 );
617 }
618#endif /* MBEDTLS_CIPHER_MODE_STREAM */
619
620 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
621}
622
623#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
624#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
625/*
626 * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
627 */
628static void add_pkcs_padding( unsigned char *output, size_t output_len,
629 size_t data_len )
630{
631 size_t padding_len = output_len - data_len;
632 unsigned char i;
633
634 for( i = 0; i < padding_len; i++ )
635 output[data_len + i] = (unsigned char) padding_len;
636}
637
638static int get_pkcs_padding( unsigned char *input, size_t input_len,
639 size_t *data_len )
640{
641 size_t i, pad_idx;
642 unsigned char padding_len, bad = 0;
643
644 if( NULL == input || NULL == data_len )
645 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
646
647 padding_len = input[input_len - 1];
648 *data_len = input_len - padding_len;
649
650 /* Avoid logical || since it results in a branch */
651 bad |= padding_len > input_len;
652 bad |= padding_len == 0;
653
654 /* The number of bytes checked must be independent of padding_len,
655 * so pick input_len, which is usually 8 or 16 (one block) */
656 pad_idx = input_len - padding_len;
657 for( i = 0; i < input_len; i++ )
658 bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
659
660 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
661}
662#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
663
664#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
665/*
666 * One and zeros padding: fill with 80 00 ... 00
667 */
668static void add_one_and_zeros_padding( unsigned char *output,
669 size_t output_len, size_t data_len )
670{
671 size_t padding_len = output_len - data_len;
672 unsigned char i = 0;
673
674 output[data_len] = 0x80;
675 for( i = 1; i < padding_len; i++ )
676 output[data_len + i] = 0x00;
677}
678
679static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
680 size_t *data_len )
681{
682 size_t i;
683 unsigned char done = 0, prev_done, bad;
684
685 if( NULL == input || NULL == data_len )
686 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
687
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100688 bad = 0x80;
Jens Wiklander817466c2018-05-22 13:49:31 +0200689 *data_len = 0;
690 for( i = input_len; i > 0; i-- )
691 {
692 prev_done = done;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100693 done |= ( input[i - 1] != 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200694 *data_len |= ( i - 1 ) * ( done != prev_done );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100695 bad ^= input[i - 1] * ( done != prev_done );
Jens Wiklander817466c2018-05-22 13:49:31 +0200696 }
697
698 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
699
700}
701#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
702
703#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
704/*
705 * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
706 */
707static void add_zeros_and_len_padding( unsigned char *output,
708 size_t output_len, size_t data_len )
709{
710 size_t padding_len = output_len - data_len;
711 unsigned char i = 0;
712
713 for( i = 1; i < padding_len; i++ )
714 output[data_len + i - 1] = 0x00;
715 output[output_len - 1] = (unsigned char) padding_len;
716}
717
718static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
719 size_t *data_len )
720{
721 size_t i, pad_idx;
722 unsigned char padding_len, bad = 0;
723
724 if( NULL == input || NULL == data_len )
725 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
726
727 padding_len = input[input_len - 1];
728 *data_len = input_len - padding_len;
729
730 /* Avoid logical || since it results in a branch */
731 bad |= padding_len > input_len;
732 bad |= padding_len == 0;
733
734 /* The number of bytes checked must be independent of padding_len */
735 pad_idx = input_len - padding_len;
736 for( i = 0; i < input_len - 1; i++ )
737 bad |= input[i] * ( i >= pad_idx );
738
739 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
740}
741#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
742
743#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
744/*
745 * Zero padding: fill with 00 ... 00
746 */
747static void add_zeros_padding( unsigned char *output,
748 size_t output_len, size_t data_len )
749{
750 size_t i;
751
752 for( i = data_len; i < output_len; i++ )
753 output[i] = 0x00;
754}
755
756static int get_zeros_padding( unsigned char *input, size_t input_len,
757 size_t *data_len )
758{
759 size_t i;
760 unsigned char done = 0, prev_done;
761
762 if( NULL == input || NULL == data_len )
763 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
764
765 *data_len = 0;
766 for( i = input_len; i > 0; i-- )
767 {
768 prev_done = done;
769 done |= ( input[i-1] != 0 );
770 *data_len |= i * ( done != prev_done );
771 }
772
773 return( 0 );
774}
775#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
776
777/*
778 * No padding: don't pad :)
779 *
780 * There is no add_padding function (check for NULL in mbedtls_cipher_finish)
781 * but a trivial get_padding function
782 */
783static int get_no_padding( unsigned char *input, size_t input_len,
784 size_t *data_len )
785{
786 if( NULL == input || NULL == data_len )
787 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
788
789 *data_len = input_len;
790
791 return( 0 );
792}
793#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
794
795int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
796 unsigned char *output, size_t *olen )
797{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100798 CIPHER_VALIDATE_RET( ctx != NULL );
799 CIPHER_VALIDATE_RET( output != NULL );
800 CIPHER_VALIDATE_RET( olen != NULL );
801 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200802 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
803
804 *olen = 0;
805
806 if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100807 MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200808 MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
809 MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100810 MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200811 MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
812 {
813 return( 0 );
814 }
815
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100816 if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) ||
817 ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
818 {
819 return( 0 );
820 }
821
Jens Wiklander817466c2018-05-22 13:49:31 +0200822 if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
823 {
824 if( ctx->unprocessed_len != 0 )
825 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
826
827 return( 0 );
828 }
829
830#if defined(MBEDTLS_CIPHER_MODE_CBC)
831 if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
832 {
833 int ret = 0;
834
835 if( MBEDTLS_ENCRYPT == ctx->operation )
836 {
837 /* check for 'no padding' mode */
838 if( NULL == ctx->add_padding )
839 {
840 if( 0 != ctx->unprocessed_len )
841 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
842
843 return( 0 );
844 }
845
846 ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ),
847 ctx->unprocessed_len );
848 }
849 else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
850 {
851 /*
852 * For decrypt operations, expect a full block,
853 * or an empty block if no padding
854 */
855 if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
856 return( 0 );
857
858 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
859 }
860
861 /* cipher block */
862 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
863 ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv,
864 ctx->unprocessed_data, output ) ) )
865 {
866 return( ret );
867 }
868
869 /* Set output size for decryption */
870 if( MBEDTLS_DECRYPT == ctx->operation )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100871 return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
872 olen ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200873
874 /* Set output size for encryption */
875 *olen = mbedtls_cipher_get_block_size( ctx );
876 return( 0 );
877 }
878#else
879 ((void) output);
880#endif /* MBEDTLS_CIPHER_MODE_CBC */
881
882 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
883}
884
885#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100886int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
887 mbedtls_cipher_padding_t mode )
Jens Wiklander817466c2018-05-22 13:49:31 +0200888{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100889 CIPHER_VALIDATE_RET( ctx != NULL );
890
891 if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
Jens Wiklander817466c2018-05-22 13:49:31 +0200892 {
893 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
894 }
895
896 switch( mode )
897 {
898#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
899 case MBEDTLS_PADDING_PKCS7:
900 ctx->add_padding = add_pkcs_padding;
901 ctx->get_padding = get_pkcs_padding;
902 break;
903#endif
904#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
905 case MBEDTLS_PADDING_ONE_AND_ZEROS:
906 ctx->add_padding = add_one_and_zeros_padding;
907 ctx->get_padding = get_one_and_zeros_padding;
908 break;
909#endif
910#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
911 case MBEDTLS_PADDING_ZEROS_AND_LEN:
912 ctx->add_padding = add_zeros_and_len_padding;
913 ctx->get_padding = get_zeros_and_len_padding;
914 break;
915#endif
916#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
917 case MBEDTLS_PADDING_ZEROS:
918 ctx->add_padding = add_zeros_padding;
919 ctx->get_padding = get_zeros_padding;
920 break;
921#endif
922 case MBEDTLS_PADDING_NONE:
923 ctx->add_padding = NULL;
924 ctx->get_padding = get_no_padding;
925 break;
926
927 default:
928 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
929 }
930
931 return( 0 );
932}
933#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
934
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100935#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200936int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
937 unsigned char *tag, size_t tag_len )
938{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100939 CIPHER_VALIDATE_RET( ctx != NULL );
940 CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
941 if( ctx->cipher_info == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200942 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
943
944 if( MBEDTLS_ENCRYPT != ctx->operation )
945 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
946
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100947#if defined(MBEDTLS_GCM_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200948 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100949 return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
950 tag, tag_len ) );
951#endif
952
953#if defined(MBEDTLS_CHACHAPOLY_C)
954 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
955 {
956 /* Don't allow truncated MAC for Poly1305 */
957 if ( tag_len != 16U )
958 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
959
960 return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
961 tag ) );
962 }
963#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200964
965 return( 0 );
966}
967
968int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
969 const unsigned char *tag, size_t tag_len )
970{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100971 unsigned char check_tag[16];
Jens Wiklander817466c2018-05-22 13:49:31 +0200972 int ret;
973
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100974 CIPHER_VALIDATE_RET( ctx != NULL );
975 CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
976 if( ctx->cipher_info == NULL )
977 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
978
979 if( MBEDTLS_DECRYPT != ctx->operation )
Jens Wiklander817466c2018-05-22 13:49:31 +0200980 {
981 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
982 }
983
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100984#if defined(MBEDTLS_GCM_C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200985 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
986 {
Jens Wiklander817466c2018-05-22 13:49:31 +0200987 if( tag_len > sizeof( check_tag ) )
988 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
989
990 if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
991 check_tag, tag_len ) ) )
992 {
993 return( ret );
994 }
995
996 /* Check the tag in "constant-time" */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100997 if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200998 return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
999
1000 return( 0 );
1001 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001002#endif /* MBEDTLS_GCM_C */
1003
1004#if defined(MBEDTLS_CHACHAPOLY_C)
1005 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
1006 {
1007 /* Don't allow truncated MAC for Poly1305 */
1008 if ( tag_len != sizeof( check_tag ) )
1009 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1010
1011 ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
1012 check_tag );
1013 if ( ret != 0 )
1014 {
1015 return( ret );
1016 }
1017
1018 /* Check the tag in "constant-time" */
1019 if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
1020 return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
1021
1022 return( 0 );
1023 }
1024#endif /* MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +02001025
1026 return( 0 );
1027}
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001028#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +02001029
1030/*
1031 * Packet-oriented wrapper for non-AEAD modes
1032 */
1033int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
1034 const unsigned char *iv, size_t iv_len,
1035 const unsigned char *input, size_t ilen,
1036 unsigned char *output, size_t *olen )
1037{
1038 int ret;
1039 size_t finish_olen;
1040
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001041 CIPHER_VALIDATE_RET( ctx != NULL );
1042 CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
1043 CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
1044 CIPHER_VALIDATE_RET( output != NULL );
1045 CIPHER_VALIDATE_RET( olen != NULL );
1046
Jens Wiklander817466c2018-05-22 13:49:31 +02001047 if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
1048 return( ret );
1049
1050 if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
1051 return( ret );
1052
1053 if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
1054 return( ret );
1055
1056 if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
1057 return( ret );
1058
1059 *olen += finish_olen;
1060
1061 return( 0 );
1062}
1063
1064#if defined(MBEDTLS_CIPHER_MODE_AEAD)
1065/*
1066 * Packet-oriented encryption for AEAD modes
1067 */
1068int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
1069 const unsigned char *iv, size_t iv_len,
1070 const unsigned char *ad, size_t ad_len,
1071 const unsigned char *input, size_t ilen,
1072 unsigned char *output, size_t *olen,
1073 unsigned char *tag, size_t tag_len )
1074{
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001075 CIPHER_VALIDATE_RET( ctx != NULL );
1076 CIPHER_VALIDATE_RET( iv != NULL );
1077 CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
1078 CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
1079 CIPHER_VALIDATE_RET( output != NULL );
1080 CIPHER_VALIDATE_RET( olen != NULL );
1081 CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
1082
Jens Wiklander817466c2018-05-22 13:49:31 +02001083#if defined(MBEDTLS_GCM_C)
1084 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
1085 {
1086 *olen = ilen;
1087 return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen,
1088 iv, iv_len, ad, ad_len, input, output,
1089 tag_len, tag ) );
1090 }
1091#endif /* MBEDTLS_GCM_C */
1092#if defined(MBEDTLS_CCM_C)
1093 if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
1094 {
1095 *olen = ilen;
1096 return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
1097 iv, iv_len, ad, ad_len, input, output,
1098 tag, tag_len ) );
1099 }
1100#endif /* MBEDTLS_CCM_C */
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001101#if defined(MBEDTLS_CHACHAPOLY_C)
1102 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
1103 {
1104 /* ChachaPoly has fixed length nonce and MAC (tag) */
1105 if ( ( iv_len != ctx->cipher_info->iv_size ) ||
1106 ( tag_len != 16U ) )
1107 {
1108 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1109 }
1110
1111 *olen = ilen;
1112 return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx,
1113 ilen, iv, ad, ad_len, input, output, tag ) );
1114 }
1115#endif /* MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +02001116
1117 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1118}
1119
1120/*
1121 * Packet-oriented decryption for AEAD modes
1122 */
1123int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
1124 const unsigned char *iv, size_t iv_len,
1125 const unsigned char *ad, size_t ad_len,
1126 const unsigned char *input, size_t ilen,
1127 unsigned char *output, size_t *olen,
1128 const unsigned char *tag, size_t tag_len )
1129{
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001130 CIPHER_VALIDATE_RET( ctx != NULL );
1131 CIPHER_VALIDATE_RET( iv != NULL );
1132 CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
1133 CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
1134 CIPHER_VALIDATE_RET( output != NULL );
1135 CIPHER_VALIDATE_RET( olen != NULL );
1136 CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
1137
Jens Wiklander817466c2018-05-22 13:49:31 +02001138#if defined(MBEDTLS_GCM_C)
1139 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
1140 {
1141 int ret;
1142
1143 *olen = ilen;
1144 ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
1145 iv, iv_len, ad, ad_len,
1146 tag, tag_len, input, output );
1147
1148 if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED )
1149 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1150
1151 return( ret );
1152 }
1153#endif /* MBEDTLS_GCM_C */
1154#if defined(MBEDTLS_CCM_C)
1155 if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
1156 {
1157 int ret;
1158
1159 *olen = ilen;
1160 ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
1161 iv, iv_len, ad, ad_len,
1162 input, output, tag, tag_len );
1163
1164 if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
1165 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1166
1167 return( ret );
1168 }
1169#endif /* MBEDTLS_CCM_C */
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001170#if defined(MBEDTLS_CHACHAPOLY_C)
1171 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
1172 {
1173 int ret;
1174
1175 /* ChachaPoly has fixed length nonce and MAC (tag) */
1176 if ( ( iv_len != ctx->cipher_info->iv_size ) ||
1177 ( tag_len != 16U ) )
1178 {
1179 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1180 }
1181
1182 *olen = ilen;
1183 ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen,
1184 iv, ad, ad_len, tag, input, output );
1185
1186 if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED )
1187 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
1188
1189 return( ret );
1190 }
1191#endif /* MBEDTLS_CHACHAPOLY_C */
Jens Wiklander817466c2018-05-22 13:49:31 +02001192
1193 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
1194}
1195#endif /* MBEDTLS_CIPHER_MODE_AEAD */
1196
1197#endif /* MBEDTLS_CIPHER_C */