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