blob: b51a40bcc8c6a474dbc0f870ab45f577b0562c91 [file] [log] [blame]
Paul Bakker8123e9d2011-01-06 15:37:30 +00001/**
2 * \file cipher.c
Paul Bakker7dc4c442014-02-01 22:50:26 +01003 *
Manuel Pégourié-Gonnardb4fe3cb2015-01-22 16:11:05 +00004 * \brief Generic cipher wrapper for mbed TLS
Paul Bakker8123e9d2011-01-06 15:37:30 +00005 *
6 * \author Adriaan de Jong <dejong@fox-it.com>
7 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02008 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02009 * SPDX-License-Identifier: Apache-2.0
10 *
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.
Paul Bakker8123e9d2011-01-06 15:37:30 +000022 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000023 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker8123e9d2011-01-06 15:37:30 +000024 */
25
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020026#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000027#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020028#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#endif
Paul Bakker8123e9d2011-01-06 15:37:30 +000031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_CIPHER_C)
Paul Bakker8123e9d2011-01-06 15:37:30 +000033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/cipher.h"
Manuel Pégourié-Gonnard50518f42015-05-26 11:04:15 +020035#include "mbedtls/cipher_internal.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050036#include "mbedtls/platform_util.h"
Paul Bakker8123e9d2011-01-06 15:37:30 +000037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <stdlib.h>
39#include <string.h>
40
Daniel Kingb437a982016-05-17 20:33:28 -030041#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
42#include "mbedtls/aead_chacha20_poly1305.h"
43#endif
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_GCM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/gcm.h"
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +020047#endif
48
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if defined(MBEDTLS_CCM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/ccm.h"
Manuel Pégourié-Gonnard41936952014-05-13 13:18:17 +020051#endif
52
Daniel King0fe7b5b2016-05-15 19:56:20 -030053#if defined(MBEDTLS_CHACHA20_C)
54#include "mbedtls/chacha20.h"
55#endif
56
Simon Butcher327398a2016-10-05 14:09:11 +010057#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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
69#define MBEDTLS_CIPHER_MODE_STREAM
Manuel Pégourié-Gonnard37e230c2013-08-28 13:50:42 +020070#endif
71
Daniel Kingb437a982016-05-17 20:33:28 -030072/* Compare the contents of two buffers in constant time.
73 * Returns 0 if the contents are bitwise identical, otherwise returns
74 * a non-zero value. */
75static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len )
76{
77 const unsigned char *p1 = (const unsigned char*) v1;
78 const unsigned char *p2 = (const unsigned char*) v2;
79 size_t i;
80 unsigned char diff;
81
82 for( diff = 0, i = 0; i < len; i++ )
83 diff |= p1[i] ^ p2[i];
84
85 return (int)diff;
86}
87
Manuel Pégourié-Gonnarddace82f2013-09-18 15:12:07 +020088static int supported_init = 0;
Paul Bakker72f62662011-01-16 21:27:44 +000089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090const int *mbedtls_cipher_list( void )
Paul Bakker72f62662011-01-16 21:27:44 +000091{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 const mbedtls_cipher_definition_t *def;
Manuel Pégourié-Gonnarddace82f2013-09-18 15:12:07 +020093 int *type;
94
95 if( ! supported_init )
96 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097 def = mbedtls_cipher_definitions;
98 type = mbedtls_cipher_supported;
Manuel Pégourié-Gonnarddace82f2013-09-18 15:12:07 +020099
100 while( def->type != 0 )
101 *type++ = (*def++).type;
102
103 *type = 0;
104
105 supported_init = 1;
106 }
107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 return( mbedtls_cipher_supported );
Paul Bakker72f62662011-01-16 21:27:44 +0000109}
110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000112{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 const mbedtls_cipher_definition_t *def;
Paul Bakker5e0efa72013-09-08 23:04:04 +0200114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115 for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
Manuel Pégourié-Gonnarddace82f2013-09-18 15:12:07 +0200116 if( def->type == cipher_type )
117 return( def->info );
Paul Bakker343a8702011-06-09 14:27:58 +0000118
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200119 return( NULL );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000120}
121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000123{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 const mbedtls_cipher_definition_t *def;
Manuel Pégourié-Gonnarddace82f2013-09-18 15:12:07 +0200125
Paul Bakker8123e9d2011-01-06 15:37:30 +0000126 if( NULL == cipher_name )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200127 return( NULL );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200130 if( ! strcmp( def->info->name, cipher_name ) )
Manuel Pégourié-Gonnarddace82f2013-09-18 15:12:07 +0200131 return( def->info );
Paul Bakkerfab5c822012-02-06 16:45:10 +0000132
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200133 return( NULL );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000134}
135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200137 int key_bitlen,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 const mbedtls_cipher_mode_t mode )
Paul Bakkerf46b6952013-09-09 00:08:26 +0200139{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 const mbedtls_cipher_definition_t *def;
Paul Bakkerf46b6952013-09-09 00:08:26 +0200141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
Manuel Pégourié-Gonnarddace82f2013-09-18 15:12:07 +0200143 if( def->info->base->cipher == cipher_id &&
Manuel Pégourié-Gonnard898e0aa2015-06-18 15:28:12 +0200144 def->info->key_bitlen == (unsigned) key_bitlen &&
Manuel Pégourié-Gonnarddace82f2013-09-18 15:12:07 +0200145 def->info->mode == mode )
146 return( def->info );
Paul Bakkerf46b6952013-09-09 00:08:26 +0200147
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200148 return( NULL );
Paul Bakkerf46b6952013-09-09 00:08:26 +0200149}
150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
Paul Bakker84bbeb52014-07-01 14:53:22 +0200152{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200154}
155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
Paul Bakker84bbeb52014-07-01 14:53:22 +0200157{
158 if( ctx == NULL )
159 return;
160
Simon Butcher327398a2016-10-05 14:09:11 +0100161#if defined(MBEDTLS_CMAC_C)
162 if( ctx->cmac_ctx )
163 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500164 mbedtls_platform_zeroize( ctx->cmac_ctx,
165 sizeof( mbedtls_cmac_context_t ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100166 mbedtls_free( ctx->cmac_ctx );
167 }
168#endif
169
Paul Bakker84bbeb52014-07-01 14:53:22 +0200170 if( ctx->cipher_ctx )
171 ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
172
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500173 mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200174}
175
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200176int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000177{
178 if( NULL == cipher_info || NULL == ctx )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000182
Paul Bakker343a8702011-06-09 14:27:58 +0000183 if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000185
186 ctx->cipher_info = cipher_info;
187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200189 /*
190 * Ignore possible errors caused by a cipher mode that doesn't use padding
191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
193 (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 );
Paul Bakker48e93c82013-08-14 12:21:18 +0200194#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE );
Paul Bakker48e93c82013-08-14 12:21:18 +0200196#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200198
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200199 return( 0 );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000200}
201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200203 int key_bitlen, const mbedtls_operation_t operation )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000204{
205 if( NULL == ctx || NULL == ctx->cipher_info )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
Manuel Pégourié-Gonnard898e0aa2015-06-18 15:28:12 +0200209 (int) ctx->cipher_info->key_bitlen != key_bitlen )
Manuel Pégourié-Gonnard398c57b2014-06-23 12:10:59 +0200210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard398c57b2014-06-23 12:10:59 +0200212 }
Manuel Pégourié-Gonnarddd0f57f2013-09-16 11:47:43 +0200213
Manuel Pégourié-Gonnard898e0aa2015-06-18 15:28:12 +0200214 ctx->key_bitlen = key_bitlen;
Paul Bakker8123e9d2011-01-06 15:37:30 +0000215 ctx->operation = operation;
216
Paul Bakker343a8702011-06-09 14:27:58 +0000217 /*
Paul Bakker6132d0a2012-07-04 17:10:40 +0000218 * For CFB and CTR mode always use the encryption key schedule
Paul Bakker343a8702011-06-09 14:27:58 +0000219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 if( MBEDTLS_ENCRYPT == operation ||
221 MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
222 MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
Paul Bakker343a8702011-06-09 14:27:58 +0000223 {
224 return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
Manuel Pégourié-Gonnard898e0aa2015-06-18 15:28:12 +0200225 ctx->key_bitlen );
Paul Bakker343a8702011-06-09 14:27:58 +0000226 }
Paul Bakker8123e9d2011-01-06 15:37:30 +0000227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 if( MBEDTLS_DECRYPT == operation )
Paul Bakker343a8702011-06-09 14:27:58 +0000229 return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
Manuel Pégourié-Gonnard898e0aa2015-06-18 15:28:12 +0200230 ctx->key_bitlen );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000233}
234
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
Manuel Pégourié-Gonnard9c853b92013-09-03 13:04:44 +0200236 const unsigned char *iv, size_t iv_len )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000237{
Manuel Pégourié-Gonnarda235b5b2013-09-03 13:25:52 +0200238 size_t actual_iv_size;
Manuel Pégourié-Gonnard9c853b92013-09-03 13:04:44 +0200239
Paul Bakker8123e9d2011-01-06 15:37:30 +0000240 if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000242
Manuel Pégourié-Gonnarde0dca4a2013-10-24 16:54:25 +0200243 /* avoid buffer overflow in ctx->iv */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 if( iv_len > MBEDTLS_MAX_IV_LENGTH )
245 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnarde0dca4a2013-10-24 16:54:25 +0200246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 )
Manuel Pégourié-Gonnarda235b5b2013-09-03 13:25:52 +0200248 actual_iv_size = iv_len;
249 else
Manuel Pégourié-Gonnarde0dca4a2013-10-24 16:54:25 +0200250 {
Manuel Pégourié-Gonnarda235b5b2013-09-03 13:25:52 +0200251 actual_iv_size = ctx->cipher_info->iv_size;
Manuel Pégourié-Gonnard9c853b92013-09-03 13:04:44 +0200252
Manuel Pégourié-Gonnarde0dca4a2013-10-24 16:54:25 +0200253 /* avoid reading past the end of input buffer */
254 if( actual_iv_size > iv_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarde0dca4a2013-10-24 16:54:25 +0200256 }
257
Daniel King0fe7b5b2016-05-15 19:56:20 -0300258#if defined(MBEDTLS_CHACHA20_C)
259 if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
260 {
261 if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
262 iv,
263 0U ) ) /* Initial counter value */
264 {
265 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
266 }
267 }
268#endif
269
Manuel Pégourié-Gonnarda235b5b2013-09-03 13:25:52 +0200270 memcpy( ctx->iv, iv, actual_iv_size );
271 ctx->iv_size = actual_iv_size;
Manuel Pégourié-Gonnard9c853b92013-09-03 13:04:44 +0200272
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200273 return( 0 );
Manuel Pégourié-Gonnard9c853b92013-09-03 13:04:44 +0200274}
275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
Manuel Pégourié-Gonnard9c853b92013-09-03 13:04:44 +0200277{
Manuel Pégourié-Gonnard2adc40c2013-09-03 13:54:12 +0200278 if( NULL == ctx || NULL == ctx->cipher_info )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard2adc40c2013-09-03 13:54:12 +0200280
Paul Bakker8123e9d2011-01-06 15:37:30 +0000281 ctx->unprocessed_len = 0;
282
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200283 return( 0 );
Manuel Pégourié-Gonnard2adc40c2013-09-03 13:54:12 +0200284}
285
Daniel Kingb437a982016-05-17 20:33:28 -0300286#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
Manuel Pégourié-Gonnard2adc40c2013-09-03 13:54:12 +0200288 const unsigned char *ad, size_t ad_len )
289{
290 if( NULL == ctx || NULL == ctx->cipher_info )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200291 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard2adc40c2013-09-03 13:54:12 +0200292
Daniel Kingb437a982016-05-17 20:33:28 -0300293#if defined(MBEDTLS_GCM_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200295 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
Manuel Pégourié-Gonnard9c853b92013-09-03 13:04:44 +0200297 ctx->iv, ctx->iv_size, ad, ad_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200298 }
Daniel Kingb437a982016-05-17 20:33:28 -0300299#endif
300
301#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
302 if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
303 {
304 int result;
305 mbedtls_aead_chacha20_poly1305_mode_t mode;
306
307 mode = ( ctx->operation == MBEDTLS_ENCRYPT )
308 ? MBEDTLS_AEAD_CHACHA20_POLY1305_ENCRYPT
309 : MBEDTLS_AEAD_CHACHA20_POLY1305_DECRYPT;
310
311 result = mbedtls_aead_chacha20_poly1305_starts( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
312 ctx->iv,
313 mode );
314 if ( result != 0 )
315 return( result );
316
317 return mbedtls_aead_chacha20_poly1305_update_aad( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
318 ad_len, ad );
319 }
320#endif
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200321
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200322 return( 0 );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000323}
Daniel Kingb437a982016-05-17 20:33:28 -0300324#endif /* MBEDTLS_GCM_C || MBEDTLS_AEAD_CHACHA20_POLY1305_C */
Paul Bakker8123e9d2011-01-06 15:37:30 +0000325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200327 size_t ilen, unsigned char *output, size_t *olen )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000328{
Paul Bakkerff61a782011-06-09 15:42:02 +0000329 int ret;
Janos Follath98e28a72016-05-31 14:03:54 +0100330 size_t block_size = 0;
Paul Bakker8123e9d2011-01-06 15:37:30 +0000331
Paul Bakker68884e32013-01-07 18:20:04 +0100332 if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
Paul Bakkera885d682011-01-20 16:35:05 +0000333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Paul Bakkera885d682011-01-20 16:35:05 +0000335 }
Paul Bakker8123e9d2011-01-06 15:37:30 +0000336
Paul Bakker6c212762013-12-16 15:24:50 +0100337 *olen = 0;
Janos Follath98e28a72016-05-31 14:03:54 +0100338 block_size = mbedtls_cipher_get_block_size( ctx );
Paul Bakker6c212762013-12-16 15:24:50 +0100339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
Paul Bakker5e0efa72013-09-08 23:04:04 +0200341 {
Janos Follath98e28a72016-05-31 14:03:54 +0100342 if( ilen != block_size )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
Paul Bakker5e0efa72013-09-08 23:04:04 +0200344
345 *olen = ilen;
346
347 if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
348 ctx->operation, input, output ) ) )
349 {
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200350 return( ret );
Paul Bakker5e0efa72013-09-08 23:04:04 +0200351 }
352
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200353 return( 0 );
Paul Bakker5e0efa72013-09-08 23:04:04 +0200354 }
355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356#if defined(MBEDTLS_GCM_C)
357 if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
Manuel Pégourié-Gonnardb8bd5932013-09-05 13:38:15 +0200358 {
359 *olen = ilen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200361 output );
Manuel Pégourié-Gonnardb8bd5932013-09-05 13:38:15 +0200362 }
363#endif
364
Janos Follath98e28a72016-05-31 14:03:54 +0100365 if ( 0 == block_size )
366 {
367 return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
368 }
369
Paul Bakker68884e32013-01-07 18:20:04 +0100370 if( input == output &&
Janos Follath98e28a72016-05-31 14:03:54 +0100371 ( ctx->unprocessed_len != 0 || ilen % block_size ) )
Paul Bakker68884e32013-01-07 18:20:04 +0100372 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Paul Bakker68884e32013-01-07 18:20:04 +0100374 }
Paul Bakker8123e9d2011-01-06 15:37:30 +0000375
Daniel King0fe7b5b2016-05-15 19:56:20 -0300376
377#if defined(MBEDTLS_CHACHA20_C)
378 if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
379 {
380 *olen = ilen;
381 return mbedtls_chacha20_update( (mbedtls_chacha20_context*) ctx->cipher_ctx,
382 ilen, input, output );
383 }
384#endif
385
Daniel Kingb437a982016-05-17 20:33:28 -0300386 if( input == output &&
387 ( ctx->unprocessed_len != 0 || ilen % mbedtls_cipher_get_block_size( ctx ) ) )
388 {
389 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
390 }
391
392#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
393 if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
394 {
395 *olen = ilen;
396 return mbedtls_aead_chacha20_poly1305_update( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
397 ilen, input, output );
398 }
399#endif
400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401#if defined(MBEDTLS_CIPHER_MODE_CBC)
402 if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000403 {
Manuel Pégourié-Gonnard989ed382013-09-13 14:41:45 +0200404 size_t copy_len = 0;
405
Paul Bakker8123e9d2011-01-06 15:37:30 +0000406 /*
407 * If there is not enough data for a full block, cache it.
408 */
Andy Leiserson79e77892017-04-28 20:01:49 -0700409 if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000410 ilen <= block_size - ctx->unprocessed_len ) ||
Andy Leiserson79e77892017-04-28 20:01:49 -0700411 ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
412 ilen < block_size - ctx->unprocessed_len ) ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 ( ctx->operation == MBEDTLS_ENCRYPT &&
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000414 ilen < block_size - ctx->unprocessed_len ) )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000415 {
416 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
417 ilen );
418
419 ctx->unprocessed_len += ilen;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200420 return( 0 );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000421 }
422
423 /*
424 * Process cached data first
425 */
Janos Follath98e28a72016-05-31 14:03:54 +0100426 if( 0 != ctx->unprocessed_len )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000427 {
Janos Follath98e28a72016-05-31 14:03:54 +0100428 copy_len = block_size - ctx->unprocessed_len;
Paul Bakker8123e9d2011-01-06 15:37:30 +0000429
430 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
431 copy_len );
432
Paul Bakkerff61a782011-06-09 15:42:02 +0000433 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
Janos Follath98e28a72016-05-31 14:03:54 +0100434 ctx->operation, block_size, ctx->iv,
Paul Bakkerff61a782011-06-09 15:42:02 +0000435 ctx->unprocessed_data, output ) ) )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000436 {
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200437 return( ret );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000438 }
439
Janos Follath98e28a72016-05-31 14:03:54 +0100440 *olen += block_size;
441 output += block_size;
Paul Bakker8123e9d2011-01-06 15:37:30 +0000442 ctx->unprocessed_len = 0;
443
444 input += copy_len;
445 ilen -= copy_len;
446 }
447
448 /*
449 * Cache final, incomplete block
450 */
451 if( 0 != ilen )
452 {
Janos Follath98e28a72016-05-31 14:03:54 +0100453 if( 0 == block_size )
454 {
455 return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
456 }
457
Andy Leiserson79e77892017-04-28 20:01:49 -0700458 /* Encryption: only cache partial blocks
459 * Decryption w/ padding: always keep at least one whole block
460 * Decryption w/o padding: only cache partial blocks
461 */
Janos Follath98e28a72016-05-31 14:03:54 +0100462 copy_len = ilen % block_size;
Andy Leiserson79e77892017-04-28 20:01:49 -0700463 if( copy_len == 0 &&
464 ctx->operation == MBEDTLS_DECRYPT &&
465 NULL != ctx->add_padding)
466 {
Janos Follath98e28a72016-05-31 14:03:54 +0100467 copy_len = block_size;
Andy Leiserson79e77892017-04-28 20:01:49 -0700468 }
Paul Bakker8123e9d2011-01-06 15:37:30 +0000469
470 memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
471 copy_len );
472
473 ctx->unprocessed_len += copy_len;
474 ilen -= copy_len;
475 }
476
477 /*
478 * Process remaining full blocks
479 */
480 if( ilen )
481 {
Paul Bakkerff61a782011-06-09 15:42:02 +0000482 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
483 ctx->operation, ilen, ctx->iv, input, output ) ) )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000484 {
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200485 return( ret );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000486 }
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200487
Paul Bakker8123e9d2011-01-06 15:37:30 +0000488 *olen += ilen;
489 }
490
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200491 return( 0 );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000492 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493#endif /* MBEDTLS_CIPHER_MODE_CBC */
Paul Bakker8123e9d2011-01-06 15:37:30 +0000494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495#if defined(MBEDTLS_CIPHER_MODE_CFB)
496 if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB )
Paul Bakker343a8702011-06-09 14:27:58 +0000497 {
Paul Bakker6132d0a2012-07-04 17:10:40 +0000498 if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
Paul Bakker343a8702011-06-09 14:27:58 +0000499 ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
Paul Bakkerff61a782011-06-09 15:42:02 +0000500 input, output ) ) )
Paul Bakker343a8702011-06-09 14:27:58 +0000501 {
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200502 return( ret );
Paul Bakker343a8702011-06-09 14:27:58 +0000503 }
504
505 *olen = ilen;
506
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200507 return( 0 );
Paul Bakker343a8702011-06-09 14:27:58 +0000508 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509#endif /* MBEDTLS_CIPHER_MODE_CFB */
Paul Bakker343a8702011-06-09 14:27:58 +0000510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511#if defined(MBEDTLS_CIPHER_MODE_CTR)
512 if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
Paul Bakker343a8702011-06-09 14:27:58 +0000513 {
Paul Bakkerff61a782011-06-09 15:42:02 +0000514 if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
Paul Bakker343a8702011-06-09 14:27:58 +0000515 ilen, &ctx->unprocessed_len, ctx->iv,
Paul Bakkerff61a782011-06-09 15:42:02 +0000516 ctx->unprocessed_data, input, output ) ) )
Paul Bakker343a8702011-06-09 14:27:58 +0000517 {
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200518 return( ret );
Paul Bakker343a8702011-06-09 14:27:58 +0000519 }
520
521 *olen = ilen;
522
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200523 return( 0 );
Paul Bakker343a8702011-06-09 14:27:58 +0000524 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525#endif /* MBEDTLS_CIPHER_MODE_CTR */
Paul Bakker343a8702011-06-09 14:27:58 +0000526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527#if defined(MBEDTLS_CIPHER_MODE_STREAM)
528 if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
Manuel Pégourié-Gonnard37e230c2013-08-28 13:50:42 +0200529 {
530 if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
531 ilen, input, output ) ) )
532 {
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200533 return( ret );
Manuel Pégourié-Gonnard37e230c2013-08-28 13:50:42 +0200534 }
535
536 *olen = ilen;
537
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200538 return( 0 );
Manuel Pégourié-Gonnard37e230c2013-08-28 13:50:42 +0200539 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540#endif /* MBEDTLS_CIPHER_MODE_STREAM */
Manuel Pégourié-Gonnard37e230c2013-08-28 13:50:42 +0200541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000543}
544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
546#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200547/*
548 * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
549 */
Paul Bakker23986e52011-04-24 08:57:21 +0000550static void add_pkcs_padding( unsigned char *output, size_t output_len,
551 size_t data_len )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000552{
Paul Bakker23986e52011-04-24 08:57:21 +0000553 size_t padding_len = output_len - data_len;
Manuel Pégourié-Gonnardf8ab0692013-10-27 17:21:14 +0100554 unsigned char i;
Paul Bakker8123e9d2011-01-06 15:37:30 +0000555
556 for( i = 0; i < padding_len; i++ )
Paul Bakker23986e52011-04-24 08:57:21 +0000557 output[data_len + i] = (unsigned char) padding_len;
Paul Bakker8123e9d2011-01-06 15:37:30 +0000558}
559
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200560static int get_pkcs_padding( unsigned char *input, size_t input_len,
561 size_t *data_len )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000562{
Manuel Pégourié-Gonnardf8ab0692013-10-27 17:21:14 +0100563 size_t i, pad_idx;
564 unsigned char padding_len, bad = 0;
Paul Bakker8123e9d2011-01-06 15:37:30 +0000565
Paul Bakkera885d682011-01-20 16:35:05 +0000566 if( NULL == input || NULL == data_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000568
569 padding_len = input[input_len - 1];
Paul Bakker8123e9d2011-01-06 15:37:30 +0000570 *data_len = input_len - padding_len;
571
Manuel Pégourié-Gonnardf8ab0692013-10-27 17:21:14 +0100572 /* Avoid logical || since it results in a branch */
573 bad |= padding_len > input_len;
574 bad |= padding_len == 0;
575
576 /* The number of bytes checked must be independent of padding_len,
577 * so pick input_len, which is usually 8 or 16 (one block) */
578 pad_idx = input_len - padding_len;
579 for( i = 0; i < input_len; i++ )
580 bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000583}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200584#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
Paul Bakker8123e9d2011-01-06 15:37:30 +0000585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200587/*
588 * One and zeros padding: fill with 80 00 ... 00
589 */
590static void add_one_and_zeros_padding( unsigned char *output,
591 size_t output_len, size_t data_len )
592{
593 size_t padding_len = output_len - data_len;
594 unsigned char i = 0;
595
596 output[data_len] = 0x80;
597 for( i = 1; i < padding_len; i++ )
598 output[data_len + i] = 0x00;
599}
600
601static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
602 size_t *data_len )
603{
Manuel Pégourié-Gonnard6c329902013-10-27 18:25:03 +0100604 size_t i;
605 unsigned char done = 0, prev_done, bad;
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200606
607 if( NULL == input || NULL == data_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200609
Micha Krausba8316f2017-12-23 23:40:08 +0100610 bad = 0x80;
Manuel Pégourié-Gonnard6c329902013-10-27 18:25:03 +0100611 *data_len = 0;
612 for( i = input_len; i > 0; i-- )
613 {
614 prev_done = done;
Micha Krausba8316f2017-12-23 23:40:08 +0100615 done |= ( input[i - 1] != 0 );
Manuel Pégourié-Gonnard6c329902013-10-27 18:25:03 +0100616 *data_len |= ( i - 1 ) * ( done != prev_done );
Micha Krausba8316f2017-12-23 23:40:08 +0100617 bad ^= input[i - 1] * ( done != prev_done );
Manuel Pégourié-Gonnard6c329902013-10-27 18:25:03 +0100618 }
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200621
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200622}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
Manuel Pégourié-Gonnard8d4291b2013-07-26 14:55:18 +0200626/*
627 * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
628 */
629static void add_zeros_and_len_padding( unsigned char *output,
630 size_t output_len, size_t data_len )
631{
632 size_t padding_len = output_len - data_len;
633 unsigned char i = 0;
634
635 for( i = 1; i < padding_len; i++ )
636 output[data_len + i - 1] = 0x00;
637 output[output_len - 1] = (unsigned char) padding_len;
638}
639
640static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
641 size_t *data_len )
642{
Manuel Pégourié-Gonnardd17df512013-10-27 17:32:43 +0100643 size_t i, pad_idx;
644 unsigned char padding_len, bad = 0;
Manuel Pégourié-Gonnard8d4291b2013-07-26 14:55:18 +0200645
646 if( NULL == input || NULL == data_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard8d4291b2013-07-26 14:55:18 +0200648
649 padding_len = input[input_len - 1];
Manuel Pégourié-Gonnard8d4291b2013-07-26 14:55:18 +0200650 *data_len = input_len - padding_len;
651
Manuel Pégourié-Gonnardd17df512013-10-27 17:32:43 +0100652 /* Avoid logical || since it results in a branch */
653 bad |= padding_len > input_len;
654 bad |= padding_len == 0;
655
656 /* The number of bytes checked must be independent of padding_len */
657 pad_idx = input_len - padding_len;
658 for( i = 0; i < input_len - 1; i++ )
659 bad |= input[i] * ( i >= pad_idx );
660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
Manuel Pégourié-Gonnard8d4291b2013-07-26 14:55:18 +0200662}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
Manuel Pégourié-Gonnard8d4291b2013-07-26 14:55:18 +0200664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
Manuel Pégourié-Gonnard0e7d2c02013-07-26 16:05:14 +0200666/*
667 * Zero padding: fill with 00 ... 00
668 */
669static void add_zeros_padding( unsigned char *output,
670 size_t output_len, size_t data_len )
671{
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200672 size_t i;
Manuel Pégourié-Gonnard0e7d2c02013-07-26 16:05:14 +0200673
674 for( i = data_len; i < output_len; i++ )
675 output[i] = 0x00;
676}
677
678static int get_zeros_padding( unsigned char *input, size_t input_len,
679 size_t *data_len )
680{
Manuel Pégourié-Gonnarde68bf172013-10-27 18:26:39 +0100681 size_t i;
682 unsigned char done = 0, prev_done;
683
Manuel Pégourié-Gonnard0e7d2c02013-07-26 16:05:14 +0200684 if( NULL == input || NULL == data_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard0e7d2c02013-07-26 16:05:14 +0200686
Manuel Pégourié-Gonnarde68bf172013-10-27 18:26:39 +0100687 *data_len = 0;
688 for( i = input_len; i > 0; i-- )
689 {
690 prev_done = done;
691 done |= ( input[i-1] != 0 );
692 *data_len |= i * ( done != prev_done );
693 }
Manuel Pégourié-Gonnard0e7d2c02013-07-26 16:05:14 +0200694
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200695 return( 0 );
Manuel Pégourié-Gonnard0e7d2c02013-07-26 16:05:14 +0200696}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
Manuel Pégourié-Gonnard0e7d2c02013-07-26 16:05:14 +0200698
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200699/*
700 * No padding: don't pad :)
701 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 * There is no add_padding function (check for NULL in mbedtls_cipher_finish)
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200703 * but a trivial get_padding function
704 */
705static int get_no_padding( unsigned char *input, size_t input_len,
706 size_t *data_len )
707{
708 if( NULL == input || NULL == data_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200710
711 *data_len = input_len;
712
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200713 return( 0 );
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200714}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200718 unsigned char *output, size_t *olen )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000719{
720 if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000722
723 *olen = 0;
724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725 if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
726 MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
727 MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
728 MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
Paul Bakker343a8702011-06-09 14:27:58 +0000729 {
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200730 return( 0 );
Paul Bakker343a8702011-06-09 14:27:58 +0000731 }
732
Daniel Kingb437a982016-05-17 20:33:28 -0300733 if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) ||
734 ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
Daniel King0fe7b5b2016-05-15 19:56:20 -0300735 {
736 return( 0 );
737 }
738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
Paul Bakker5e0efa72013-09-08 23:04:04 +0200740 {
741 if( ctx->unprocessed_len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
Paul Bakker5e0efa72013-09-08 23:04:04 +0200743
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200744 return( 0 );
Paul Bakker5e0efa72013-09-08 23:04:04 +0200745 }
746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747#if defined(MBEDTLS_CIPHER_MODE_CBC)
748 if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000749 {
Manuel Pégourié-Gonnard989ed382013-09-13 14:41:45 +0200750 int ret = 0;
751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 if( MBEDTLS_ENCRYPT == ctx->operation )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000753 {
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200754 /* check for 'no padding' mode */
755 if( NULL == ctx->add_padding )
756 {
757 if( 0 != ctx->unprocessed_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200758 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200759
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200760 return( 0 );
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200761 }
762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ),
Paul Bakker8123e9d2011-01-06 15:37:30 +0000764 ctx->unprocessed_len );
765 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000767 {
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200768 /*
769 * For decrypt operations, expect a full block,
770 * or an empty block if no padding
771 */
772 if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200773 return( 0 );
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000776 }
777
778 /* cipher block */
Paul Bakkerff61a782011-06-09 15:42:02 +0000779 if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200780 ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv,
Paul Bakkerff61a782011-06-09 15:42:02 +0000781 ctx->unprocessed_data, output ) ) )
Paul Bakker8123e9d2011-01-06 15:37:30 +0000782 {
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200783 return( ret );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000784 }
785
786 /* Set output size for decryption */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787 if( MBEDTLS_DECRYPT == ctx->operation )
788 return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200789 olen );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000790
791 /* Set output size for encryption */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792 *olen = mbedtls_cipher_get_block_size( ctx );
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200793 return( 0 );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000794 }
Manuel Pégourié-Gonnard989ed382013-09-13 14:41:45 +0200795#else
796 ((void) output);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797#endif /* MBEDTLS_CIPHER_MODE_CBC */
Paul Bakker8123e9d2011-01-06 15:37:30 +0000798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200799 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Paul Bakker8123e9d2011-01-06 15:37:30 +0000800}
801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
803int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode )
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200804{
805 if( NULL == ctx ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200806 MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200807 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200809 }
810
Paul Bakker1a45d912013-08-14 12:04:26 +0200811 switch( mode )
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200812 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200813#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
814 case MBEDTLS_PADDING_PKCS7:
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200815 ctx->add_padding = add_pkcs_padding;
816 ctx->get_padding = get_pkcs_padding;
Paul Bakker1a45d912013-08-14 12:04:26 +0200817 break;
Paul Bakker48e93c82013-08-14 12:21:18 +0200818#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
820 case MBEDTLS_PADDING_ONE_AND_ZEROS:
Manuel Pégourié-Gonnard679f9e92013-07-26 12:46:02 +0200821 ctx->add_padding = add_one_and_zeros_padding;
822 ctx->get_padding = get_one_and_zeros_padding;
Paul Bakker1a45d912013-08-14 12:04:26 +0200823 break;
Paul Bakker48e93c82013-08-14 12:21:18 +0200824#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
826 case MBEDTLS_PADDING_ZEROS_AND_LEN:
Manuel Pégourié-Gonnard8d4291b2013-07-26 14:55:18 +0200827 ctx->add_padding = add_zeros_and_len_padding;
828 ctx->get_padding = get_zeros_and_len_padding;
Paul Bakker1a45d912013-08-14 12:04:26 +0200829 break;
Paul Bakker48e93c82013-08-14 12:21:18 +0200830#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
832 case MBEDTLS_PADDING_ZEROS:
Manuel Pégourié-Gonnard0e7d2c02013-07-26 16:05:14 +0200833 ctx->add_padding = add_zeros_padding;
834 ctx->get_padding = get_zeros_padding;
Paul Bakker1a45d912013-08-14 12:04:26 +0200835 break;
Paul Bakker48e93c82013-08-14 12:21:18 +0200836#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837 case MBEDTLS_PADDING_NONE:
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200838 ctx->add_padding = NULL;
839 ctx->get_padding = get_no_padding;
Paul Bakker1a45d912013-08-14 12:04:26 +0200840 break;
841
842 default:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardebdc4132013-07-26 16:50:44 +0200844 }
845
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200846 return( 0 );
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200847}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
Manuel Pégourié-Gonnardac56a1a2013-07-25 12:31:10 +0200849
Daniel Kingb437a982016-05-17 20:33:28 -0300850#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200852 unsigned char *tag, size_t tag_len )
853{
854 if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200855 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 if( MBEDTLS_ENCRYPT != ctx->operation )
858 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200859
Daniel Kingb437a982016-05-17 20:33:28 -0300860#if defined(MBEDTLS_GCM_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
862 return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
Daniel Kingb437a982016-05-17 20:33:28 -0300863#endif
864
865#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
866 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
867 {
868 /* Don't allow truncated MAC for Poly1305 */
869 if ( tag_len != 16U )
870 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
871
872 return mbedtls_aead_chacha20_poly1305_finish( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
873 tag );
874 }
875#endif
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200876
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200877 return( 0 );
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200878}
Paul Bakker9af723c2014-05-01 13:03:14 +0200879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200881 const unsigned char *tag, size_t tag_len )
882{
Daniel Kingb437a982016-05-17 20:33:28 -0300883 unsigned char check_tag[16];
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200884 int ret;
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200885
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200886 if( NULL == ctx || NULL == ctx->cipher_info ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200887 MBEDTLS_DECRYPT != ctx->operation )
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200888 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200890 }
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200891
Daniel Kingb437a982016-05-17 20:33:28 -0300892#if defined(MBEDTLS_GCM_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200894 {
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200895 if( tag_len > sizeof( check_tag ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200899 check_tag, tag_len ) ) )
900 {
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200901 return( ret );
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200902 }
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200903
904 /* Check the tag in "constant-time" */
Daniel Kingb437a982016-05-17 20:33:28 -0300905 if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906 return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200907
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200908 return( 0 );
Manuel Pégourié-Gonnard43a47802013-09-03 16:35:53 +0200909 }
Daniel Kingb437a982016-05-17 20:33:28 -0300910#endif /* MBEDTLS_GCM_C */
911
912#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
913 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
914 {
915 /* Don't allow truncated MAC for Poly1305 */
916 if ( tag_len != sizeof( check_tag ) )
917 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
918
919 ret = mbedtls_aead_chacha20_poly1305_finish( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
920 check_tag );
921 if ( ret != 0 )
922 {
923 return( ret );
924 }
925
926 /* Check the tag in "constant-time" */
927 if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
928 return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
929
930 return( 0 );
931 }
932#endif /* MBEDTLS_AEAD_CHACHA20_POLY1305_C */
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200933
934 return( 0 );
935}
Daniel Kingb437a982016-05-17 20:33:28 -0300936#endif /* MBEDTLS_GCM_C || MBEDTLS_AEAD_CHACHA20_POLY1305_C */
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200937
Manuel Pégourié-Gonnard3c1d1502014-05-12 13:46:08 +0200938/*
939 * Packet-oriented wrapper for non-AEAD modes
940 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
Manuel Pégourié-Gonnard3c1d1502014-05-12 13:46:08 +0200942 const unsigned char *iv, size_t iv_len,
943 const unsigned char *input, size_t ilen,
944 unsigned char *output, size_t *olen )
945{
946 int ret;
947 size_t finish_olen;
948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949 if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
Manuel Pégourié-Gonnard3c1d1502014-05-12 13:46:08 +0200950 return( ret );
951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952 if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
Manuel Pégourié-Gonnard3c1d1502014-05-12 13:46:08 +0200953 return( ret );
954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200955 if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
Manuel Pégourié-Gonnard3c1d1502014-05-12 13:46:08 +0200956 return( ret );
957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958 if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
Manuel Pégourié-Gonnard3c1d1502014-05-12 13:46:08 +0200959 return( ret );
960
961 *olen += finish_olen;
962
963 return( 0 );
964}
965
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966#if defined(MBEDTLS_CIPHER_MODE_AEAD)
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +0200967/*
968 * Packet-oriented encryption for AEAD modes
969 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +0200971 const unsigned char *iv, size_t iv_len,
972 const unsigned char *ad, size_t ad_len,
973 const unsigned char *input, size_t ilen,
974 unsigned char *output, size_t *olen,
975 unsigned char *tag, size_t tag_len )
976{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977#if defined(MBEDTLS_GCM_C)
978 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +0200979 {
980 *olen = ilen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981 return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen,
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +0200982 iv, iv_len, ad, ad_len, input, output,
983 tag_len, tag ) );
984 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985#endif /* MBEDTLS_GCM_C */
986#if defined(MBEDTLS_CCM_C)
987 if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
Manuel Pégourié-Gonnard41936952014-05-13 13:18:17 +0200988 {
989 *olen = ilen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
Manuel Pégourié-Gonnard41936952014-05-13 13:18:17 +0200991 iv, iv_len, ad, ad_len, input, output,
992 tag, tag_len ) );
993 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994#endif /* MBEDTLS_CCM_C */
Daniel Kingb437a982016-05-17 20:33:28 -0300995#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
996 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
997 {
998 int ret;
999
1000 if ( ( iv_len != ctx->cipher_info->iv_size ) ||
1001 ( tag_len != 16U ) ) /* Truncated MAC is not allowed for Poly1305 */
1002 {
1003 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1004 }
1005
1006 *olen = ilen;
1007
1008 ret = mbedtls_aead_chacha20_poly1305_starts( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
1009 iv, MBEDTLS_AEAD_CHACHA20_POLY1305_ENCRYPT );
1010 if ( ret != 0 )
1011 return( ret );
1012
1013 ret = mbedtls_aead_chacha20_poly1305_update_aad( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
1014 ad_len, ad );
1015 if ( ret != 0 )
1016 return( ret );
1017
1018 ret = mbedtls_aead_chacha20_poly1305_update( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
1019 ilen, input, output );
1020 if ( ret != 0 )
1021 return( ret );
1022
1023 ret = mbedtls_aead_chacha20_poly1305_finish( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
1024 tag );
1025 return( ret );
1026 }
1027#endif /* MBEDTLS_AEAD_CHACHA20_POLY1305_C */
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001030}
1031
1032/*
1033 * Packet-oriented decryption for AEAD modes
1034 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001036 const unsigned char *iv, size_t iv_len,
1037 const unsigned char *ad, size_t ad_len,
1038 const unsigned char *input, size_t ilen,
1039 unsigned char *output, size_t *olen,
1040 const unsigned char *tag, size_t tag_len )
1041{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042#if defined(MBEDTLS_GCM_C)
1043 if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001044 {
1045 int ret;
1046
1047 *olen = ilen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001049 iv, iv_len, ad, ad_len,
1050 tag, tag_len, input, output );
1051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED )
1053 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001054
1055 return( ret );
1056 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057#endif /* MBEDTLS_GCM_C */
1058#if defined(MBEDTLS_CCM_C)
1059 if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
Manuel Pégourié-Gonnard41936952014-05-13 13:18:17 +02001060 {
1061 int ret;
1062
1063 *olen = ilen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064 ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
Manuel Pégourié-Gonnard41936952014-05-13 13:18:17 +02001065 iv, iv_len, ad, ad_len,
1066 input, output, tag, tag_len );
1067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
1069 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
Manuel Pégourié-Gonnard41936952014-05-13 13:18:17 +02001070
1071 return( ret );
1072 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073#endif /* MBEDTLS_CCM_C */
Daniel Kingb437a982016-05-17 20:33:28 -03001074#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
1075 if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
1076 {
1077 unsigned char check_tag[16];
1078 int ret;
1079
1080 if ( ( iv_len != ctx->cipher_info->iv_size ) ||
1081 ( tag_len != 16U ) ) /* Truncated MAC is not allowed for Poly1305 */
1082 {
1083 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
1084 }
1085
1086 *olen = ilen;
1087
1088 ret = mbedtls_aead_chacha20_poly1305_starts( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
1089 iv, MBEDTLS_AEAD_CHACHA20_POLY1305_DECRYPT );
1090 if ( ret != 0 )
1091 return( ret );
1092
1093 ret = mbedtls_aead_chacha20_poly1305_update_aad( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
1094 ad_len, ad );
1095 if ( ret != 0 )
1096 return( ret );
1097
1098 ret = mbedtls_aead_chacha20_poly1305_update( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
1099 ilen, input, output );
1100 if ( ret != 0 )
1101 return( ret );
1102
1103 ret = mbedtls_aead_chacha20_poly1305_finish( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
1104 check_tag );
1105 if ( ret != 0 )
1106 return( ret );
1107
1108 /* Compare the tag in constant time */
1109 if ( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
1110 return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
1111
1112 return( 0 );
1113 }
1114#endif /* MBEDTLS_AEAD_CHACHA20_POLY1305_C */
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001117}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118#endif /* MBEDTLS_CIPHER_MODE_AEAD */
Manuel Pégourié-Gonnard4562ffe2014-05-13 12:19:29 +02001119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120#endif /* MBEDTLS_CIPHER_C */