1c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0 2817466cbSJens Wiklander /** 3817466cbSJens Wiklander * \file cipher.c 4817466cbSJens Wiklander * 5817466cbSJens Wiklander * \brief Generic cipher wrapper for mbed TLS 6817466cbSJens Wiklander * 7817466cbSJens Wiklander * \author Adriaan de Jong <dejong@fox-it.com> 8817466cbSJens Wiklander * 9817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 10817466cbSJens Wiklander * 11817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 12817466cbSJens Wiklander * not use this file except in compliance with the License. 13817466cbSJens Wiklander * You may obtain a copy of the License at 14817466cbSJens Wiklander * 15817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 16817466cbSJens Wiklander * 17817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 18817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 19817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20817466cbSJens Wiklander * See the License for the specific language governing permissions and 21817466cbSJens Wiklander * limitations under the License. 22817466cbSJens Wiklander * 23817466cbSJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 24817466cbSJens Wiklander */ 25817466cbSJens Wiklander 26817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 27817466cbSJens Wiklander #include "mbedtls/config.h" 28817466cbSJens Wiklander #else 29817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 30817466cbSJens Wiklander #endif 31817466cbSJens Wiklander 32817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_C) 33817466cbSJens Wiklander 34817466cbSJens Wiklander #include "mbedtls/cipher.h" 35817466cbSJens Wiklander #include "mbedtls/cipher_internal.h" 363d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 37*11fa71b9SJerome Forissier #include "mbedtls/error.h" 38817466cbSJens Wiklander 39817466cbSJens Wiklander #include <stdlib.h> 40817466cbSJens Wiklander #include <string.h> 41817466cbSJens Wiklander 423d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 433d3b0591SJens Wiklander #include "mbedtls/chachapoly.h" 443d3b0591SJens Wiklander #endif 453d3b0591SJens Wiklander 46817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 47817466cbSJens Wiklander #include "mbedtls/gcm.h" 48817466cbSJens Wiklander #endif 49817466cbSJens Wiklander 50817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 51817466cbSJens Wiklander #include "mbedtls/ccm.h" 52817466cbSJens Wiklander #endif 53817466cbSJens Wiklander 543d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C) 553d3b0591SJens Wiklander #include "mbedtls/chacha20.h" 563d3b0591SJens Wiklander #endif 573d3b0591SJens Wiklander 58817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C) 59817466cbSJens Wiklander #include "mbedtls/cmac.h" 60817466cbSJens Wiklander #endif 61817466cbSJens Wiklander 62*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 63*11fa71b9SJerome Forissier #include "psa/crypto.h" 64*11fa71b9SJerome Forissier #include "mbedtls/psa_util.h" 65*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 66*11fa71b9SJerome Forissier 67*11fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 68*11fa71b9SJerome Forissier #include "mbedtls/nist_kw.h" 69*11fa71b9SJerome Forissier #endif 70*11fa71b9SJerome Forissier 71817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 72817466cbSJens Wiklander #include "mbedtls/platform.h" 73817466cbSJens Wiklander #else 74817466cbSJens Wiklander #define mbedtls_calloc calloc 75817466cbSJens Wiklander #define mbedtls_free free 76817466cbSJens Wiklander #endif 77817466cbSJens Wiklander 783d3b0591SJens Wiklander #define CIPHER_VALIDATE_RET( cond ) \ 793d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) 803d3b0591SJens Wiklander #define CIPHER_VALIDATE( cond ) \ 813d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE( cond ) 82817466cbSJens Wiklander 833d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 843d3b0591SJens Wiklander /* Compare the contents of two buffers in constant time. 853d3b0591SJens Wiklander * Returns 0 if the contents are bitwise identical, otherwise returns 863d3b0591SJens Wiklander * a non-zero value. 873d3b0591SJens Wiklander * This is currently only used by GCM and ChaCha20+Poly1305. 883d3b0591SJens Wiklander */ 89*11fa71b9SJerome Forissier static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, 90*11fa71b9SJerome Forissier size_t len ) 913d3b0591SJens Wiklander { 923d3b0591SJens Wiklander const unsigned char *p1 = (const unsigned char*) v1; 933d3b0591SJens Wiklander const unsigned char *p2 = (const unsigned char*) v2; 943d3b0591SJens Wiklander size_t i; 953d3b0591SJens Wiklander unsigned char diff; 963d3b0591SJens Wiklander 973d3b0591SJens Wiklander for( diff = 0, i = 0; i < len; i++ ) 983d3b0591SJens Wiklander diff |= p1[i] ^ p2[i]; 993d3b0591SJens Wiklander 1003d3b0591SJens Wiklander return( (int)diff ); 101817466cbSJens Wiklander } 1023d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 103817466cbSJens Wiklander 104817466cbSJens Wiklander static int supported_init = 0; 105817466cbSJens Wiklander 106817466cbSJens Wiklander const int *mbedtls_cipher_list( void ) 107817466cbSJens Wiklander { 108817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 109817466cbSJens Wiklander int *type; 110817466cbSJens Wiklander 111817466cbSJens Wiklander if( ! supported_init ) 112817466cbSJens Wiklander { 113817466cbSJens Wiklander def = mbedtls_cipher_definitions; 114817466cbSJens Wiklander type = mbedtls_cipher_supported; 115817466cbSJens Wiklander 116817466cbSJens Wiklander while( def->type != 0 ) 117817466cbSJens Wiklander *type++ = (*def++).type; 118817466cbSJens Wiklander 119817466cbSJens Wiklander *type = 0; 120817466cbSJens Wiklander 121817466cbSJens Wiklander supported_init = 1; 122817466cbSJens Wiklander } 123817466cbSJens Wiklander 124817466cbSJens Wiklander return( mbedtls_cipher_supported ); 125817466cbSJens Wiklander } 126817466cbSJens Wiklander 127*11fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( 128*11fa71b9SJerome Forissier const mbedtls_cipher_type_t cipher_type ) 129817466cbSJens Wiklander { 130817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 131817466cbSJens Wiklander 132817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 133817466cbSJens Wiklander if( def->type == cipher_type ) 134817466cbSJens Wiklander return( def->info ); 135817466cbSJens Wiklander 136817466cbSJens Wiklander return( NULL ); 137817466cbSJens Wiklander } 138817466cbSJens Wiklander 139*11fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( 140*11fa71b9SJerome Forissier const char *cipher_name ) 141817466cbSJens Wiklander { 142817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 143817466cbSJens Wiklander 144817466cbSJens Wiklander if( NULL == cipher_name ) 145817466cbSJens Wiklander return( NULL ); 146817466cbSJens Wiklander 147817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 148817466cbSJens Wiklander if( ! strcmp( def->info->name, cipher_name ) ) 149817466cbSJens Wiklander return( def->info ); 150817466cbSJens Wiklander 151817466cbSJens Wiklander return( NULL ); 152817466cbSJens Wiklander } 153817466cbSJens Wiklander 154*11fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( 155*11fa71b9SJerome Forissier const mbedtls_cipher_id_t cipher_id, 156817466cbSJens Wiklander int key_bitlen, 157817466cbSJens Wiklander const mbedtls_cipher_mode_t mode ) 158817466cbSJens Wiklander { 159817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 160817466cbSJens Wiklander 161817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 162817466cbSJens Wiklander if( def->info->base->cipher == cipher_id && 163817466cbSJens Wiklander def->info->key_bitlen == (unsigned) key_bitlen && 164817466cbSJens Wiklander def->info->mode == mode ) 165817466cbSJens Wiklander return( def->info ); 166817466cbSJens Wiklander 167817466cbSJens Wiklander return( NULL ); 168817466cbSJens Wiklander } 169817466cbSJens Wiklander 170817466cbSJens Wiklander void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) 171817466cbSJens Wiklander { 1723d3b0591SJens Wiklander CIPHER_VALIDATE( ctx != NULL ); 173817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 174817466cbSJens Wiklander } 175817466cbSJens Wiklander 176817466cbSJens Wiklander void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) 177817466cbSJens Wiklander { 178817466cbSJens Wiklander if( ctx == NULL ) 179817466cbSJens Wiklander return; 180817466cbSJens Wiklander 181*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 182*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 183*11fa71b9SJerome Forissier { 184*11fa71b9SJerome Forissier if( ctx->cipher_ctx != NULL ) 185*11fa71b9SJerome Forissier { 186*11fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 187*11fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 188*11fa71b9SJerome Forissier 189*11fa71b9SJerome Forissier if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED ) 190*11fa71b9SJerome Forissier { 191*11fa71b9SJerome Forissier /* xxx_free() doesn't allow to return failures. */ 192*11fa71b9SJerome Forissier (void) psa_destroy_key( cipher_psa->slot ); 193*11fa71b9SJerome Forissier } 194*11fa71b9SJerome Forissier 195*11fa71b9SJerome Forissier mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) ); 196*11fa71b9SJerome Forissier mbedtls_free( cipher_psa ); 197*11fa71b9SJerome Forissier } 198*11fa71b9SJerome Forissier 199*11fa71b9SJerome Forissier mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); 200*11fa71b9SJerome Forissier return; 201*11fa71b9SJerome Forissier } 202*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 203*11fa71b9SJerome Forissier 204817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C) 205817466cbSJens Wiklander if( ctx->cmac_ctx ) 206817466cbSJens Wiklander { 2073d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx->cmac_ctx, 2083d3b0591SJens Wiklander sizeof( mbedtls_cmac_context_t ) ); 209817466cbSJens Wiklander mbedtls_free( ctx->cmac_ctx ); 210817466cbSJens Wiklander } 211817466cbSJens Wiklander #endif 212817466cbSJens Wiklander 213817466cbSJens Wiklander if( ctx->cipher_ctx ) 214817466cbSJens Wiklander ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); 215817466cbSJens Wiklander 2163d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); 217817466cbSJens Wiklander } 218817466cbSJens Wiklander 21912484fc7SEdison Ai int mbedtls_cipher_clone( mbedtls_cipher_context_t *dst, 22012484fc7SEdison Ai const mbedtls_cipher_context_t *src ) 22112484fc7SEdison Ai { 22212484fc7SEdison Ai if( dst == NULL || dst->cipher_info == NULL || 22312484fc7SEdison Ai src == NULL || src->cipher_info == NULL) 22412484fc7SEdison Ai { 22512484fc7SEdison Ai return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 22612484fc7SEdison Ai } 22712484fc7SEdison Ai 22812484fc7SEdison Ai dst->cipher_info = src->cipher_info; 22912484fc7SEdison Ai dst->key_bitlen = src->key_bitlen; 23012484fc7SEdison Ai dst->operation = src->operation; 23112484fc7SEdison Ai #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 23212484fc7SEdison Ai dst->add_padding = src->add_padding; 23312484fc7SEdison Ai dst->get_padding = src->get_padding; 23412484fc7SEdison Ai #endif 23512484fc7SEdison Ai memcpy( dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH ); 23612484fc7SEdison Ai dst->unprocessed_len = src->unprocessed_len; 23712484fc7SEdison Ai memcpy( dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH ); 23812484fc7SEdison Ai dst->iv_size = src->iv_size; 23912484fc7SEdison Ai if( dst->cipher_info->base->ctx_clone_func ) 24012484fc7SEdison Ai dst->cipher_info->base->ctx_clone_func( dst->cipher_ctx, src->cipher_ctx ); 24112484fc7SEdison Ai 24212484fc7SEdison Ai #if defined(MBEDTLS_CMAC_C) 24312484fc7SEdison Ai if( dst->cmac_ctx != NULL && src->cmac_ctx != NULL ) 24412484fc7SEdison Ai memcpy( dst->cmac_ctx, src->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); 24512484fc7SEdison Ai #endif 24612484fc7SEdison Ai return( 0 ); 24712484fc7SEdison Ai } 24812484fc7SEdison Ai 249*11fa71b9SJerome Forissier int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, 250*11fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info ) 251817466cbSJens Wiklander { 2523d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 2533d3b0591SJens Wiklander if( cipher_info == NULL ) 254817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 255817466cbSJens Wiklander 256817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 257817466cbSJens Wiklander 258817466cbSJens Wiklander if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) 259817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 260817466cbSJens Wiklander 261817466cbSJens Wiklander ctx->cipher_info = cipher_info; 262817466cbSJens Wiklander 263817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 264817466cbSJens Wiklander /* 265817466cbSJens Wiklander * Ignore possible errors caused by a cipher mode that doesn't use padding 266817466cbSJens Wiklander */ 267817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 268817466cbSJens Wiklander (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); 269817466cbSJens Wiklander #else 270817466cbSJens Wiklander (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); 271817466cbSJens Wiklander #endif 272817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 273817466cbSJens Wiklander 274817466cbSJens Wiklander return( 0 ); 275817466cbSJens Wiklander } 276817466cbSJens Wiklander 277*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 278*11fa71b9SJerome Forissier int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, 279*11fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info, 280*11fa71b9SJerome Forissier size_t taglen ) 281*11fa71b9SJerome Forissier { 282*11fa71b9SJerome Forissier psa_algorithm_t alg; 283*11fa71b9SJerome Forissier mbedtls_cipher_context_psa *cipher_psa; 284*11fa71b9SJerome Forissier 285*11fa71b9SJerome Forissier if( NULL == cipher_info || NULL == ctx ) 286*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 287*11fa71b9SJerome Forissier 288*11fa71b9SJerome Forissier /* Check that the underlying cipher mode and cipher type are 289*11fa71b9SJerome Forissier * supported by the underlying PSA Crypto implementation. */ 290*11fa71b9SJerome Forissier alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen ); 291*11fa71b9SJerome Forissier if( alg == 0 ) 292*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 293*11fa71b9SJerome Forissier if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 ) 294*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 295*11fa71b9SJerome Forissier 296*11fa71b9SJerome Forissier memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 297*11fa71b9SJerome Forissier 298*11fa71b9SJerome Forissier cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) ); 299*11fa71b9SJerome Forissier if( cipher_psa == NULL ) 300*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 301*11fa71b9SJerome Forissier cipher_psa->alg = alg; 302*11fa71b9SJerome Forissier ctx->cipher_ctx = cipher_psa; 303*11fa71b9SJerome Forissier ctx->cipher_info = cipher_info; 304*11fa71b9SJerome Forissier ctx->psa_enabled = 1; 305*11fa71b9SJerome Forissier return( 0 ); 306*11fa71b9SJerome Forissier } 307*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 308*11fa71b9SJerome Forissier 30912484fc7SEdison Ai int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) 31012484fc7SEdison Ai { 31112484fc7SEdison Ai if( NULL == cipher_info || NULL == ctx ) 31212484fc7SEdison Ai return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 31312484fc7SEdison Ai 31412484fc7SEdison Ai ctx->cipher_info = cipher_info; 31512484fc7SEdison Ai return( 0 ); 31612484fc7SEdison Ai } 31712484fc7SEdison Ai 3183d3b0591SJens Wiklander int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, 3193d3b0591SJens Wiklander const unsigned char *key, 3203d3b0591SJens Wiklander int key_bitlen, 3213d3b0591SJens Wiklander const mbedtls_operation_t operation ) 322817466cbSJens Wiklander { 3233d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 3243d3b0591SJens Wiklander CIPHER_VALIDATE_RET( key != NULL ); 3253d3b0591SJens Wiklander CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || 3263d3b0591SJens Wiklander operation == MBEDTLS_DECRYPT ); 3273d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 328817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 329817466cbSJens Wiklander 330*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 331*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 332*11fa71b9SJerome Forissier { 333*11fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 334*11fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 335*11fa71b9SJerome Forissier 336*11fa71b9SJerome Forissier size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8; 337*11fa71b9SJerome Forissier 338*11fa71b9SJerome Forissier psa_status_t status; 339*11fa71b9SJerome Forissier psa_key_type_t key_type; 340*11fa71b9SJerome Forissier psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 341*11fa71b9SJerome Forissier 342*11fa71b9SJerome Forissier /* PSA Crypto API only accepts byte-aligned keys. */ 343*11fa71b9SJerome Forissier if( key_bitlen % 8 != 0 ) 344*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 345*11fa71b9SJerome Forissier 346*11fa71b9SJerome Forissier /* Don't allow keys to be set multiple times. */ 347*11fa71b9SJerome Forissier if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET ) 348*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 349*11fa71b9SJerome Forissier 350*11fa71b9SJerome Forissier key_type = mbedtls_psa_translate_cipher_type( 351*11fa71b9SJerome Forissier ctx->cipher_info->type ); 352*11fa71b9SJerome Forissier if( key_type == 0 ) 353*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 354*11fa71b9SJerome Forissier psa_set_key_type( &attributes, key_type ); 355*11fa71b9SJerome Forissier 356*11fa71b9SJerome Forissier /* Mbed TLS' cipher layer doesn't enforce the mode of operation 357*11fa71b9SJerome Forissier * (encrypt vs. decrypt): it is possible to setup a key for encryption 358*11fa71b9SJerome Forissier * and use it for AEAD decryption. Until tests relying on this 359*11fa71b9SJerome Forissier * are changed, allow any usage in PSA. */ 360*11fa71b9SJerome Forissier psa_set_key_usage_flags( &attributes, 361*11fa71b9SJerome Forissier /* mbedtls_psa_translate_cipher_operation( operation ); */ 362*11fa71b9SJerome Forissier PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); 363*11fa71b9SJerome Forissier psa_set_key_algorithm( &attributes, cipher_psa->alg ); 364*11fa71b9SJerome Forissier 365*11fa71b9SJerome Forissier status = psa_import_key( &attributes, key, key_bytelen, 366*11fa71b9SJerome Forissier &cipher_psa->slot ); 367*11fa71b9SJerome Forissier switch( status ) 368*11fa71b9SJerome Forissier { 369*11fa71b9SJerome Forissier case PSA_SUCCESS: 370*11fa71b9SJerome Forissier break; 371*11fa71b9SJerome Forissier case PSA_ERROR_INSUFFICIENT_MEMORY: 372*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 373*11fa71b9SJerome Forissier case PSA_ERROR_NOT_SUPPORTED: 374*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 375*11fa71b9SJerome Forissier default: 376*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 377*11fa71b9SJerome Forissier } 378*11fa71b9SJerome Forissier /* Indicate that we own the key slot and need to 379*11fa71b9SJerome Forissier * destroy it in mbedtls_cipher_free(). */ 380*11fa71b9SJerome Forissier cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; 381*11fa71b9SJerome Forissier 382*11fa71b9SJerome Forissier ctx->key_bitlen = key_bitlen; 383*11fa71b9SJerome Forissier ctx->operation = operation; 384*11fa71b9SJerome Forissier return( 0 ); 385*11fa71b9SJerome Forissier } 386*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 387*11fa71b9SJerome Forissier 388817466cbSJens Wiklander if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && 389817466cbSJens Wiklander (int) ctx->cipher_info->key_bitlen != key_bitlen ) 390817466cbSJens Wiklander { 391817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 392817466cbSJens Wiklander } 393817466cbSJens Wiklander 394817466cbSJens Wiklander ctx->key_bitlen = key_bitlen; 395817466cbSJens Wiklander ctx->operation = operation; 396817466cbSJens Wiklander 397817466cbSJens Wiklander /* 3983d3b0591SJens Wiklander * For OFB, CFB and CTR mode always use the encryption key schedule 399817466cbSJens Wiklander */ 400817466cbSJens Wiklander if( MBEDTLS_ENCRYPT == operation || 401817466cbSJens Wiklander MBEDTLS_MODE_CFB == ctx->cipher_info->mode || 4023d3b0591SJens Wiklander MBEDTLS_MODE_OFB == ctx->cipher_info->mode || 403817466cbSJens Wiklander MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) 404817466cbSJens Wiklander { 4053d3b0591SJens Wiklander return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, 4063d3b0591SJens Wiklander ctx->key_bitlen ) ); 407817466cbSJens Wiklander } 408817466cbSJens Wiklander 409817466cbSJens Wiklander if( MBEDTLS_DECRYPT == operation ) 4103d3b0591SJens Wiklander return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, 4113d3b0591SJens Wiklander ctx->key_bitlen ) ); 412817466cbSJens Wiklander 413817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 414817466cbSJens Wiklander } 415817466cbSJens Wiklander 416817466cbSJens Wiklander int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, 4173d3b0591SJens Wiklander const unsigned char *iv, 4183d3b0591SJens Wiklander size_t iv_len ) 419817466cbSJens Wiklander { 420817466cbSJens Wiklander size_t actual_iv_size; 421817466cbSJens Wiklander 4223d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 4233d3b0591SJens Wiklander CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 4243d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 425817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 426*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 427*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 428*11fa71b9SJerome Forissier { 429*11fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 430*11fa71b9SJerome Forissier * operations, we currently don't make it 431*11fa71b9SJerome Forissier * accessible through the cipher layer. */ 432*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 433*11fa71b9SJerome Forissier } 434*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 435817466cbSJens Wiklander 436817466cbSJens Wiklander /* avoid buffer overflow in ctx->iv */ 437817466cbSJens Wiklander if( iv_len > MBEDTLS_MAX_IV_LENGTH ) 438817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 439817466cbSJens Wiklander 440817466cbSJens Wiklander if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) 441817466cbSJens Wiklander actual_iv_size = iv_len; 442817466cbSJens Wiklander else 443817466cbSJens Wiklander { 444817466cbSJens Wiklander actual_iv_size = ctx->cipher_info->iv_size; 445817466cbSJens Wiklander 446817466cbSJens Wiklander /* avoid reading past the end of input buffer */ 447817466cbSJens Wiklander if( actual_iv_size > iv_len ) 448817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 449817466cbSJens Wiklander } 450817466cbSJens Wiklander 4513d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C) 4523d3b0591SJens Wiklander if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) 4533d3b0591SJens Wiklander { 4543d3b0591SJens Wiklander if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, 4553d3b0591SJens Wiklander iv, 4563d3b0591SJens Wiklander 0U ) ) /* Initial counter value */ 4573d3b0591SJens Wiklander { 4583d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 4593d3b0591SJens Wiklander } 4603d3b0591SJens Wiklander } 4613d3b0591SJens Wiklander #endif 4623d3b0591SJens Wiklander 4633d3b0591SJens Wiklander if ( actual_iv_size != 0 ) 4643d3b0591SJens Wiklander { 465817466cbSJens Wiklander memcpy( ctx->iv, iv, actual_iv_size ); 466817466cbSJens Wiklander ctx->iv_size = actual_iv_size; 4673d3b0591SJens Wiklander } 468817466cbSJens Wiklander 469817466cbSJens Wiklander return( 0 ); 470817466cbSJens Wiklander } 471817466cbSJens Wiklander 472817466cbSJens Wiklander int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) 473817466cbSJens Wiklander { 4743d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 4753d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 476817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 477817466cbSJens Wiklander 478*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 479*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 480*11fa71b9SJerome Forissier { 481*11fa71b9SJerome Forissier /* We don't support resetting PSA-based 482*11fa71b9SJerome Forissier * cipher contexts, yet. */ 483*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 484*11fa71b9SJerome Forissier } 485*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 486*11fa71b9SJerome Forissier 487817466cbSJens Wiklander ctx->unprocessed_len = 0; 488817466cbSJens Wiklander 489817466cbSJens Wiklander return( 0 ); 490817466cbSJens Wiklander } 491817466cbSJens Wiklander 4923d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 493817466cbSJens Wiklander int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, 494817466cbSJens Wiklander const unsigned char *ad, size_t ad_len ) 495817466cbSJens Wiklander { 4963d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 4973d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 4983d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 499817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 500817466cbSJens Wiklander 501*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 502*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 503*11fa71b9SJerome Forissier { 504*11fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 505*11fa71b9SJerome Forissier * operations, we currently don't make it 506*11fa71b9SJerome Forissier * accessible through the cipher layer. */ 507*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 508*11fa71b9SJerome Forissier } 509*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 510*11fa71b9SJerome Forissier 5113d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 512817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 513817466cbSJens Wiklander { 5143d3b0591SJens Wiklander return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, 5153d3b0591SJens Wiklander ctx->iv, ctx->iv_size, ad, ad_len ) ); 516817466cbSJens Wiklander } 5173d3b0591SJens Wiklander #endif 5183d3b0591SJens Wiklander 5193d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 5203d3b0591SJens Wiklander if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 5213d3b0591SJens Wiklander { 5223d3b0591SJens Wiklander int result; 5233d3b0591SJens Wiklander mbedtls_chachapoly_mode_t mode; 5243d3b0591SJens Wiklander 5253d3b0591SJens Wiklander mode = ( ctx->operation == MBEDTLS_ENCRYPT ) 5263d3b0591SJens Wiklander ? MBEDTLS_CHACHAPOLY_ENCRYPT 5273d3b0591SJens Wiklander : MBEDTLS_CHACHAPOLY_DECRYPT; 5283d3b0591SJens Wiklander 5293d3b0591SJens Wiklander result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 5303d3b0591SJens Wiklander ctx->iv, 5313d3b0591SJens Wiklander mode ); 5323d3b0591SJens Wiklander if ( result != 0 ) 5333d3b0591SJens Wiklander return( result ); 5343d3b0591SJens Wiklander 5353d3b0591SJens Wiklander return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 5363d3b0591SJens Wiklander ad, ad_len ) ); 5373d3b0591SJens Wiklander } 5383d3b0591SJens Wiklander #endif 539817466cbSJens Wiklander 540817466cbSJens Wiklander return( 0 ); 541817466cbSJens Wiklander } 5423d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 543817466cbSJens Wiklander 544817466cbSJens Wiklander int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, 545817466cbSJens Wiklander size_t ilen, unsigned char *output, size_t *olen ) 546817466cbSJens Wiklander { 547*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 5483d3b0591SJens Wiklander size_t block_size; 549817466cbSJens Wiklander 5503d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 5513d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 5523d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 5533d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 5543d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 555817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 556817466cbSJens Wiklander 557*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 558*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 559*11fa71b9SJerome Forissier { 560*11fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 561*11fa71b9SJerome Forissier * operations, we currently don't make it 562*11fa71b9SJerome Forissier * accessible through the cipher layer. */ 563*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 564*11fa71b9SJerome Forissier } 565*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 566*11fa71b9SJerome Forissier 567817466cbSJens Wiklander *olen = 0; 568817466cbSJens Wiklander block_size = mbedtls_cipher_get_block_size( ctx ); 5695b25c76aSJerome Forissier if ( 0 == block_size ) 5705b25c76aSJerome Forissier { 5715b25c76aSJerome Forissier return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); 5725b25c76aSJerome Forissier } 573817466cbSJens Wiklander 574817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) 575817466cbSJens Wiklander { 576817466cbSJens Wiklander if( ilen != block_size ) 577817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 578817466cbSJens Wiklander 579817466cbSJens Wiklander *olen = ilen; 580817466cbSJens Wiklander 581817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, 582817466cbSJens Wiklander ctx->operation, input, output ) ) ) 583817466cbSJens Wiklander { 584817466cbSJens Wiklander return( ret ); 585817466cbSJens Wiklander } 586817466cbSJens Wiklander 587817466cbSJens Wiklander return( 0 ); 588817466cbSJens Wiklander } 589817466cbSJens Wiklander 590817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 591817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) 592817466cbSJens Wiklander { 593817466cbSJens Wiklander *olen = ilen; 5943d3b0591SJens Wiklander return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, 5953d3b0591SJens Wiklander output ) ); 5963d3b0591SJens Wiklander } 5973d3b0591SJens Wiklander #endif 5983d3b0591SJens Wiklander 5993d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 6003d3b0591SJens Wiklander if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) 6013d3b0591SJens Wiklander { 6023d3b0591SJens Wiklander *olen = ilen; 6033d3b0591SJens Wiklander return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 6043d3b0591SJens Wiklander ilen, input, output ) ); 605817466cbSJens Wiklander } 606817466cbSJens Wiklander #endif 607817466cbSJens Wiklander 608817466cbSJens Wiklander if( input == output && 609817466cbSJens Wiklander ( ctx->unprocessed_len != 0 || ilen % block_size ) ) 610817466cbSJens Wiklander { 611817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 612817466cbSJens Wiklander } 613817466cbSJens Wiklander 614817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC) 615817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) 616817466cbSJens Wiklander { 617817466cbSJens Wiklander size_t copy_len = 0; 618817466cbSJens Wiklander 619817466cbSJens Wiklander /* 620817466cbSJens Wiklander * If there is not enough data for a full block, cache it. 621817466cbSJens Wiklander */ 6223d3b0591SJens Wiklander if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && 623817466cbSJens Wiklander ilen <= block_size - ctx->unprocessed_len ) || 6243d3b0591SJens Wiklander ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && 6253d3b0591SJens Wiklander ilen < block_size - ctx->unprocessed_len ) || 626817466cbSJens Wiklander ( ctx->operation == MBEDTLS_ENCRYPT && 627817466cbSJens Wiklander ilen < block_size - ctx->unprocessed_len ) ) 628817466cbSJens Wiklander { 629817466cbSJens Wiklander memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, 630817466cbSJens Wiklander ilen ); 631817466cbSJens Wiklander 632817466cbSJens Wiklander ctx->unprocessed_len += ilen; 633817466cbSJens Wiklander return( 0 ); 634817466cbSJens Wiklander } 635817466cbSJens Wiklander 636817466cbSJens Wiklander /* 637817466cbSJens Wiklander * Process cached data first 638817466cbSJens Wiklander */ 639817466cbSJens Wiklander if( 0 != ctx->unprocessed_len ) 640817466cbSJens Wiklander { 641817466cbSJens Wiklander copy_len = block_size - ctx->unprocessed_len; 642817466cbSJens Wiklander 643817466cbSJens Wiklander memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, 644817466cbSJens Wiklander copy_len ); 645817466cbSJens Wiklander 646817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 647817466cbSJens Wiklander ctx->operation, block_size, ctx->iv, 648817466cbSJens Wiklander ctx->unprocessed_data, output ) ) ) 649817466cbSJens Wiklander { 650817466cbSJens Wiklander return( ret ); 651817466cbSJens Wiklander } 652817466cbSJens Wiklander 653817466cbSJens Wiklander *olen += block_size; 654817466cbSJens Wiklander output += block_size; 655817466cbSJens Wiklander ctx->unprocessed_len = 0; 656817466cbSJens Wiklander 657817466cbSJens Wiklander input += copy_len; 658817466cbSJens Wiklander ilen -= copy_len; 659817466cbSJens Wiklander } 660817466cbSJens Wiklander 661817466cbSJens Wiklander /* 662817466cbSJens Wiklander * Cache final, incomplete block 663817466cbSJens Wiklander */ 664817466cbSJens Wiklander if( 0 != ilen ) 665817466cbSJens Wiklander { 6663d3b0591SJens Wiklander /* Encryption: only cache partial blocks 6673d3b0591SJens Wiklander * Decryption w/ padding: always keep at least one whole block 6683d3b0591SJens Wiklander * Decryption w/o padding: only cache partial blocks 6693d3b0591SJens Wiklander */ 670817466cbSJens Wiklander copy_len = ilen % block_size; 6713d3b0591SJens Wiklander if( copy_len == 0 && 6723d3b0591SJens Wiklander ctx->operation == MBEDTLS_DECRYPT && 6733d3b0591SJens Wiklander NULL != ctx->add_padding) 6743d3b0591SJens Wiklander { 675817466cbSJens Wiklander copy_len = block_size; 6763d3b0591SJens Wiklander } 677817466cbSJens Wiklander 678817466cbSJens Wiklander memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), 679817466cbSJens Wiklander copy_len ); 680817466cbSJens Wiklander 681817466cbSJens Wiklander ctx->unprocessed_len += copy_len; 682817466cbSJens Wiklander ilen -= copy_len; 683817466cbSJens Wiklander } 684817466cbSJens Wiklander 685817466cbSJens Wiklander /* 686817466cbSJens Wiklander * Process remaining full blocks 687817466cbSJens Wiklander */ 688817466cbSJens Wiklander if( ilen ) 689817466cbSJens Wiklander { 690817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 691817466cbSJens Wiklander ctx->operation, ilen, ctx->iv, input, output ) ) ) 692817466cbSJens Wiklander { 693817466cbSJens Wiklander return( ret ); 694817466cbSJens Wiklander } 695817466cbSJens Wiklander 696817466cbSJens Wiklander *olen += ilen; 697817466cbSJens Wiklander } 698817466cbSJens Wiklander 699817466cbSJens Wiklander return( 0 ); 700817466cbSJens Wiklander } 701817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */ 702817466cbSJens Wiklander 703817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CFB) 704817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) 705817466cbSJens Wiklander { 706817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, 707817466cbSJens Wiklander ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, 708817466cbSJens Wiklander input, output ) ) ) 709817466cbSJens Wiklander { 710817466cbSJens Wiklander return( ret ); 711817466cbSJens Wiklander } 712817466cbSJens Wiklander 713817466cbSJens Wiklander *olen = ilen; 714817466cbSJens Wiklander 715817466cbSJens Wiklander return( 0 ); 716817466cbSJens Wiklander } 717817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CFB */ 718817466cbSJens Wiklander 7193d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_OFB) 7203d3b0591SJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) 7213d3b0591SJens Wiklander { 7223d3b0591SJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, 7233d3b0591SJens Wiklander ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) 7243d3b0591SJens Wiklander { 7253d3b0591SJens Wiklander return( ret ); 7263d3b0591SJens Wiklander } 7273d3b0591SJens Wiklander 7283d3b0591SJens Wiklander *olen = ilen; 7293d3b0591SJens Wiklander 7303d3b0591SJens Wiklander return( 0 ); 7313d3b0591SJens Wiklander } 7323d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_OFB */ 7333d3b0591SJens Wiklander 734817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CTR) 735817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) 736817466cbSJens Wiklander { 737817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, 738817466cbSJens Wiklander ilen, &ctx->unprocessed_len, ctx->iv, 739817466cbSJens Wiklander ctx->unprocessed_data, input, output ) ) ) 740817466cbSJens Wiklander { 741817466cbSJens Wiklander return( ret ); 742817466cbSJens Wiklander } 743817466cbSJens Wiklander 744817466cbSJens Wiklander *olen = ilen; 745817466cbSJens Wiklander 746817466cbSJens Wiklander return( 0 ); 747817466cbSJens Wiklander } 748817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CTR */ 749817466cbSJens Wiklander 7503d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_XTS) 7513d3b0591SJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) 7523d3b0591SJens Wiklander { 7533d3b0591SJens Wiklander if( ctx->unprocessed_len > 0 ) { 7543d3b0591SJens Wiklander /* We can only process an entire data unit at a time. */ 7553d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 7563d3b0591SJens Wiklander } 7573d3b0591SJens Wiklander 7583d3b0591SJens Wiklander ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, 7593d3b0591SJens Wiklander ctx->operation, ilen, ctx->iv, input, output ); 7603d3b0591SJens Wiklander if( ret != 0 ) 7613d3b0591SJens Wiklander { 7623d3b0591SJens Wiklander return( ret ); 7633d3b0591SJens Wiklander } 7643d3b0591SJens Wiklander 7653d3b0591SJens Wiklander *olen = ilen; 7663d3b0591SJens Wiklander 7673d3b0591SJens Wiklander return( 0 ); 7683d3b0591SJens Wiklander } 7693d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_XTS */ 7703d3b0591SJens Wiklander 771817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_STREAM) 772817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) 773817466cbSJens Wiklander { 774817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, 775817466cbSJens Wiklander ilen, input, output ) ) ) 776817466cbSJens Wiklander { 777817466cbSJens Wiklander return( ret ); 778817466cbSJens Wiklander } 779817466cbSJens Wiklander 780817466cbSJens Wiklander *olen = ilen; 781817466cbSJens Wiklander 782817466cbSJens Wiklander return( 0 ); 783817466cbSJens Wiklander } 784817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_STREAM */ 785817466cbSJens Wiklander 786817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 787817466cbSJens Wiklander } 788817466cbSJens Wiklander 789817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 790817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 791817466cbSJens Wiklander /* 792817466cbSJens Wiklander * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len 793817466cbSJens Wiklander */ 794817466cbSJens Wiklander static void add_pkcs_padding( unsigned char *output, size_t output_len, 795817466cbSJens Wiklander size_t data_len ) 796817466cbSJens Wiklander { 797817466cbSJens Wiklander size_t padding_len = output_len - data_len; 798817466cbSJens Wiklander unsigned char i; 799817466cbSJens Wiklander 800817466cbSJens Wiklander for( i = 0; i < padding_len; i++ ) 801817466cbSJens Wiklander output[data_len + i] = (unsigned char) padding_len; 802817466cbSJens Wiklander } 803817466cbSJens Wiklander 804817466cbSJens Wiklander static int get_pkcs_padding( unsigned char *input, size_t input_len, 805817466cbSJens Wiklander size_t *data_len ) 806817466cbSJens Wiklander { 807817466cbSJens Wiklander size_t i, pad_idx; 808817466cbSJens Wiklander unsigned char padding_len, bad = 0; 809817466cbSJens Wiklander 810817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 811817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 812817466cbSJens Wiklander 813817466cbSJens Wiklander padding_len = input[input_len - 1]; 814817466cbSJens Wiklander *data_len = input_len - padding_len; 815817466cbSJens Wiklander 816817466cbSJens Wiklander /* Avoid logical || since it results in a branch */ 817817466cbSJens Wiklander bad |= padding_len > input_len; 818817466cbSJens Wiklander bad |= padding_len == 0; 819817466cbSJens Wiklander 820817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len, 821817466cbSJens Wiklander * so pick input_len, which is usually 8 or 16 (one block) */ 822817466cbSJens Wiklander pad_idx = input_len - padding_len; 823817466cbSJens Wiklander for( i = 0; i < input_len; i++ ) 824817466cbSJens Wiklander bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); 825817466cbSJens Wiklander 826817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 827817466cbSJens Wiklander } 828817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ 829817466cbSJens Wiklander 830817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) 831817466cbSJens Wiklander /* 832817466cbSJens Wiklander * One and zeros padding: fill with 80 00 ... 00 833817466cbSJens Wiklander */ 834817466cbSJens Wiklander static void add_one_and_zeros_padding( unsigned char *output, 835817466cbSJens Wiklander size_t output_len, size_t data_len ) 836817466cbSJens Wiklander { 837817466cbSJens Wiklander size_t padding_len = output_len - data_len; 838817466cbSJens Wiklander unsigned char i = 0; 839817466cbSJens Wiklander 840817466cbSJens Wiklander output[data_len] = 0x80; 841817466cbSJens Wiklander for( i = 1; i < padding_len; i++ ) 842817466cbSJens Wiklander output[data_len + i] = 0x00; 843817466cbSJens Wiklander } 844817466cbSJens Wiklander 845817466cbSJens Wiklander static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, 846817466cbSJens Wiklander size_t *data_len ) 847817466cbSJens Wiklander { 848817466cbSJens Wiklander size_t i; 849817466cbSJens Wiklander unsigned char done = 0, prev_done, bad; 850817466cbSJens Wiklander 851817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 852817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 853817466cbSJens Wiklander 8543d3b0591SJens Wiklander bad = 0x80; 855817466cbSJens Wiklander *data_len = 0; 856817466cbSJens Wiklander for( i = input_len; i > 0; i-- ) 857817466cbSJens Wiklander { 858817466cbSJens Wiklander prev_done = done; 859817466cbSJens Wiklander done |= ( input[i - 1] != 0 ); 860817466cbSJens Wiklander *data_len |= ( i - 1 ) * ( done != prev_done ); 8613d3b0591SJens Wiklander bad ^= input[i - 1] * ( done != prev_done ); 862817466cbSJens Wiklander } 863817466cbSJens Wiklander 864817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 865817466cbSJens Wiklander 866817466cbSJens Wiklander } 867817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ 868817466cbSJens Wiklander 869817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) 870817466cbSJens Wiklander /* 871817466cbSJens Wiklander * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length 872817466cbSJens Wiklander */ 873817466cbSJens Wiklander static void add_zeros_and_len_padding( unsigned char *output, 874817466cbSJens Wiklander size_t output_len, size_t data_len ) 875817466cbSJens Wiklander { 876817466cbSJens Wiklander size_t padding_len = output_len - data_len; 877817466cbSJens Wiklander unsigned char i = 0; 878817466cbSJens Wiklander 879817466cbSJens Wiklander for( i = 1; i < padding_len; i++ ) 880817466cbSJens Wiklander output[data_len + i - 1] = 0x00; 881817466cbSJens Wiklander output[output_len - 1] = (unsigned char) padding_len; 882817466cbSJens Wiklander } 883817466cbSJens Wiklander 884817466cbSJens Wiklander static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, 885817466cbSJens Wiklander size_t *data_len ) 886817466cbSJens Wiklander { 887817466cbSJens Wiklander size_t i, pad_idx; 888817466cbSJens Wiklander unsigned char padding_len, bad = 0; 889817466cbSJens Wiklander 890817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 891817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 892817466cbSJens Wiklander 893817466cbSJens Wiklander padding_len = input[input_len - 1]; 894817466cbSJens Wiklander *data_len = input_len - padding_len; 895817466cbSJens Wiklander 896817466cbSJens Wiklander /* Avoid logical || since it results in a branch */ 897817466cbSJens Wiklander bad |= padding_len > input_len; 898817466cbSJens Wiklander bad |= padding_len == 0; 899817466cbSJens Wiklander 900817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len */ 901817466cbSJens Wiklander pad_idx = input_len - padding_len; 902817466cbSJens Wiklander for( i = 0; i < input_len - 1; i++ ) 903817466cbSJens Wiklander bad |= input[i] * ( i >= pad_idx ); 904817466cbSJens Wiklander 905817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 906817466cbSJens Wiklander } 907817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ 908817466cbSJens Wiklander 909817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) 910817466cbSJens Wiklander /* 911817466cbSJens Wiklander * Zero padding: fill with 00 ... 00 912817466cbSJens Wiklander */ 913817466cbSJens Wiklander static void add_zeros_padding( unsigned char *output, 914817466cbSJens Wiklander size_t output_len, size_t data_len ) 915817466cbSJens Wiklander { 916817466cbSJens Wiklander size_t i; 917817466cbSJens Wiklander 918817466cbSJens Wiklander for( i = data_len; i < output_len; i++ ) 919817466cbSJens Wiklander output[i] = 0x00; 920817466cbSJens Wiklander } 921817466cbSJens Wiklander 922817466cbSJens Wiklander static int get_zeros_padding( unsigned char *input, size_t input_len, 923817466cbSJens Wiklander size_t *data_len ) 924817466cbSJens Wiklander { 925817466cbSJens Wiklander size_t i; 926817466cbSJens Wiklander unsigned char done = 0, prev_done; 927817466cbSJens Wiklander 928817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 929817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 930817466cbSJens Wiklander 931817466cbSJens Wiklander *data_len = 0; 932817466cbSJens Wiklander for( i = input_len; i > 0; i-- ) 933817466cbSJens Wiklander { 934817466cbSJens Wiklander prev_done = done; 935817466cbSJens Wiklander done |= ( input[i-1] != 0 ); 936817466cbSJens Wiklander *data_len |= i * ( done != prev_done ); 937817466cbSJens Wiklander } 938817466cbSJens Wiklander 939817466cbSJens Wiklander return( 0 ); 940817466cbSJens Wiklander } 941817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ 942817466cbSJens Wiklander 943817466cbSJens Wiklander /* 944817466cbSJens Wiklander * No padding: don't pad :) 945817466cbSJens Wiklander * 946817466cbSJens Wiklander * There is no add_padding function (check for NULL in mbedtls_cipher_finish) 947817466cbSJens Wiklander * but a trivial get_padding function 948817466cbSJens Wiklander */ 949817466cbSJens Wiklander static int get_no_padding( unsigned char *input, size_t input_len, 950817466cbSJens Wiklander size_t *data_len ) 951817466cbSJens Wiklander { 952817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 953817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 954817466cbSJens Wiklander 955817466cbSJens Wiklander *data_len = input_len; 956817466cbSJens Wiklander 957817466cbSJens Wiklander return( 0 ); 958817466cbSJens Wiklander } 959817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 960817466cbSJens Wiklander 961817466cbSJens Wiklander int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, 962817466cbSJens Wiklander unsigned char *output, size_t *olen ) 963817466cbSJens Wiklander { 9643d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 9653d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 9663d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 9673d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 968817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 969817466cbSJens Wiklander 970*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 971*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 972*11fa71b9SJerome Forissier { 973*11fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 974*11fa71b9SJerome Forissier * operations, we currently don't make it 975*11fa71b9SJerome Forissier * accessible through the cipher layer. */ 976*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 977*11fa71b9SJerome Forissier } 978*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 979*11fa71b9SJerome Forissier 980817466cbSJens Wiklander *olen = 0; 981817466cbSJens Wiklander 982817466cbSJens Wiklander if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || 9833d3b0591SJens Wiklander MBEDTLS_MODE_OFB == ctx->cipher_info->mode || 984817466cbSJens Wiklander MBEDTLS_MODE_CTR == ctx->cipher_info->mode || 985817466cbSJens Wiklander MBEDTLS_MODE_GCM == ctx->cipher_info->mode || 9863d3b0591SJens Wiklander MBEDTLS_MODE_XTS == ctx->cipher_info->mode || 987817466cbSJens Wiklander MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) 988817466cbSJens Wiklander { 989817466cbSJens Wiklander return( 0 ); 990817466cbSJens Wiklander } 991817466cbSJens Wiklander 9923d3b0591SJens Wiklander if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || 9933d3b0591SJens Wiklander ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) 9943d3b0591SJens Wiklander { 9953d3b0591SJens Wiklander return( 0 ); 9963d3b0591SJens Wiklander } 9973d3b0591SJens Wiklander 998817466cbSJens Wiklander if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) 999817466cbSJens Wiklander { 1000817466cbSJens Wiklander if( ctx->unprocessed_len != 0 ) 1001817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 1002817466cbSJens Wiklander 1003817466cbSJens Wiklander return( 0 ); 1004817466cbSJens Wiklander } 1005817466cbSJens Wiklander 1006817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC) 1007817466cbSJens Wiklander if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) 1008817466cbSJens Wiklander { 1009817466cbSJens Wiklander int ret = 0; 1010817466cbSJens Wiklander 1011817466cbSJens Wiklander if( MBEDTLS_ENCRYPT == ctx->operation ) 1012817466cbSJens Wiklander { 1013817466cbSJens Wiklander /* check for 'no padding' mode */ 1014817466cbSJens Wiklander if( NULL == ctx->add_padding ) 1015817466cbSJens Wiklander { 1016817466cbSJens Wiklander if( 0 != ctx->unprocessed_len ) 1017817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 1018817466cbSJens Wiklander 1019817466cbSJens Wiklander return( 0 ); 1020817466cbSJens Wiklander } 1021817466cbSJens Wiklander 1022817466cbSJens Wiklander ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), 1023817466cbSJens Wiklander ctx->unprocessed_len ); 1024817466cbSJens Wiklander } 1025817466cbSJens Wiklander else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) 1026817466cbSJens Wiklander { 1027817466cbSJens Wiklander /* 1028817466cbSJens Wiklander * For decrypt operations, expect a full block, 1029817466cbSJens Wiklander * or an empty block if no padding 1030817466cbSJens Wiklander */ 1031817466cbSJens Wiklander if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) 1032817466cbSJens Wiklander return( 0 ); 1033817466cbSJens Wiklander 1034817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 1035817466cbSJens Wiklander } 1036817466cbSJens Wiklander 1037817466cbSJens Wiklander /* cipher block */ 1038817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 1039817466cbSJens Wiklander ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, 1040817466cbSJens Wiklander ctx->unprocessed_data, output ) ) ) 1041817466cbSJens Wiklander { 1042817466cbSJens Wiklander return( ret ); 1043817466cbSJens Wiklander } 1044817466cbSJens Wiklander 1045817466cbSJens Wiklander /* Set output size for decryption */ 1046817466cbSJens Wiklander if( MBEDTLS_DECRYPT == ctx->operation ) 10473d3b0591SJens Wiklander return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), 10483d3b0591SJens Wiklander olen ) ); 1049817466cbSJens Wiklander 1050817466cbSJens Wiklander /* Set output size for encryption */ 1051817466cbSJens Wiklander *olen = mbedtls_cipher_get_block_size( ctx ); 1052817466cbSJens Wiklander return( 0 ); 1053817466cbSJens Wiklander } 1054817466cbSJens Wiklander #else 1055817466cbSJens Wiklander ((void) output); 1056817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */ 1057817466cbSJens Wiklander 1058817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1059817466cbSJens Wiklander } 1060817466cbSJens Wiklander 1061817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 10623d3b0591SJens Wiklander int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, 10633d3b0591SJens Wiklander mbedtls_cipher_padding_t mode ) 1064817466cbSJens Wiklander { 10653d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 10663d3b0591SJens Wiklander 10673d3b0591SJens Wiklander if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) 1068817466cbSJens Wiklander { 1069817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1070817466cbSJens Wiklander } 1071817466cbSJens Wiklander 1072*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1073*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 1074*11fa71b9SJerome Forissier { 1075*11fa71b9SJerome Forissier /* While PSA Crypto knows about CBC padding 1076*11fa71b9SJerome Forissier * schemes, we currently don't make them 1077*11fa71b9SJerome Forissier * accessible through the cipher layer. */ 1078*11fa71b9SJerome Forissier if( mode != MBEDTLS_PADDING_NONE ) 1079*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1080*11fa71b9SJerome Forissier 1081*11fa71b9SJerome Forissier return( 0 ); 1082*11fa71b9SJerome Forissier } 1083*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 1084*11fa71b9SJerome Forissier 1085817466cbSJens Wiklander switch( mode ) 1086817466cbSJens Wiklander { 1087817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 1088817466cbSJens Wiklander case MBEDTLS_PADDING_PKCS7: 1089817466cbSJens Wiklander ctx->add_padding = add_pkcs_padding; 1090817466cbSJens Wiklander ctx->get_padding = get_pkcs_padding; 1091817466cbSJens Wiklander break; 1092817466cbSJens Wiklander #endif 1093817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) 1094817466cbSJens Wiklander case MBEDTLS_PADDING_ONE_AND_ZEROS: 1095817466cbSJens Wiklander ctx->add_padding = add_one_and_zeros_padding; 1096817466cbSJens Wiklander ctx->get_padding = get_one_and_zeros_padding; 1097817466cbSJens Wiklander break; 1098817466cbSJens Wiklander #endif 1099817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) 1100817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS_AND_LEN: 1101817466cbSJens Wiklander ctx->add_padding = add_zeros_and_len_padding; 1102817466cbSJens Wiklander ctx->get_padding = get_zeros_and_len_padding; 1103817466cbSJens Wiklander break; 1104817466cbSJens Wiklander #endif 1105817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) 1106817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS: 1107817466cbSJens Wiklander ctx->add_padding = add_zeros_padding; 1108817466cbSJens Wiklander ctx->get_padding = get_zeros_padding; 1109817466cbSJens Wiklander break; 1110817466cbSJens Wiklander #endif 1111817466cbSJens Wiklander case MBEDTLS_PADDING_NONE: 1112817466cbSJens Wiklander ctx->add_padding = NULL; 1113817466cbSJens Wiklander ctx->get_padding = get_no_padding; 1114817466cbSJens Wiklander break; 1115817466cbSJens Wiklander 1116817466cbSJens Wiklander default: 1117817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1118817466cbSJens Wiklander } 1119817466cbSJens Wiklander 1120817466cbSJens Wiklander return( 0 ); 1121817466cbSJens Wiklander } 1122817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 1123817466cbSJens Wiklander 11243d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 1125817466cbSJens Wiklander int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, 1126817466cbSJens Wiklander unsigned char *tag, size_t tag_len ) 1127817466cbSJens Wiklander { 11283d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 11293d3b0591SJens Wiklander CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 11303d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 1131817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1132817466cbSJens Wiklander 1133817466cbSJens Wiklander if( MBEDTLS_ENCRYPT != ctx->operation ) 1134817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1135817466cbSJens Wiklander 1136*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1137*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 1138*11fa71b9SJerome Forissier { 1139*11fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 1140*11fa71b9SJerome Forissier * operations, we currently don't make it 1141*11fa71b9SJerome Forissier * accessible through the cipher layer. */ 1142*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1143*11fa71b9SJerome Forissier } 1144*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 1145*11fa71b9SJerome Forissier 11463d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 1147817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 11483d3b0591SJens Wiklander return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, 11493d3b0591SJens Wiklander tag, tag_len ) ); 11503d3b0591SJens Wiklander #endif 11513d3b0591SJens Wiklander 11523d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 11533d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 11543d3b0591SJens Wiklander { 11553d3b0591SJens Wiklander /* Don't allow truncated MAC for Poly1305 */ 11563d3b0591SJens Wiklander if ( tag_len != 16U ) 11573d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 11583d3b0591SJens Wiklander 1159*11fa71b9SJerome Forissier return( mbedtls_chachapoly_finish( 1160*11fa71b9SJerome Forissier (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) ); 11613d3b0591SJens Wiklander } 11623d3b0591SJens Wiklander #endif 1163817466cbSJens Wiklander 1164817466cbSJens Wiklander return( 0 ); 1165817466cbSJens Wiklander } 1166817466cbSJens Wiklander 1167817466cbSJens Wiklander int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, 1168817466cbSJens Wiklander const unsigned char *tag, size_t tag_len ) 1169817466cbSJens Wiklander { 11703d3b0591SJens Wiklander unsigned char check_tag[16]; 1171*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1172817466cbSJens Wiklander 11733d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 11743d3b0591SJens Wiklander CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 11753d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 11763d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 11773d3b0591SJens Wiklander 11783d3b0591SJens Wiklander if( MBEDTLS_DECRYPT != ctx->operation ) 1179817466cbSJens Wiklander { 1180817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1181817466cbSJens Wiklander } 1182817466cbSJens Wiklander 1183*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1184*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 1185*11fa71b9SJerome Forissier { 1186*11fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 1187*11fa71b9SJerome Forissier * operations, we currently don't make it 1188*11fa71b9SJerome Forissier * accessible through the cipher layer. */ 1189*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1190*11fa71b9SJerome Forissier } 1191*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 1192*11fa71b9SJerome Forissier 11933d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 1194817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1195817466cbSJens Wiklander { 1196817466cbSJens Wiklander if( tag_len > sizeof( check_tag ) ) 1197817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1198817466cbSJens Wiklander 1199*11fa71b9SJerome Forissier if( 0 != ( ret = mbedtls_gcm_finish( 1200*11fa71b9SJerome Forissier (mbedtls_gcm_context *) ctx->cipher_ctx, 1201817466cbSJens Wiklander check_tag, tag_len ) ) ) 1202817466cbSJens Wiklander { 1203817466cbSJens Wiklander return( ret ); 1204817466cbSJens Wiklander } 1205817466cbSJens Wiklander 1206817466cbSJens Wiklander /* Check the tag in "constant-time" */ 12073d3b0591SJens Wiklander if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) 1208817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); 1209817466cbSJens Wiklander 1210817466cbSJens Wiklander return( 0 ); 1211817466cbSJens Wiklander } 12123d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C */ 12133d3b0591SJens Wiklander 12143d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 12153d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 12163d3b0591SJens Wiklander { 12173d3b0591SJens Wiklander /* Don't allow truncated MAC for Poly1305 */ 12183d3b0591SJens Wiklander if ( tag_len != sizeof( check_tag ) ) 12193d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 12203d3b0591SJens Wiklander 1221*11fa71b9SJerome Forissier ret = mbedtls_chachapoly_finish( 1222*11fa71b9SJerome Forissier (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag ); 12233d3b0591SJens Wiklander if ( ret != 0 ) 12243d3b0591SJens Wiklander { 12253d3b0591SJens Wiklander return( ret ); 12263d3b0591SJens Wiklander } 12273d3b0591SJens Wiklander 12283d3b0591SJens Wiklander /* Check the tag in "constant-time" */ 12293d3b0591SJens Wiklander if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) 12303d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); 1231817466cbSJens Wiklander 1232817466cbSJens Wiklander return( 0 ); 1233817466cbSJens Wiklander } 12343d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 12353d3b0591SJens Wiklander 12363d3b0591SJens Wiklander return( 0 ); 12373d3b0591SJens Wiklander } 12383d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 1239817466cbSJens Wiklander 1240817466cbSJens Wiklander /* 1241817466cbSJens Wiklander * Packet-oriented wrapper for non-AEAD modes 1242817466cbSJens Wiklander */ 1243817466cbSJens Wiklander int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, 1244817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1245817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1246817466cbSJens Wiklander unsigned char *output, size_t *olen ) 1247817466cbSJens Wiklander { 1248*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1249817466cbSJens Wiklander size_t finish_olen; 1250817466cbSJens Wiklander 12513d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 12523d3b0591SJens Wiklander CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 12533d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 12543d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 12553d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 12563d3b0591SJens Wiklander 1257*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1258*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 1259*11fa71b9SJerome Forissier { 1260*11fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 1261*11fa71b9SJerome Forissier * a key has been set. If not, the key slot will 1262*11fa71b9SJerome Forissier * still be in its default state of 0, which is 1263*11fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 1264*11fa71b9SJerome Forissier * below will gracefully fail. */ 1265*11fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 1266*11fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 1267*11fa71b9SJerome Forissier 1268*11fa71b9SJerome Forissier psa_status_t status; 1269*11fa71b9SJerome Forissier psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; 1270*11fa71b9SJerome Forissier size_t part_len; 1271*11fa71b9SJerome Forissier 1272*11fa71b9SJerome Forissier if( ctx->operation == MBEDTLS_DECRYPT ) 1273*11fa71b9SJerome Forissier { 1274*11fa71b9SJerome Forissier status = psa_cipher_decrypt_setup( &cipher_op, 1275*11fa71b9SJerome Forissier cipher_psa->slot, 1276*11fa71b9SJerome Forissier cipher_psa->alg ); 1277*11fa71b9SJerome Forissier } 1278*11fa71b9SJerome Forissier else if( ctx->operation == MBEDTLS_ENCRYPT ) 1279*11fa71b9SJerome Forissier { 1280*11fa71b9SJerome Forissier status = psa_cipher_encrypt_setup( &cipher_op, 1281*11fa71b9SJerome Forissier cipher_psa->slot, 1282*11fa71b9SJerome Forissier cipher_psa->alg ); 1283*11fa71b9SJerome Forissier } 1284*11fa71b9SJerome Forissier else 1285*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1286*11fa71b9SJerome Forissier 1287*11fa71b9SJerome Forissier /* In the following, we can immediately return on an error, 1288*11fa71b9SJerome Forissier * because the PSA Crypto API guarantees that cipher operations 1289*11fa71b9SJerome Forissier * are terminated by unsuccessful calls to psa_cipher_update(), 1290*11fa71b9SJerome Forissier * and by any call to psa_cipher_finish(). */ 1291*11fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 1292*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 1293*11fa71b9SJerome Forissier 1294*11fa71b9SJerome Forissier status = psa_cipher_set_iv( &cipher_op, iv, iv_len ); 1295*11fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 1296*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 1297*11fa71b9SJerome Forissier 1298*11fa71b9SJerome Forissier status = psa_cipher_update( &cipher_op, 1299*11fa71b9SJerome Forissier input, ilen, 1300*11fa71b9SJerome Forissier output, ilen, olen ); 1301*11fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 1302*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 1303*11fa71b9SJerome Forissier 1304*11fa71b9SJerome Forissier status = psa_cipher_finish( &cipher_op, 1305*11fa71b9SJerome Forissier output + *olen, ilen - *olen, 1306*11fa71b9SJerome Forissier &part_len ); 1307*11fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 1308*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 1309*11fa71b9SJerome Forissier 1310*11fa71b9SJerome Forissier *olen += part_len; 1311*11fa71b9SJerome Forissier return( 0 ); 1312*11fa71b9SJerome Forissier } 1313*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 1314*11fa71b9SJerome Forissier 1315817466cbSJens Wiklander if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) 1316817466cbSJens Wiklander return( ret ); 1317817466cbSJens Wiklander 1318817466cbSJens Wiklander if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) 1319817466cbSJens Wiklander return( ret ); 1320817466cbSJens Wiklander 1321*11fa71b9SJerome Forissier if( ( ret = mbedtls_cipher_update( ctx, input, ilen, 1322*11fa71b9SJerome Forissier output, olen ) ) != 0 ) 1323817466cbSJens Wiklander return( ret ); 1324817466cbSJens Wiklander 1325*11fa71b9SJerome Forissier if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, 1326*11fa71b9SJerome Forissier &finish_olen ) ) != 0 ) 1327817466cbSJens Wiklander return( ret ); 1328817466cbSJens Wiklander 1329817466cbSJens Wiklander *olen += finish_olen; 1330817466cbSJens Wiklander 1331817466cbSJens Wiklander return( 0 ); 1332817466cbSJens Wiklander } 1333817466cbSJens Wiklander 1334817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_AEAD) 1335817466cbSJens Wiklander /* 1336817466cbSJens Wiklander * Packet-oriented encryption for AEAD modes 1337817466cbSJens Wiklander */ 1338817466cbSJens Wiklander int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, 1339817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1340817466cbSJens Wiklander const unsigned char *ad, size_t ad_len, 1341817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1342817466cbSJens Wiklander unsigned char *output, size_t *olen, 1343817466cbSJens Wiklander unsigned char *tag, size_t tag_len ) 1344817466cbSJens Wiklander { 13453d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 13463d3b0591SJens Wiklander CIPHER_VALIDATE_RET( iv != NULL ); 13473d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 13483d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 13493d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 13503d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 13513d3b0591SJens Wiklander CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 13523d3b0591SJens Wiklander 1353*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1354*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 1355*11fa71b9SJerome Forissier { 1356*11fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 1357*11fa71b9SJerome Forissier * a key has been set. If not, the key slot will 1358*11fa71b9SJerome Forissier * still be in its default state of 0, which is 1359*11fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 1360*11fa71b9SJerome Forissier * below will gracefully fail. */ 1361*11fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 1362*11fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 1363*11fa71b9SJerome Forissier 1364*11fa71b9SJerome Forissier psa_status_t status; 1365*11fa71b9SJerome Forissier 1366*11fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag 1367*11fa71b9SJerome Forissier * at the end of the encrypted message. */ 1368*11fa71b9SJerome Forissier if( tag != output + ilen ) 1369*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1370*11fa71b9SJerome Forissier 1371*11fa71b9SJerome Forissier status = psa_aead_encrypt( cipher_psa->slot, 1372*11fa71b9SJerome Forissier cipher_psa->alg, 1373*11fa71b9SJerome Forissier iv, iv_len, 1374*11fa71b9SJerome Forissier ad, ad_len, 1375*11fa71b9SJerome Forissier input, ilen, 1376*11fa71b9SJerome Forissier output, ilen + tag_len, olen ); 1377*11fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 1378*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 1379*11fa71b9SJerome Forissier 1380*11fa71b9SJerome Forissier *olen -= tag_len; 1381*11fa71b9SJerome Forissier return( 0 ); 1382*11fa71b9SJerome Forissier } 1383*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 1384*11fa71b9SJerome Forissier 1385817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 1386817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1387817466cbSJens Wiklander { 1388817466cbSJens Wiklander *olen = ilen; 1389*11fa71b9SJerome Forissier return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, 1390*11fa71b9SJerome Forissier ilen, iv, iv_len, ad, ad_len, 1391*11fa71b9SJerome Forissier input, output, tag_len, tag ) ); 1392817466cbSJens Wiklander } 1393817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1394817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 1395817466cbSJens Wiklander if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) 1396817466cbSJens Wiklander { 1397817466cbSJens Wiklander *olen = ilen; 1398817466cbSJens Wiklander return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, 1399817466cbSJens Wiklander iv, iv_len, ad, ad_len, input, output, 1400817466cbSJens Wiklander tag, tag_len ) ); 1401817466cbSJens Wiklander } 1402817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */ 14033d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 14043d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 14053d3b0591SJens Wiklander { 14063d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */ 14073d3b0591SJens Wiklander if ( ( iv_len != ctx->cipher_info->iv_size ) || 14083d3b0591SJens Wiklander ( tag_len != 16U ) ) 14093d3b0591SJens Wiklander { 14103d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 14113d3b0591SJens Wiklander } 14123d3b0591SJens Wiklander 14133d3b0591SJens Wiklander *olen = ilen; 14143d3b0591SJens Wiklander return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, 14153d3b0591SJens Wiklander ilen, iv, ad, ad_len, input, output, tag ) ); 14163d3b0591SJens Wiklander } 14173d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 1418*11fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 1419*11fa71b9SJerome Forissier if( MBEDTLS_MODE_KW == ctx->cipher_info->mode || 1420*11fa71b9SJerome Forissier MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) 1421*11fa71b9SJerome Forissier { 1422*11fa71b9SJerome Forissier mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? 1423*11fa71b9SJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; 1424*11fa71b9SJerome Forissier 1425*11fa71b9SJerome Forissier /* There is no iv, tag or ad associated with KW and KWP, these length should be 0 */ 1426*11fa71b9SJerome Forissier if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) 1427*11fa71b9SJerome Forissier { 1428*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1429*11fa71b9SJerome Forissier } 1430*11fa71b9SJerome Forissier 1431*11fa71b9SJerome Forissier return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen, output, olen, SIZE_MAX ) ); 1432*11fa71b9SJerome Forissier } 1433*11fa71b9SJerome Forissier #endif /* MBEDTLS_NIST_KW_C */ 1434817466cbSJens Wiklander 1435817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1436817466cbSJens Wiklander } 1437817466cbSJens Wiklander 1438817466cbSJens Wiklander /* 1439817466cbSJens Wiklander * Packet-oriented decryption for AEAD modes 1440817466cbSJens Wiklander */ 1441817466cbSJens Wiklander int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, 1442817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1443817466cbSJens Wiklander const unsigned char *ad, size_t ad_len, 1444817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1445817466cbSJens Wiklander unsigned char *output, size_t *olen, 1446817466cbSJens Wiklander const unsigned char *tag, size_t tag_len ) 1447817466cbSJens Wiklander { 14483d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 14493d3b0591SJens Wiklander CIPHER_VALIDATE_RET( iv != NULL ); 14503d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 14513d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 14523d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 14533d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 14543d3b0591SJens Wiklander CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 14553d3b0591SJens Wiklander 1456*11fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1457*11fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 1458*11fa71b9SJerome Forissier { 1459*11fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 1460*11fa71b9SJerome Forissier * a key has been set. If not, the key slot will 1461*11fa71b9SJerome Forissier * still be in its default state of 0, which is 1462*11fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 1463*11fa71b9SJerome Forissier * below will gracefully fail. */ 1464*11fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 1465*11fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 1466*11fa71b9SJerome Forissier 1467*11fa71b9SJerome Forissier psa_status_t status; 1468*11fa71b9SJerome Forissier 1469*11fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag 1470*11fa71b9SJerome Forissier * at the end of the encrypted message. */ 1471*11fa71b9SJerome Forissier if( tag != input + ilen ) 1472*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1473*11fa71b9SJerome Forissier 1474*11fa71b9SJerome Forissier status = psa_aead_decrypt( cipher_psa->slot, 1475*11fa71b9SJerome Forissier cipher_psa->alg, 1476*11fa71b9SJerome Forissier iv, iv_len, 1477*11fa71b9SJerome Forissier ad, ad_len, 1478*11fa71b9SJerome Forissier input, ilen + tag_len, 1479*11fa71b9SJerome Forissier output, ilen, olen ); 1480*11fa71b9SJerome Forissier if( status == PSA_ERROR_INVALID_SIGNATURE ) 1481*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); 1482*11fa71b9SJerome Forissier else if( status != PSA_SUCCESS ) 1483*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 1484*11fa71b9SJerome Forissier 1485*11fa71b9SJerome Forissier return( 0 ); 1486*11fa71b9SJerome Forissier } 1487*11fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 1488*11fa71b9SJerome Forissier 1489817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 1490817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1491817466cbSJens Wiklander { 1492*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1493817466cbSJens Wiklander 1494817466cbSJens Wiklander *olen = ilen; 1495817466cbSJens Wiklander ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, 1496817466cbSJens Wiklander iv, iv_len, ad, ad_len, 1497817466cbSJens Wiklander tag, tag_len, input, output ); 1498817466cbSJens Wiklander 1499817466cbSJens Wiklander if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) 1500817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1501817466cbSJens Wiklander 1502817466cbSJens Wiklander return( ret ); 1503817466cbSJens Wiklander } 1504817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1505817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 1506817466cbSJens Wiklander if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) 1507817466cbSJens Wiklander { 1508*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1509817466cbSJens Wiklander 1510817466cbSJens Wiklander *olen = ilen; 1511817466cbSJens Wiklander ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, 1512817466cbSJens Wiklander iv, iv_len, ad, ad_len, 1513817466cbSJens Wiklander input, output, tag, tag_len ); 1514817466cbSJens Wiklander 1515817466cbSJens Wiklander if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) 1516817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1517817466cbSJens Wiklander 1518817466cbSJens Wiklander return( ret ); 1519817466cbSJens Wiklander } 1520817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */ 15213d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 15223d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 15233d3b0591SJens Wiklander { 1524*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 15253d3b0591SJens Wiklander 15263d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */ 15273d3b0591SJens Wiklander if ( ( iv_len != ctx->cipher_info->iv_size ) || 15283d3b0591SJens Wiklander ( tag_len != 16U ) ) 15293d3b0591SJens Wiklander { 15303d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 15313d3b0591SJens Wiklander } 15323d3b0591SJens Wiklander 15333d3b0591SJens Wiklander *olen = ilen; 15343d3b0591SJens Wiklander ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, 15353d3b0591SJens Wiklander iv, ad, ad_len, tag, input, output ); 15363d3b0591SJens Wiklander 15373d3b0591SJens Wiklander if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) 15383d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 15393d3b0591SJens Wiklander 15403d3b0591SJens Wiklander return( ret ); 15413d3b0591SJens Wiklander } 15423d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 1543*11fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 1544*11fa71b9SJerome Forissier if( MBEDTLS_MODE_KW == ctx->cipher_info->mode || 1545*11fa71b9SJerome Forissier MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) 1546*11fa71b9SJerome Forissier { 1547*11fa71b9SJerome Forissier mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? 1548*11fa71b9SJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; 1549*11fa71b9SJerome Forissier 1550*11fa71b9SJerome Forissier /* There is no iv, tag or ad associated with KW and KWP, these length should be 0 */ 1551*11fa71b9SJerome Forissier if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) 1552*11fa71b9SJerome Forissier { 1553*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1554*11fa71b9SJerome Forissier } 1555*11fa71b9SJerome Forissier 1556*11fa71b9SJerome Forissier return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen, output, olen, SIZE_MAX ) ); 1557*11fa71b9SJerome Forissier } 1558*11fa71b9SJerome Forissier #endif /* MBEDTLS_NIST_KW_C */ 1559817466cbSJens Wiklander 1560817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1561817466cbSJens Wiklander } 1562817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 1563817466cbSJens Wiklander 1564817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_C */ 1565