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