]>
Commit | Line | Data |
---|---|---|
1 | /** | |
2 | * \file cipher.c | |
3 | * | |
4 | * \brief Generic cipher wrapper for mbed TLS | |
5 | * | |
6 | * \author Adriaan de Jong <dejong@fox-it.com> | |
7 | * | |
8 | * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved | |
9 | * SPDX-License-Identifier: GPL-2.0 | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License as published by | |
13 | * the Free Software Foundation; either version 2 of the License, or | |
14 | * (at your option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License along | |
22 | * with this program; if not, write to the Free Software Foundation, Inc., | |
23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | * | |
25 | * This file is part of mbed TLS (https://tls.mbed.org) | |
26 | */ | |
27 | ||
28 | #if !defined(MBEDTLS_CONFIG_FILE) | |
29 | #include "mbedtls/config.h" | |
30 | #else | |
31 | #include MBEDTLS_CONFIG_FILE | |
32 | #endif | |
33 | ||
34 | #if defined(MBEDTLS_CIPHER_C) | |
35 | ||
36 | #include "mbedtls/cipher.h" | |
37 | #include "mbedtls/cipher_internal.h" | |
38 | #include "mbedtls/platform_util.h" | |
39 | ||
40 | #include <stdlib.h> | |
41 | #include <string.h> | |
42 | ||
43 | #if defined(MBEDTLS_CHACHAPOLY_C) | |
44 | #include "mbedtls/chachapoly.h" | |
45 | #endif | |
46 | ||
47 | #if defined(MBEDTLS_GCM_C) | |
48 | #include "mbedtls/gcm.h" | |
49 | #endif | |
50 | ||
51 | #if defined(MBEDTLS_CCM_C) | |
52 | #include "mbedtls/ccm.h" | |
53 | #endif | |
54 | ||
55 | #if defined(MBEDTLS_CHACHA20_C) | |
56 | #include "mbedtls/chacha20.h" | |
57 | #endif | |
58 | ||
59 | #if defined(MBEDTLS_CMAC_C) | |
60 | #include "mbedtls/cmac.h" | |
61 | #endif | |
62 | ||
63 | #if defined(MBEDTLS_PLATFORM_C) | |
64 | #include "mbedtls/platform.h" | |
65 | #else | |
66 | #define mbedtls_calloc calloc | |
67 | #define mbedtls_free free | |
68 | #endif | |
69 | ||
70 | #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) | |
71 | /* Compare the contents of two buffers in constant time. | |
72 | * Returns 0 if the contents are bitwise identical, otherwise returns | |
73 | * a non-zero value. | |
74 | * This is currently only used by GCM and ChaCha20+Poly1305. | |
75 | */ | |
76 | static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len ) | |
77 | { | |
78 | const unsigned char *p1 = (const unsigned char*) v1; | |
79 | const unsigned char *p2 = (const unsigned char*) v2; | |
80 | size_t i; | |
81 | unsigned char diff; | |
82 | ||
83 | for( diff = 0, i = 0; i < len; i++ ) | |
84 | diff |= p1[i] ^ p2[i]; | |
85 | ||
86 | return (int)diff; | |
87 | } | |
88 | #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ | |
89 | ||
90 | static int supported_init = 0; | |
91 | ||
92 | const int *mbedtls_cipher_list( void ) | |
93 | { | |
94 | const mbedtls_cipher_definition_t *def; | |
95 | int *type; | |
96 | ||
97 | if( ! supported_init ) | |
98 | { | |
99 | def = mbedtls_cipher_definitions; | |
100 | type = mbedtls_cipher_supported; | |
101 | ||
102 | while( def->type != 0 ) | |
103 | *type++ = (*def++).type; | |
104 | ||
105 | *type = 0; | |
106 | ||
107 | supported_init = 1; | |
108 | } | |
109 | ||
110 | return( mbedtls_cipher_supported ); | |
111 | } | |
112 | ||
113 | const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) | |
114 | { | |
115 | const mbedtls_cipher_definition_t *def; | |
116 | ||
117 | for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) | |
118 | if( def->type == cipher_type ) | |
119 | return( def->info ); | |
120 | ||
121 | return( NULL ); | |
122 | } | |
123 | ||
124 | const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) | |
125 | { | |
126 | const mbedtls_cipher_definition_t *def; | |
127 | ||
128 | if( NULL == cipher_name ) | |
129 | return( NULL ); | |
130 | ||
131 | for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) | |
132 | if( ! strcmp( def->info->name, cipher_name ) ) | |
133 | return( def->info ); | |
134 | ||
135 | return( NULL ); | |
136 | } | |
137 | ||
138 | const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, | |
139 | int key_bitlen, | |
140 | const mbedtls_cipher_mode_t mode ) | |
141 | { | |
142 | const mbedtls_cipher_definition_t *def; | |
143 | ||
144 | for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) | |
145 | if( def->info->base->cipher == cipher_id && | |
146 | def->info->key_bitlen == (unsigned) key_bitlen && | |
147 | def->info->mode == mode ) | |
148 | return( def->info ); | |
149 | ||
150 | return( NULL ); | |
151 | } | |
152 | ||
153 | void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) | |
154 | { | |
155 | memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); | |
156 | } | |
157 | ||
158 | void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) | |
159 | { | |
160 | if( ctx == NULL ) | |
161 | return; | |
162 | ||
163 | #if defined(MBEDTLS_CMAC_C) | |
164 | if( ctx->cmac_ctx ) | |
165 | { | |
166 | mbedtls_platform_zeroize( ctx->cmac_ctx, | |
167 | sizeof( mbedtls_cmac_context_t ) ); | |
168 | mbedtls_free( ctx->cmac_ctx ); | |
169 | } | |
170 | #endif | |
171 | ||
172 | if( ctx->cipher_ctx ) | |
173 | ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); | |
174 | ||
175 | mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); | |
176 | } | |
177 | ||
178 | int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) | |
179 | { | |
180 | if( NULL == cipher_info || NULL == ctx ) | |
181 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
182 | ||
183 | memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); | |
184 | ||
185 | if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) | |
186 | return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); | |
187 | ||
188 | ctx->cipher_info = cipher_info; | |
189 | ||
190 | #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) | |
191 | /* | |
192 | * Ignore possible errors caused by a cipher mode that doesn't use padding | |
193 | */ | |
194 | #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) | |
195 | (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); | |
196 | #else | |
197 | (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); | |
198 | #endif | |
199 | #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ | |
200 | ||
201 | return( 0 ); | |
202 | } | |
203 | ||
204 | int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, | |
205 | int key_bitlen, const mbedtls_operation_t operation ) | |
206 | { | |
207 | if( NULL == ctx || NULL == ctx->cipher_info ) | |
208 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
209 | ||
210 | if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && | |
211 | (int) ctx->cipher_info->key_bitlen != key_bitlen ) | |
212 | { | |
213 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
214 | } | |
215 | ||
216 | ctx->key_bitlen = key_bitlen; | |
217 | ctx->operation = operation; | |
218 | ||
219 | /* | |
220 | * For OFB, CFB and CTR mode always use the encryption key schedule | |
221 | */ | |
222 | if( MBEDTLS_ENCRYPT == operation || | |
223 | MBEDTLS_MODE_CFB == ctx->cipher_info->mode || | |
224 | MBEDTLS_MODE_OFB == ctx->cipher_info->mode || | |
225 | MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) | |
226 | { | |
227 | return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, | |
228 | ctx->key_bitlen ); | |
229 | } | |
230 | ||
231 | if( MBEDTLS_DECRYPT == operation ) | |
232 | return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, | |
233 | ctx->key_bitlen ); | |
234 | ||
235 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
236 | } | |
237 | ||
238 | int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, | |
239 | const unsigned char *iv, size_t iv_len ) | |
240 | { | |
241 | size_t actual_iv_size; | |
242 | ||
243 | if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) | |
244 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
245 | ||
246 | /* avoid buffer overflow in ctx->iv */ | |
247 | if( iv_len > MBEDTLS_MAX_IV_LENGTH ) | |
248 | return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); | |
249 | ||
250 | if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) | |
251 | actual_iv_size = iv_len; | |
252 | else | |
253 | { | |
254 | actual_iv_size = ctx->cipher_info->iv_size; | |
255 | ||
256 | /* avoid reading past the end of input buffer */ | |
257 | if( actual_iv_size > iv_len ) | |
258 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
259 | } | |
260 | ||
261 | #if defined(MBEDTLS_CHACHA20_C) | |
262 | if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) | |
263 | { | |
264 | if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, | |
265 | iv, | |
266 | 0U ) ) /* Initial counter value */ | |
267 | { | |
268 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
269 | } | |
270 | } | |
271 | #endif | |
272 | ||
273 | memcpy( ctx->iv, iv, actual_iv_size ); | |
274 | ctx->iv_size = actual_iv_size; | |
275 | ||
276 | return( 0 ); | |
277 | } | |
278 | ||
279 | int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) | |
280 | { | |
281 | if( NULL == ctx || NULL == ctx->cipher_info ) | |
282 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
283 | ||
284 | ctx->unprocessed_len = 0; | |
285 | ||
286 | return( 0 ); | |
287 | } | |
288 | ||
289 | #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) | |
290 | int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, | |
291 | const unsigned char *ad, size_t ad_len ) | |
292 | { | |
293 | if( NULL == ctx || NULL == ctx->cipher_info ) | |
294 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
295 | ||
296 | #if defined(MBEDTLS_GCM_C) | |
297 | if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) | |
298 | { | |
299 | return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, | |
300 | ctx->iv, ctx->iv_size, ad, ad_len ); | |
301 | } | |
302 | #endif | |
303 | ||
304 | #if defined(MBEDTLS_CHACHAPOLY_C) | |
305 | if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) | |
306 | { | |
307 | int result; | |
308 | mbedtls_chachapoly_mode_t mode; | |
309 | ||
310 | mode = ( ctx->operation == MBEDTLS_ENCRYPT ) | |
311 | ? MBEDTLS_CHACHAPOLY_ENCRYPT | |
312 | : MBEDTLS_CHACHAPOLY_DECRYPT; | |
313 | ||
314 | result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, | |
315 | ctx->iv, | |
316 | mode ); | |
317 | if ( result != 0 ) | |
318 | return( result ); | |
319 | ||
320 | return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, | |
321 | ad, ad_len ); | |
322 | } | |
323 | #endif | |
324 | ||
325 | return( 0 ); | |
326 | } | |
327 | #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ | |
328 | ||
329 | int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, | |
330 | size_t ilen, unsigned char *output, size_t *olen ) | |
331 | { | |
332 | int ret; | |
333 | size_t block_size = 0; | |
334 | ||
335 | if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) | |
336 | { | |
337 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
338 | } | |
339 | ||
340 | *olen = 0; | |
341 | block_size = mbedtls_cipher_get_block_size( ctx ); | |
342 | ||
343 | if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) | |
344 | { | |
345 | if( ilen != block_size ) | |
346 | return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); | |
347 | ||
348 | *olen = ilen; | |
349 | ||
350 | if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, | |
351 | ctx->operation, input, output ) ) ) | |
352 | { | |
353 | return( ret ); | |
354 | } | |
355 | ||
356 | return( 0 ); | |
357 | } | |
358 | ||
359 | #if defined(MBEDTLS_GCM_C) | |
360 | if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) | |
361 | { | |
362 | *olen = ilen; | |
363 | return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, | |
364 | output ); | |
365 | } | |
366 | #endif | |
367 | ||
368 | #if defined(MBEDTLS_CHACHAPOLY_C) | |
369 | if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) | |
370 | { | |
371 | *olen = ilen; | |
372 | return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, | |
373 | ilen, input, output ); | |
374 | } | |
375 | #endif | |
376 | ||
377 | if ( 0 == block_size ) | |
378 | { | |
379 | return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; | |
380 | } | |
381 | ||
382 | if( input == output && | |
383 | ( ctx->unprocessed_len != 0 || ilen % block_size ) ) | |
384 | { | |
385 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
386 | } | |
387 | ||
388 | #if defined(MBEDTLS_CIPHER_MODE_CBC) | |
389 | if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) | |
390 | { | |
391 | size_t copy_len = 0; | |
392 | ||
393 | /* | |
394 | * If there is not enough data for a full block, cache it. | |
395 | */ | |
396 | if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && | |
397 | ilen <= block_size - ctx->unprocessed_len ) || | |
398 | ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && | |
399 | ilen < block_size - ctx->unprocessed_len ) || | |
400 | ( ctx->operation == MBEDTLS_ENCRYPT && | |
401 | ilen < block_size - ctx->unprocessed_len ) ) | |
402 | { | |
403 | memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, | |
404 | ilen ); | |
405 | ||
406 | ctx->unprocessed_len += ilen; | |
407 | return( 0 ); | |
408 | } | |
409 | ||
410 | /* | |
411 | * Process cached data first | |
412 | */ | |
413 | if( 0 != ctx->unprocessed_len ) | |
414 | { | |
415 | copy_len = block_size - ctx->unprocessed_len; | |
416 | ||
417 | memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, | |
418 | copy_len ); | |
419 | ||
420 | if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, | |
421 | ctx->operation, block_size, ctx->iv, | |
422 | ctx->unprocessed_data, output ) ) ) | |
423 | { | |
424 | return( ret ); | |
425 | } | |
426 | ||
427 | *olen += block_size; | |
428 | output += block_size; | |
429 | ctx->unprocessed_len = 0; | |
430 | ||
431 | input += copy_len; | |
432 | ilen -= copy_len; | |
433 | } | |
434 | ||
435 | /* | |
436 | * Cache final, incomplete block | |
437 | */ | |
438 | if( 0 != ilen ) | |
439 | { | |
440 | if( 0 == block_size ) | |
441 | { | |
442 | return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; | |
443 | } | |
444 | ||
445 | /* Encryption: only cache partial blocks | |
446 | * Decryption w/ padding: always keep at least one whole block | |
447 | * Decryption w/o padding: only cache partial blocks | |
448 | */ | |
449 | copy_len = ilen % block_size; | |
450 | if( copy_len == 0 && | |
451 | ctx->operation == MBEDTLS_DECRYPT && | |
452 | NULL != ctx->add_padding) | |
453 | { | |
454 | copy_len = block_size; | |
455 | } | |
456 | ||
457 | memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), | |
458 | copy_len ); | |
459 | ||
460 | ctx->unprocessed_len += copy_len; | |
461 | ilen -= copy_len; | |
462 | } | |
463 | ||
464 | /* | |
465 | * Process remaining full blocks | |
466 | */ | |
467 | if( ilen ) | |
468 | { | |
469 | if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, | |
470 | ctx->operation, ilen, ctx->iv, input, output ) ) ) | |
471 | { | |
472 | return( ret ); | |
473 | } | |
474 | ||
475 | *olen += ilen; | |
476 | } | |
477 | ||
478 | return( 0 ); | |
479 | } | |
480 | #endif /* MBEDTLS_CIPHER_MODE_CBC */ | |
481 | ||
482 | #if defined(MBEDTLS_CIPHER_MODE_CFB) | |
483 | if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) | |
484 | { | |
485 | if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, | |
486 | ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, | |
487 | input, output ) ) ) | |
488 | { | |
489 | return( ret ); | |
490 | } | |
491 | ||
492 | *olen = ilen; | |
493 | ||
494 | return( 0 ); | |
495 | } | |
496 | #endif /* MBEDTLS_CIPHER_MODE_CFB */ | |
497 | ||
498 | #if defined(MBEDTLS_CIPHER_MODE_OFB) | |
499 | if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) | |
500 | { | |
501 | if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, | |
502 | ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) | |
503 | { | |
504 | return( ret ); | |
505 | } | |
506 | ||
507 | *olen = ilen; | |
508 | ||
509 | return( 0 ); | |
510 | } | |
511 | #endif /* MBEDTLS_CIPHER_MODE_OFB */ | |
512 | ||
513 | #if defined(MBEDTLS_CIPHER_MODE_CTR) | |
514 | if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) | |
515 | { | |
516 | if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, | |
517 | ilen, &ctx->unprocessed_len, ctx->iv, | |
518 | ctx->unprocessed_data, input, output ) ) ) | |
519 | { | |
520 | return( ret ); | |
521 | } | |
522 | ||
523 | *olen = ilen; | |
524 | ||
525 | return( 0 ); | |
526 | } | |
527 | #endif /* MBEDTLS_CIPHER_MODE_CTR */ | |
528 | ||
529 | #if defined(MBEDTLS_CIPHER_MODE_XTS) | |
530 | if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) | |
531 | { | |
532 | if( ctx->unprocessed_len > 0 ) { | |
533 | /* We can only process an entire data unit at a time. */ | |
534 | return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); | |
535 | } | |
536 | ||
537 | ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, | |
538 | ctx->operation, ilen, ctx->iv, input, output ); | |
539 | if( ret != 0 ) | |
540 | { | |
541 | return( ret ); | |
542 | } | |
543 | ||
544 | *olen = ilen; | |
545 | ||
546 | return( 0 ); | |
547 | } | |
548 | #endif /* MBEDTLS_CIPHER_MODE_XTS */ | |
549 | ||
550 | #if defined(MBEDTLS_CIPHER_MODE_STREAM) | |
551 | if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) | |
552 | { | |
553 | if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, | |
554 | ilen, input, output ) ) ) | |
555 | { | |
556 | return( ret ); | |
557 | } | |
558 | ||
559 | *olen = ilen; | |
560 | ||
561 | return( 0 ); | |
562 | } | |
563 | #endif /* MBEDTLS_CIPHER_MODE_STREAM */ | |
564 | ||
565 | return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); | |
566 | } | |
567 | ||
568 | #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) | |
569 | #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) | |
570 | /* | |
571 | * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len | |
572 | */ | |
573 | static void add_pkcs_padding( unsigned char *output, size_t output_len, | |
574 | size_t data_len ) | |
575 | { | |
576 | size_t padding_len = output_len - data_len; | |
577 | unsigned char i; | |
578 | ||
579 | for( i = 0; i < padding_len; i++ ) | |
580 | output[data_len + i] = (unsigned char) padding_len; | |
581 | } | |
582 | ||
583 | static int get_pkcs_padding( unsigned char *input, size_t input_len, | |
584 | size_t *data_len ) | |
585 | { | |
586 | size_t i, pad_idx; | |
587 | unsigned char padding_len, bad = 0; | |
588 | ||
589 | if( NULL == input || NULL == data_len ) | |
590 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
591 | ||
592 | padding_len = input[input_len - 1]; | |
593 | *data_len = input_len - padding_len; | |
594 | ||
595 | /* Avoid logical || since it results in a branch */ | |
596 | bad |= padding_len > input_len; | |
597 | bad |= padding_len == 0; | |
598 | ||
599 | /* The number of bytes checked must be independent of padding_len, | |
600 | * so pick input_len, which is usually 8 or 16 (one block) */ | |
601 | pad_idx = input_len - padding_len; | |
602 | for( i = 0; i < input_len; i++ ) | |
603 | bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); | |
604 | ||
605 | return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); | |
606 | } | |
607 | #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ | |
608 | ||
609 | #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) | |
610 | /* | |
611 | * One and zeros padding: fill with 80 00 ... 00 | |
612 | */ | |
613 | static void add_one_and_zeros_padding( unsigned char *output, | |
614 | size_t output_len, size_t data_len ) | |
615 | { | |
616 | size_t padding_len = output_len - data_len; | |
617 | unsigned char i = 0; | |
618 | ||
619 | output[data_len] = 0x80; | |
620 | for( i = 1; i < padding_len; i++ ) | |
621 | output[data_len + i] = 0x00; | |
622 | } | |
623 | ||
624 | static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, | |
625 | size_t *data_len ) | |
626 | { | |
627 | size_t i; | |
628 | unsigned char done = 0, prev_done, bad; | |
629 | ||
630 | if( NULL == input || NULL == data_len ) | |
631 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
632 | ||
633 | bad = 0x80; | |
634 | *data_len = 0; | |
635 | for( i = input_len; i > 0; i-- ) | |
636 | { | |
637 | prev_done = done; | |
638 | done |= ( input[i - 1] != 0 ); | |
639 | *data_len |= ( i - 1 ) * ( done != prev_done ); | |
640 | bad ^= input[i - 1] * ( done != prev_done ); | |
641 | } | |
642 | ||
643 | return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); | |
644 | ||
645 | } | |
646 | #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ | |
647 | ||
648 | #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) | |
649 | /* | |
650 | * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length | |
651 | */ | |
652 | static void add_zeros_and_len_padding( unsigned char *output, | |
653 | size_t output_len, size_t data_len ) | |
654 | { | |
655 | size_t padding_len = output_len - data_len; | |
656 | unsigned char i = 0; | |
657 | ||
658 | for( i = 1; i < padding_len; i++ ) | |
659 | output[data_len + i - 1] = 0x00; | |
660 | output[output_len - 1] = (unsigned char) padding_len; | |
661 | } | |
662 | ||
663 | static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, | |
664 | size_t *data_len ) | |
665 | { | |
666 | size_t i, pad_idx; | |
667 | unsigned char padding_len, bad = 0; | |
668 | ||
669 | if( NULL == input || NULL == data_len ) | |
670 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
671 | ||
672 | padding_len = input[input_len - 1]; | |
673 | *data_len = input_len - padding_len; | |
674 | ||
675 | /* Avoid logical || since it results in a branch */ | |
676 | bad |= padding_len > input_len; | |
677 | bad |= padding_len == 0; | |
678 | ||
679 | /* The number of bytes checked must be independent of padding_len */ | |
680 | pad_idx = input_len - padding_len; | |
681 | for( i = 0; i < input_len - 1; i++ ) | |
682 | bad |= input[i] * ( i >= pad_idx ); | |
683 | ||
684 | return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); | |
685 | } | |
686 | #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ | |
687 | ||
688 | #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) | |
689 | /* | |
690 | * Zero padding: fill with 00 ... 00 | |
691 | */ | |
692 | static void add_zeros_padding( unsigned char *output, | |
693 | size_t output_len, size_t data_len ) | |
694 | { | |
695 | size_t i; | |
696 | ||
697 | for( i = data_len; i < output_len; i++ ) | |
698 | output[i] = 0x00; | |
699 | } | |
700 | ||
701 | static int get_zeros_padding( unsigned char *input, size_t input_len, | |
702 | size_t *data_len ) | |
703 | { | |
704 | size_t i; | |
705 | unsigned char done = 0, prev_done; | |
706 | ||
707 | if( NULL == input || NULL == data_len ) | |
708 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
709 | ||
710 | *data_len = 0; | |
711 | for( i = input_len; i > 0; i-- ) | |
712 | { | |
713 | prev_done = done; | |
714 | done |= ( input[i-1] != 0 ); | |
715 | *data_len |= i * ( done != prev_done ); | |
716 | } | |
717 | ||
718 | return( 0 ); | |
719 | } | |
720 | #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ | |
721 | ||
722 | /* | |
723 | * No padding: don't pad :) | |
724 | * | |
725 | * There is no add_padding function (check for NULL in mbedtls_cipher_finish) | |
726 | * but a trivial get_padding function | |
727 | */ | |
728 | static int get_no_padding( unsigned char *input, size_t input_len, | |
729 | size_t *data_len ) | |
730 | { | |
731 | if( NULL == input || NULL == data_len ) | |
732 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
733 | ||
734 | *data_len = input_len; | |
735 | ||
736 | return( 0 ); | |
737 | } | |
738 | #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ | |
739 | ||
740 | int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, | |
741 | unsigned char *output, size_t *olen ) | |
742 | { | |
743 | if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) | |
744 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
745 | ||
746 | *olen = 0; | |
747 | ||
748 | if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || | |
749 | MBEDTLS_MODE_OFB == ctx->cipher_info->mode || | |
750 | MBEDTLS_MODE_CTR == ctx->cipher_info->mode || | |
751 | MBEDTLS_MODE_GCM == ctx->cipher_info->mode || | |
752 | MBEDTLS_MODE_XTS == ctx->cipher_info->mode || | |
753 | MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) | |
754 | { | |
755 | return( 0 ); | |
756 | } | |
757 | ||
758 | if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || | |
759 | ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) | |
760 | { | |
761 | return( 0 ); | |
762 | } | |
763 | ||
764 | if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) | |
765 | { | |
766 | if( ctx->unprocessed_len != 0 ) | |
767 | return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); | |
768 | ||
769 | return( 0 ); | |
770 | } | |
771 | ||
772 | #if defined(MBEDTLS_CIPHER_MODE_CBC) | |
773 | if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) | |
774 | { | |
775 | int ret = 0; | |
776 | ||
777 | if( MBEDTLS_ENCRYPT == ctx->operation ) | |
778 | { | |
779 | /* check for 'no padding' mode */ | |
780 | if( NULL == ctx->add_padding ) | |
781 | { | |
782 | if( 0 != ctx->unprocessed_len ) | |
783 | return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); | |
784 | ||
785 | return( 0 ); | |
786 | } | |
787 | ||
788 | ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), | |
789 | ctx->unprocessed_len ); | |
790 | } | |
791 | else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) | |
792 | { | |
793 | /* | |
794 | * For decrypt operations, expect a full block, | |
795 | * or an empty block if no padding | |
796 | */ | |
797 | if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) | |
798 | return( 0 ); | |
799 | ||
800 | return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); | |
801 | } | |
802 | ||
803 | /* cipher block */ | |
804 | if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, | |
805 | ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, | |
806 | ctx->unprocessed_data, output ) ) ) | |
807 | { | |
808 | return( ret ); | |
809 | } | |
810 | ||
811 | /* Set output size for decryption */ | |
812 | if( MBEDTLS_DECRYPT == ctx->operation ) | |
813 | return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), | |
814 | olen ); | |
815 | ||
816 | /* Set output size for encryption */ | |
817 | *olen = mbedtls_cipher_get_block_size( ctx ); | |
818 | return( 0 ); | |
819 | } | |
820 | #else | |
821 | ((void) output); | |
822 | #endif /* MBEDTLS_CIPHER_MODE_CBC */ | |
823 | ||
824 | return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); | |
825 | } | |
826 | ||
827 | #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) | |
828 | int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) | |
829 | { | |
830 | if( NULL == ctx || | |
831 | MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) | |
832 | { | |
833 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
834 | } | |
835 | ||
836 | switch( mode ) | |
837 | { | |
838 | #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) | |
839 | case MBEDTLS_PADDING_PKCS7: | |
840 | ctx->add_padding = add_pkcs_padding; | |
841 | ctx->get_padding = get_pkcs_padding; | |
842 | break; | |
843 | #endif | |
844 | #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) | |
845 | case MBEDTLS_PADDING_ONE_AND_ZEROS: | |
846 | ctx->add_padding = add_one_and_zeros_padding; | |
847 | ctx->get_padding = get_one_and_zeros_padding; | |
848 | break; | |
849 | #endif | |
850 | #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) | |
851 | case MBEDTLS_PADDING_ZEROS_AND_LEN: | |
852 | ctx->add_padding = add_zeros_and_len_padding; | |
853 | ctx->get_padding = get_zeros_and_len_padding; | |
854 | break; | |
855 | #endif | |
856 | #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) | |
857 | case MBEDTLS_PADDING_ZEROS: | |
858 | ctx->add_padding = add_zeros_padding; | |
859 | ctx->get_padding = get_zeros_padding; | |
860 | break; | |
861 | #endif | |
862 | case MBEDTLS_PADDING_NONE: | |
863 | ctx->add_padding = NULL; | |
864 | ctx->get_padding = get_no_padding; | |
865 | break; | |
866 | ||
867 | default: | |
868 | return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); | |
869 | } | |
870 | ||
871 | return( 0 ); | |
872 | } | |
873 | #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ | |
874 | ||
875 | #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) | |
876 | int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, | |
877 | unsigned char *tag, size_t tag_len ) | |
878 | { | |
879 | if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) | |
880 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
881 | ||
882 | if( MBEDTLS_ENCRYPT != ctx->operation ) | |
883 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
884 | ||
885 | #if defined(MBEDTLS_GCM_C) | |
886 | if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) | |
887 | return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); | |
888 | #endif | |
889 | ||
890 | #if defined(MBEDTLS_CHACHAPOLY_C) | |
891 | if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) | |
892 | { | |
893 | /* Don't allow truncated MAC for Poly1305 */ | |
894 | if ( tag_len != 16U ) | |
895 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
896 | ||
897 | return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, | |
898 | tag ); | |
899 | } | |
900 | #endif | |
901 | ||
902 | return( 0 ); | |
903 | } | |
904 | ||
905 | int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, | |
906 | const unsigned char *tag, size_t tag_len ) | |
907 | { | |
908 | unsigned char check_tag[16]; | |
909 | int ret; | |
910 | ||
911 | if( NULL == ctx || NULL == ctx->cipher_info || | |
912 | MBEDTLS_DECRYPT != ctx->operation ) | |
913 | { | |
914 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
915 | } | |
916 | ||
917 | #if defined(MBEDTLS_GCM_C) | |
918 | if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) | |
919 | { | |
920 | if( tag_len > sizeof( check_tag ) ) | |
921 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
922 | ||
923 | if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, | |
924 | check_tag, tag_len ) ) ) | |
925 | { | |
926 | return( ret ); | |
927 | } | |
928 | ||
929 | /* Check the tag in "constant-time" */ | |
930 | if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) | |
931 | return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); | |
932 | ||
933 | return( 0 ); | |
934 | } | |
935 | #endif /* MBEDTLS_GCM_C */ | |
936 | ||
937 | #if defined(MBEDTLS_CHACHAPOLY_C) | |
938 | if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) | |
939 | { | |
940 | /* Don't allow truncated MAC for Poly1305 */ | |
941 | if ( tag_len != sizeof( check_tag ) ) | |
942 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
943 | ||
944 | ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, | |
945 | check_tag ); | |
946 | if ( ret != 0 ) | |
947 | { | |
948 | return( ret ); | |
949 | } | |
950 | ||
951 | /* Check the tag in "constant-time" */ | |
952 | if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) | |
953 | return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); | |
954 | ||
955 | return( 0 ); | |
956 | } | |
957 | #endif /* MBEDTLS_CHACHAPOLY_C */ | |
958 | ||
959 | return( 0 ); | |
960 | } | |
961 | #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ | |
962 | ||
963 | /* | |
964 | * Packet-oriented wrapper for non-AEAD modes | |
965 | */ | |
966 | int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, | |
967 | const unsigned char *iv, size_t iv_len, | |
968 | const unsigned char *input, size_t ilen, | |
969 | unsigned char *output, size_t *olen ) | |
970 | { | |
971 | int ret; | |
972 | size_t finish_olen; | |
973 | ||
974 | if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) | |
975 | return( ret ); | |
976 | ||
977 | if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) | |
978 | return( ret ); | |
979 | ||
980 | if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) | |
981 | return( ret ); | |
982 | ||
983 | if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) | |
984 | return( ret ); | |
985 | ||
986 | *olen += finish_olen; | |
987 | ||
988 | return( 0 ); | |
989 | } | |
990 | ||
991 | #if defined(MBEDTLS_CIPHER_MODE_AEAD) | |
992 | /* | |
993 | * Packet-oriented encryption for AEAD modes | |
994 | */ | |
995 | int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, | |
996 | const unsigned char *iv, size_t iv_len, | |
997 | const unsigned char *ad, size_t ad_len, | |
998 | const unsigned char *input, size_t ilen, | |
999 | unsigned char *output, size_t *olen, | |
1000 | unsigned char *tag, size_t tag_len ) | |
1001 | { | |
1002 | #if defined(MBEDTLS_GCM_C) | |
1003 | if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) | |
1004 | { | |
1005 | *olen = ilen; | |
1006 | return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, | |
1007 | iv, iv_len, ad, ad_len, input, output, | |
1008 | tag_len, tag ) ); | |
1009 | } | |
1010 | #endif /* MBEDTLS_GCM_C */ | |
1011 | #if defined(MBEDTLS_CCM_C) | |
1012 | if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) | |
1013 | { | |
1014 | *olen = ilen; | |
1015 | return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, | |
1016 | iv, iv_len, ad, ad_len, input, output, | |
1017 | tag, tag_len ) ); | |
1018 | } | |
1019 | #endif /* MBEDTLS_CCM_C */ | |
1020 | #if defined(MBEDTLS_CHACHAPOLY_C) | |
1021 | if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) | |
1022 | { | |
1023 | /* ChachaPoly has fixed length nonce and MAC (tag) */ | |
1024 | if ( ( iv_len != ctx->cipher_info->iv_size ) || | |
1025 | ( tag_len != 16U ) ) | |
1026 | { | |
1027 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
1028 | } | |
1029 | ||
1030 | *olen = ilen; | |
1031 | return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, | |
1032 | ilen, iv, ad, ad_len, input, output, tag ) ); | |
1033 | } | |
1034 | #endif /* MBEDTLS_CHACHAPOLY_C */ | |
1035 | ||
1036 | return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); | |
1037 | } | |
1038 | ||
1039 | /* | |
1040 | * Packet-oriented decryption for AEAD modes | |
1041 | */ | |
1042 | int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, | |
1043 | const unsigned char *iv, size_t iv_len, | |
1044 | const unsigned char *ad, size_t ad_len, | |
1045 | const unsigned char *input, size_t ilen, | |
1046 | unsigned char *output, size_t *olen, | |
1047 | const unsigned char *tag, size_t tag_len ) | |
1048 | { | |
1049 | #if defined(MBEDTLS_GCM_C) | |
1050 | if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) | |
1051 | { | |
1052 | int ret; | |
1053 | ||
1054 | *olen = ilen; | |
1055 | ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, | |
1056 | iv, iv_len, ad, ad_len, | |
1057 | tag, tag_len, input, output ); | |
1058 | ||
1059 | if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) | |
1060 | ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; | |
1061 | ||
1062 | return( ret ); | |
1063 | } | |
1064 | #endif /* MBEDTLS_GCM_C */ | |
1065 | #if defined(MBEDTLS_CCM_C) | |
1066 | if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) | |
1067 | { | |
1068 | int ret; | |
1069 | ||
1070 | *olen = ilen; | |
1071 | ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, | |
1072 | iv, iv_len, ad, ad_len, | |
1073 | input, output, tag, tag_len ); | |
1074 | ||
1075 | if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) | |
1076 | ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; | |
1077 | ||
1078 | return( ret ); | |
1079 | } | |
1080 | #endif /* MBEDTLS_CCM_C */ | |
1081 | #if defined(MBEDTLS_CHACHAPOLY_C) | |
1082 | if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) | |
1083 | { | |
1084 | int ret; | |
1085 | ||
1086 | /* ChachaPoly has fixed length nonce and MAC (tag) */ | |
1087 | if ( ( iv_len != ctx->cipher_info->iv_size ) || | |
1088 | ( tag_len != 16U ) ) | |
1089 | { | |
1090 | return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); | |
1091 | } | |
1092 | ||
1093 | *olen = ilen; | |
1094 | ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, | |
1095 | iv, ad, ad_len, tag, input, output ); | |
1096 | ||
1097 | if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) | |
1098 | ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; | |
1099 | ||
1100 | return( ret ); | |
1101 | } | |
1102 | #endif /* MBEDTLS_CHACHAPOLY_C */ | |
1103 | ||
1104 | return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); | |
1105 | } | |
1106 | #endif /* MBEDTLS_CIPHER_MODE_AEAD */ | |
1107 | ||
1108 | #endif /* MBEDTLS_CIPHER_C */ |