1817466cbSJens Wiklander /** 2817466cbSJens Wiklander * \file cipher.c 3817466cbSJens Wiklander * 4817466cbSJens Wiklander * \brief Generic cipher wrapper for mbed TLS 5817466cbSJens Wiklander * 6817466cbSJens Wiklander * \author Adriaan de Jong <dejong@fox-it.com> 7817466cbSJens Wiklander * 8*7901324dSJerome Forissier * Copyright The Mbed TLS Contributors 9*7901324dSJerome Forissier * SPDX-License-Identifier: Apache-2.0 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 24*7901324dSJerome Forissier #include "common.h" 25817466cbSJens Wiklander 26817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_C) 27817466cbSJens Wiklander 28817466cbSJens Wiklander #include "mbedtls/cipher.h" 29817466cbSJens Wiklander #include "mbedtls/cipher_internal.h" 303d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 3111fa71b9SJerome Forissier #include "mbedtls/error.h" 32817466cbSJens Wiklander 33817466cbSJens Wiklander #include <stdlib.h> 34817466cbSJens Wiklander #include <string.h> 35817466cbSJens Wiklander 363d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 373d3b0591SJens Wiklander #include "mbedtls/chachapoly.h" 383d3b0591SJens Wiklander #endif 393d3b0591SJens Wiklander 40817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 41817466cbSJens Wiklander #include "mbedtls/gcm.h" 42817466cbSJens Wiklander #endif 43817466cbSJens Wiklander 44817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 45817466cbSJens Wiklander #include "mbedtls/ccm.h" 46817466cbSJens Wiklander #endif 47817466cbSJens Wiklander 483d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C) 493d3b0591SJens Wiklander #include "mbedtls/chacha20.h" 503d3b0591SJens Wiklander #endif 513d3b0591SJens Wiklander 52817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C) 53817466cbSJens Wiklander #include "mbedtls/cmac.h" 54817466cbSJens Wiklander #endif 55817466cbSJens Wiklander 5611fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 5711fa71b9SJerome Forissier #include "psa/crypto.h" 5811fa71b9SJerome Forissier #include "mbedtls/psa_util.h" 5911fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 6011fa71b9SJerome Forissier 6111fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 6211fa71b9SJerome Forissier #include "mbedtls/nist_kw.h" 6311fa71b9SJerome Forissier #endif 6411fa71b9SJerome Forissier 65817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 66817466cbSJens Wiklander #include "mbedtls/platform.h" 67817466cbSJens Wiklander #else 68817466cbSJens Wiklander #define mbedtls_calloc calloc 69817466cbSJens Wiklander #define mbedtls_free free 70817466cbSJens Wiklander #endif 71817466cbSJens Wiklander 723d3b0591SJens Wiklander #define CIPHER_VALIDATE_RET( cond ) \ 733d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) 743d3b0591SJens Wiklander #define CIPHER_VALIDATE( cond ) \ 753d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE( cond ) 76817466cbSJens Wiklander 773d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 783d3b0591SJens Wiklander /* Compare the contents of two buffers in constant time. 793d3b0591SJens Wiklander * Returns 0 if the contents are bitwise identical, otherwise returns 803d3b0591SJens Wiklander * a non-zero value. 813d3b0591SJens Wiklander * This is currently only used by GCM and ChaCha20+Poly1305. 823d3b0591SJens Wiklander */ 8311fa71b9SJerome Forissier static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, 8411fa71b9SJerome Forissier size_t len ) 853d3b0591SJens Wiklander { 863d3b0591SJens Wiklander const unsigned char *p1 = (const unsigned char*) v1; 873d3b0591SJens Wiklander const unsigned char *p2 = (const unsigned char*) v2; 883d3b0591SJens Wiklander size_t i; 893d3b0591SJens Wiklander unsigned char diff; 903d3b0591SJens Wiklander 913d3b0591SJens Wiklander for( diff = 0, i = 0; i < len; i++ ) 923d3b0591SJens Wiklander diff |= p1[i] ^ p2[i]; 933d3b0591SJens Wiklander 943d3b0591SJens Wiklander return( (int)diff ); 95817466cbSJens Wiklander } 963d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 97817466cbSJens Wiklander 98817466cbSJens Wiklander static int supported_init = 0; 99817466cbSJens Wiklander 100817466cbSJens Wiklander const int *mbedtls_cipher_list( void ) 101817466cbSJens Wiklander { 102817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 103817466cbSJens Wiklander int *type; 104817466cbSJens Wiklander 105817466cbSJens Wiklander if( ! supported_init ) 106817466cbSJens Wiklander { 107817466cbSJens Wiklander def = mbedtls_cipher_definitions; 108817466cbSJens Wiklander type = mbedtls_cipher_supported; 109817466cbSJens Wiklander 110817466cbSJens Wiklander while( def->type != 0 ) 111817466cbSJens Wiklander *type++ = (*def++).type; 112817466cbSJens Wiklander 113817466cbSJens Wiklander *type = 0; 114817466cbSJens Wiklander 115817466cbSJens Wiklander supported_init = 1; 116817466cbSJens Wiklander } 117817466cbSJens Wiklander 118817466cbSJens Wiklander return( mbedtls_cipher_supported ); 119817466cbSJens Wiklander } 120817466cbSJens Wiklander 12111fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( 12211fa71b9SJerome Forissier const mbedtls_cipher_type_t cipher_type ) 123817466cbSJens Wiklander { 124817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 125817466cbSJens Wiklander 126817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 127817466cbSJens Wiklander if( def->type == cipher_type ) 128817466cbSJens Wiklander return( def->info ); 129817466cbSJens Wiklander 130817466cbSJens Wiklander return( NULL ); 131817466cbSJens Wiklander } 132817466cbSJens Wiklander 13311fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( 13411fa71b9SJerome Forissier const char *cipher_name ) 135817466cbSJens Wiklander { 136817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 137817466cbSJens Wiklander 138817466cbSJens Wiklander if( NULL == cipher_name ) 139817466cbSJens Wiklander return( NULL ); 140817466cbSJens Wiklander 141817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 142817466cbSJens Wiklander if( ! strcmp( def->info->name, cipher_name ) ) 143817466cbSJens Wiklander return( def->info ); 144817466cbSJens Wiklander 145817466cbSJens Wiklander return( NULL ); 146817466cbSJens Wiklander } 147817466cbSJens Wiklander 14811fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( 14911fa71b9SJerome Forissier const mbedtls_cipher_id_t cipher_id, 150817466cbSJens Wiklander int key_bitlen, 151817466cbSJens Wiklander const mbedtls_cipher_mode_t mode ) 152817466cbSJens Wiklander { 153817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 154817466cbSJens Wiklander 155817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 156817466cbSJens Wiklander if( def->info->base->cipher == cipher_id && 157817466cbSJens Wiklander def->info->key_bitlen == (unsigned) key_bitlen && 158817466cbSJens Wiklander def->info->mode == mode ) 159817466cbSJens Wiklander return( def->info ); 160817466cbSJens Wiklander 161817466cbSJens Wiklander return( NULL ); 162817466cbSJens Wiklander } 163817466cbSJens Wiklander 164817466cbSJens Wiklander void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) 165817466cbSJens Wiklander { 1663d3b0591SJens Wiklander CIPHER_VALIDATE( ctx != NULL ); 167817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 168817466cbSJens Wiklander } 169817466cbSJens Wiklander 170817466cbSJens Wiklander void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) 171817466cbSJens Wiklander { 172817466cbSJens Wiklander if( ctx == NULL ) 173817466cbSJens Wiklander return; 174817466cbSJens Wiklander 17511fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 17611fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 17711fa71b9SJerome Forissier { 17811fa71b9SJerome Forissier if( ctx->cipher_ctx != NULL ) 17911fa71b9SJerome Forissier { 18011fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 18111fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 18211fa71b9SJerome Forissier 18311fa71b9SJerome Forissier if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED ) 18411fa71b9SJerome Forissier { 18511fa71b9SJerome Forissier /* xxx_free() doesn't allow to return failures. */ 18611fa71b9SJerome Forissier (void) psa_destroy_key( cipher_psa->slot ); 18711fa71b9SJerome Forissier } 18811fa71b9SJerome Forissier 18911fa71b9SJerome Forissier mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) ); 19011fa71b9SJerome Forissier mbedtls_free( cipher_psa ); 19111fa71b9SJerome Forissier } 19211fa71b9SJerome Forissier 19311fa71b9SJerome Forissier mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); 19411fa71b9SJerome Forissier return; 19511fa71b9SJerome Forissier } 19611fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 19711fa71b9SJerome Forissier 198817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C) 199817466cbSJens Wiklander if( ctx->cmac_ctx ) 200817466cbSJens Wiklander { 2013d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx->cmac_ctx, 2023d3b0591SJens Wiklander sizeof( mbedtls_cmac_context_t ) ); 203817466cbSJens Wiklander mbedtls_free( ctx->cmac_ctx ); 204817466cbSJens Wiklander } 205817466cbSJens Wiklander #endif 206817466cbSJens Wiklander 207817466cbSJens Wiklander if( ctx->cipher_ctx ) 208817466cbSJens Wiklander ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); 209817466cbSJens Wiklander 2103d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); 211817466cbSJens Wiklander } 212817466cbSJens Wiklander 21312484fc7SEdison Ai int mbedtls_cipher_clone( mbedtls_cipher_context_t *dst, 21412484fc7SEdison Ai const mbedtls_cipher_context_t *src ) 21512484fc7SEdison Ai { 21612484fc7SEdison Ai if( dst == NULL || dst->cipher_info == NULL || 21712484fc7SEdison Ai src == NULL || src->cipher_info == NULL) 21812484fc7SEdison Ai { 21912484fc7SEdison Ai return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 22012484fc7SEdison Ai } 22112484fc7SEdison Ai 22212484fc7SEdison Ai dst->cipher_info = src->cipher_info; 22312484fc7SEdison Ai dst->key_bitlen = src->key_bitlen; 22412484fc7SEdison Ai dst->operation = src->operation; 22512484fc7SEdison Ai #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 22612484fc7SEdison Ai dst->add_padding = src->add_padding; 22712484fc7SEdison Ai dst->get_padding = src->get_padding; 22812484fc7SEdison Ai #endif 22912484fc7SEdison Ai memcpy( dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH ); 23012484fc7SEdison Ai dst->unprocessed_len = src->unprocessed_len; 23112484fc7SEdison Ai memcpy( dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH ); 23212484fc7SEdison Ai dst->iv_size = src->iv_size; 23312484fc7SEdison Ai if( dst->cipher_info->base->ctx_clone_func ) 23412484fc7SEdison Ai dst->cipher_info->base->ctx_clone_func( dst->cipher_ctx, src->cipher_ctx ); 23512484fc7SEdison Ai 23612484fc7SEdison Ai #if defined(MBEDTLS_CMAC_C) 23712484fc7SEdison Ai if( dst->cmac_ctx != NULL && src->cmac_ctx != NULL ) 23812484fc7SEdison Ai memcpy( dst->cmac_ctx, src->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); 23912484fc7SEdison Ai #endif 24012484fc7SEdison Ai return( 0 ); 24112484fc7SEdison Ai } 24212484fc7SEdison Ai 24311fa71b9SJerome Forissier int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, 24411fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info ) 245817466cbSJens Wiklander { 2463d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 2473d3b0591SJens Wiklander if( cipher_info == NULL ) 248817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 249817466cbSJens Wiklander 250817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 251817466cbSJens Wiklander 252817466cbSJens Wiklander if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) 253817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 254817466cbSJens Wiklander 255817466cbSJens Wiklander ctx->cipher_info = cipher_info; 256817466cbSJens Wiklander 257817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 258817466cbSJens Wiklander /* 259817466cbSJens Wiklander * Ignore possible errors caused by a cipher mode that doesn't use padding 260817466cbSJens Wiklander */ 261817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 262817466cbSJens Wiklander (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); 263817466cbSJens Wiklander #else 264817466cbSJens Wiklander (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); 265817466cbSJens Wiklander #endif 266817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 267817466cbSJens Wiklander 268817466cbSJens Wiklander return( 0 ); 269817466cbSJens Wiklander } 270817466cbSJens Wiklander 27111fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 27211fa71b9SJerome Forissier int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, 27311fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info, 27411fa71b9SJerome Forissier size_t taglen ) 27511fa71b9SJerome Forissier { 27611fa71b9SJerome Forissier psa_algorithm_t alg; 27711fa71b9SJerome Forissier mbedtls_cipher_context_psa *cipher_psa; 27811fa71b9SJerome Forissier 27911fa71b9SJerome Forissier if( NULL == cipher_info || NULL == ctx ) 28011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 28111fa71b9SJerome Forissier 28211fa71b9SJerome Forissier /* Check that the underlying cipher mode and cipher type are 28311fa71b9SJerome Forissier * supported by the underlying PSA Crypto implementation. */ 28411fa71b9SJerome Forissier alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen ); 28511fa71b9SJerome Forissier if( alg == 0 ) 28611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 28711fa71b9SJerome Forissier if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 ) 28811fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 28911fa71b9SJerome Forissier 29011fa71b9SJerome Forissier memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 29111fa71b9SJerome Forissier 29211fa71b9SJerome Forissier cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) ); 29311fa71b9SJerome Forissier if( cipher_psa == NULL ) 29411fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 29511fa71b9SJerome Forissier cipher_psa->alg = alg; 29611fa71b9SJerome Forissier ctx->cipher_ctx = cipher_psa; 29711fa71b9SJerome Forissier ctx->cipher_info = cipher_info; 29811fa71b9SJerome Forissier ctx->psa_enabled = 1; 29911fa71b9SJerome Forissier return( 0 ); 30011fa71b9SJerome Forissier } 30111fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 30211fa71b9SJerome Forissier 30312484fc7SEdison Ai int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) 30412484fc7SEdison Ai { 30512484fc7SEdison Ai if( NULL == cipher_info || NULL == ctx ) 30612484fc7SEdison Ai return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 30712484fc7SEdison Ai 30812484fc7SEdison Ai ctx->cipher_info = cipher_info; 30912484fc7SEdison Ai return( 0 ); 31012484fc7SEdison Ai } 31112484fc7SEdison Ai 3123d3b0591SJens Wiklander int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, 3133d3b0591SJens Wiklander const unsigned char *key, 3143d3b0591SJens Wiklander int key_bitlen, 3153d3b0591SJens Wiklander const mbedtls_operation_t operation ) 316817466cbSJens Wiklander { 3173d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 3183d3b0591SJens Wiklander CIPHER_VALIDATE_RET( key != NULL ); 3193d3b0591SJens Wiklander CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || 3203d3b0591SJens Wiklander operation == MBEDTLS_DECRYPT ); 3213d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 322817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 323817466cbSJens Wiklander 32411fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 32511fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 32611fa71b9SJerome Forissier { 32711fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 32811fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 32911fa71b9SJerome Forissier 33011fa71b9SJerome Forissier size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8; 33111fa71b9SJerome Forissier 33211fa71b9SJerome Forissier psa_status_t status; 33311fa71b9SJerome Forissier psa_key_type_t key_type; 33411fa71b9SJerome Forissier psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 33511fa71b9SJerome Forissier 33611fa71b9SJerome Forissier /* PSA Crypto API only accepts byte-aligned keys. */ 33711fa71b9SJerome Forissier if( key_bitlen % 8 != 0 ) 33811fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 33911fa71b9SJerome Forissier 34011fa71b9SJerome Forissier /* Don't allow keys to be set multiple times. */ 34111fa71b9SJerome Forissier if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET ) 34211fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 34311fa71b9SJerome Forissier 34411fa71b9SJerome Forissier key_type = mbedtls_psa_translate_cipher_type( 34511fa71b9SJerome Forissier ctx->cipher_info->type ); 34611fa71b9SJerome Forissier if( key_type == 0 ) 34711fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 34811fa71b9SJerome Forissier psa_set_key_type( &attributes, key_type ); 34911fa71b9SJerome Forissier 35011fa71b9SJerome Forissier /* Mbed TLS' cipher layer doesn't enforce the mode of operation 35111fa71b9SJerome Forissier * (encrypt vs. decrypt): it is possible to setup a key for encryption 35211fa71b9SJerome Forissier * and use it for AEAD decryption. Until tests relying on this 35311fa71b9SJerome Forissier * are changed, allow any usage in PSA. */ 35411fa71b9SJerome Forissier psa_set_key_usage_flags( &attributes, 35511fa71b9SJerome Forissier /* mbedtls_psa_translate_cipher_operation( operation ); */ 35611fa71b9SJerome Forissier PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); 35711fa71b9SJerome Forissier psa_set_key_algorithm( &attributes, cipher_psa->alg ); 35811fa71b9SJerome Forissier 35911fa71b9SJerome Forissier status = psa_import_key( &attributes, key, key_bytelen, 36011fa71b9SJerome Forissier &cipher_psa->slot ); 36111fa71b9SJerome Forissier switch( status ) 36211fa71b9SJerome Forissier { 36311fa71b9SJerome Forissier case PSA_SUCCESS: 36411fa71b9SJerome Forissier break; 36511fa71b9SJerome Forissier case PSA_ERROR_INSUFFICIENT_MEMORY: 36611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 36711fa71b9SJerome Forissier case PSA_ERROR_NOT_SUPPORTED: 36811fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 36911fa71b9SJerome Forissier default: 37011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 37111fa71b9SJerome Forissier } 37211fa71b9SJerome Forissier /* Indicate that we own the key slot and need to 37311fa71b9SJerome Forissier * destroy it in mbedtls_cipher_free(). */ 37411fa71b9SJerome Forissier cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; 37511fa71b9SJerome Forissier 37611fa71b9SJerome Forissier ctx->key_bitlen = key_bitlen; 37711fa71b9SJerome Forissier ctx->operation = operation; 37811fa71b9SJerome Forissier return( 0 ); 37911fa71b9SJerome Forissier } 38011fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 38111fa71b9SJerome Forissier 382817466cbSJens Wiklander if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && 383817466cbSJens Wiklander (int) ctx->cipher_info->key_bitlen != key_bitlen ) 384817466cbSJens Wiklander { 385817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 386817466cbSJens Wiklander } 387817466cbSJens Wiklander 388817466cbSJens Wiklander ctx->key_bitlen = key_bitlen; 389817466cbSJens Wiklander ctx->operation = operation; 390817466cbSJens Wiklander 391817466cbSJens Wiklander /* 3923d3b0591SJens Wiklander * For OFB, CFB and CTR mode always use the encryption key schedule 393817466cbSJens Wiklander */ 394817466cbSJens Wiklander if( MBEDTLS_ENCRYPT == operation || 395817466cbSJens Wiklander MBEDTLS_MODE_CFB == ctx->cipher_info->mode || 3963d3b0591SJens Wiklander MBEDTLS_MODE_OFB == ctx->cipher_info->mode || 397817466cbSJens Wiklander MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) 398817466cbSJens Wiklander { 3993d3b0591SJens Wiklander return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, 4003d3b0591SJens Wiklander ctx->key_bitlen ) ); 401817466cbSJens Wiklander } 402817466cbSJens Wiklander 403817466cbSJens Wiklander if( MBEDTLS_DECRYPT == operation ) 4043d3b0591SJens Wiklander return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, 4053d3b0591SJens Wiklander ctx->key_bitlen ) ); 406817466cbSJens Wiklander 407817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 408817466cbSJens Wiklander } 409817466cbSJens Wiklander 410817466cbSJens Wiklander int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, 4113d3b0591SJens Wiklander const unsigned char *iv, 4123d3b0591SJens Wiklander size_t iv_len ) 413817466cbSJens Wiklander { 414817466cbSJens Wiklander size_t actual_iv_size; 415817466cbSJens Wiklander 4163d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 4173d3b0591SJens Wiklander CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 4183d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 419817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 42011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 42111fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 42211fa71b9SJerome Forissier { 42311fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 42411fa71b9SJerome Forissier * operations, we currently don't make it 42511fa71b9SJerome Forissier * accessible through the cipher layer. */ 42611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 42711fa71b9SJerome Forissier } 42811fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 429817466cbSJens Wiklander 430817466cbSJens Wiklander /* avoid buffer overflow in ctx->iv */ 431817466cbSJens Wiklander if( iv_len > MBEDTLS_MAX_IV_LENGTH ) 432817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 433817466cbSJens Wiklander 434817466cbSJens Wiklander if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) 435817466cbSJens Wiklander actual_iv_size = iv_len; 436817466cbSJens Wiklander else 437817466cbSJens Wiklander { 438817466cbSJens Wiklander actual_iv_size = ctx->cipher_info->iv_size; 439817466cbSJens Wiklander 440817466cbSJens Wiklander /* avoid reading past the end of input buffer */ 441817466cbSJens Wiklander if( actual_iv_size > iv_len ) 442817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 443817466cbSJens Wiklander } 444817466cbSJens Wiklander 4453d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C) 4463d3b0591SJens Wiklander if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) 4473d3b0591SJens Wiklander { 4483d3b0591SJens Wiklander if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, 4493d3b0591SJens Wiklander iv, 4503d3b0591SJens Wiklander 0U ) ) /* Initial counter value */ 4513d3b0591SJens Wiklander { 4523d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 4533d3b0591SJens Wiklander } 4543d3b0591SJens Wiklander } 4553d3b0591SJens Wiklander #endif 4563d3b0591SJens Wiklander 4573d3b0591SJens Wiklander if ( actual_iv_size != 0 ) 4583d3b0591SJens Wiklander { 459817466cbSJens Wiklander memcpy( ctx->iv, iv, actual_iv_size ); 460817466cbSJens Wiklander ctx->iv_size = actual_iv_size; 4613d3b0591SJens Wiklander } 462817466cbSJens Wiklander 463817466cbSJens Wiklander return( 0 ); 464817466cbSJens Wiklander } 465817466cbSJens Wiklander 466817466cbSJens Wiklander int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) 467817466cbSJens Wiklander { 4683d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 4693d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 470817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 471817466cbSJens Wiklander 47211fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 47311fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 47411fa71b9SJerome Forissier { 47511fa71b9SJerome Forissier /* We don't support resetting PSA-based 47611fa71b9SJerome Forissier * cipher contexts, yet. */ 47711fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 47811fa71b9SJerome Forissier } 47911fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 48011fa71b9SJerome Forissier 481817466cbSJens Wiklander ctx->unprocessed_len = 0; 482817466cbSJens Wiklander 483817466cbSJens Wiklander return( 0 ); 484817466cbSJens Wiklander } 485817466cbSJens Wiklander 4863d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 487817466cbSJens Wiklander int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, 488817466cbSJens Wiklander const unsigned char *ad, size_t ad_len ) 489817466cbSJens Wiklander { 4903d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 4913d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 4923d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 493817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 494817466cbSJens Wiklander 49511fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 49611fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 49711fa71b9SJerome Forissier { 49811fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 49911fa71b9SJerome Forissier * operations, we currently don't make it 50011fa71b9SJerome Forissier * accessible through the cipher layer. */ 50111fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 50211fa71b9SJerome Forissier } 50311fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 50411fa71b9SJerome Forissier 5053d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 506817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 507817466cbSJens Wiklander { 5083d3b0591SJens Wiklander return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, 5093d3b0591SJens Wiklander ctx->iv, ctx->iv_size, ad, ad_len ) ); 510817466cbSJens Wiklander } 5113d3b0591SJens Wiklander #endif 5123d3b0591SJens Wiklander 5133d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 5143d3b0591SJens Wiklander if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 5153d3b0591SJens Wiklander { 5163d3b0591SJens Wiklander int result; 5173d3b0591SJens Wiklander mbedtls_chachapoly_mode_t mode; 5183d3b0591SJens Wiklander 5193d3b0591SJens Wiklander mode = ( ctx->operation == MBEDTLS_ENCRYPT ) 5203d3b0591SJens Wiklander ? MBEDTLS_CHACHAPOLY_ENCRYPT 5213d3b0591SJens Wiklander : MBEDTLS_CHACHAPOLY_DECRYPT; 5223d3b0591SJens Wiklander 5233d3b0591SJens Wiklander result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 5243d3b0591SJens Wiklander ctx->iv, 5253d3b0591SJens Wiklander mode ); 5263d3b0591SJens Wiklander if ( result != 0 ) 5273d3b0591SJens Wiklander return( result ); 5283d3b0591SJens Wiklander 5293d3b0591SJens Wiklander return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 5303d3b0591SJens Wiklander ad, ad_len ) ); 5313d3b0591SJens Wiklander } 5323d3b0591SJens Wiklander #endif 533817466cbSJens Wiklander 534817466cbSJens Wiklander return( 0 ); 535817466cbSJens Wiklander } 5363d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 537817466cbSJens Wiklander 538817466cbSJens Wiklander int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, 539817466cbSJens Wiklander size_t ilen, unsigned char *output, size_t *olen ) 540817466cbSJens Wiklander { 54111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 5423d3b0591SJens Wiklander size_t block_size; 543817466cbSJens Wiklander 5443d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 5453d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 5463d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 5473d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 5483d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 549817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 550817466cbSJens Wiklander 55111fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 55211fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 55311fa71b9SJerome Forissier { 55411fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 55511fa71b9SJerome Forissier * operations, we currently don't make it 55611fa71b9SJerome Forissier * accessible through the cipher layer. */ 55711fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 55811fa71b9SJerome Forissier } 55911fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 56011fa71b9SJerome Forissier 561817466cbSJens Wiklander *olen = 0; 562817466cbSJens Wiklander block_size = mbedtls_cipher_get_block_size( ctx ); 5635b25c76aSJerome Forissier if ( 0 == block_size ) 5645b25c76aSJerome Forissier { 5655b25c76aSJerome Forissier return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); 5665b25c76aSJerome Forissier } 567817466cbSJens Wiklander 568817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) 569817466cbSJens Wiklander { 570817466cbSJens Wiklander if( ilen != block_size ) 571817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 572817466cbSJens Wiklander 573817466cbSJens Wiklander *olen = ilen; 574817466cbSJens Wiklander 575817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, 576817466cbSJens Wiklander ctx->operation, input, output ) ) ) 577817466cbSJens Wiklander { 578817466cbSJens Wiklander return( ret ); 579817466cbSJens Wiklander } 580817466cbSJens Wiklander 581817466cbSJens Wiklander return( 0 ); 582817466cbSJens Wiklander } 583817466cbSJens Wiklander 584817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 585817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) 586817466cbSJens Wiklander { 587817466cbSJens Wiklander *olen = ilen; 5883d3b0591SJens Wiklander return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, 5893d3b0591SJens Wiklander output ) ); 5903d3b0591SJens Wiklander } 5913d3b0591SJens Wiklander #endif 5923d3b0591SJens Wiklander 5933d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 5943d3b0591SJens Wiklander if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) 5953d3b0591SJens Wiklander { 5963d3b0591SJens Wiklander *olen = ilen; 5973d3b0591SJens Wiklander return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 5983d3b0591SJens Wiklander ilen, input, output ) ); 599817466cbSJens Wiklander } 600817466cbSJens Wiklander #endif 601817466cbSJens Wiklander 602817466cbSJens Wiklander if( input == output && 603817466cbSJens Wiklander ( ctx->unprocessed_len != 0 || ilen % block_size ) ) 604817466cbSJens Wiklander { 605817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 606817466cbSJens Wiklander } 607817466cbSJens Wiklander 608817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC) 609817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) 610817466cbSJens Wiklander { 611817466cbSJens Wiklander size_t copy_len = 0; 612817466cbSJens Wiklander 613817466cbSJens Wiklander /* 614817466cbSJens Wiklander * If there is not enough data for a full block, cache it. 615817466cbSJens Wiklander */ 6163d3b0591SJens Wiklander if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && 617817466cbSJens Wiklander ilen <= block_size - ctx->unprocessed_len ) || 6183d3b0591SJens Wiklander ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && 6193d3b0591SJens Wiklander ilen < block_size - ctx->unprocessed_len ) || 620817466cbSJens Wiklander ( ctx->operation == MBEDTLS_ENCRYPT && 621817466cbSJens Wiklander ilen < block_size - ctx->unprocessed_len ) ) 622817466cbSJens Wiklander { 623817466cbSJens Wiklander memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, 624817466cbSJens Wiklander ilen ); 625817466cbSJens Wiklander 626817466cbSJens Wiklander ctx->unprocessed_len += ilen; 627817466cbSJens Wiklander return( 0 ); 628817466cbSJens Wiklander } 629817466cbSJens Wiklander 630817466cbSJens Wiklander /* 631817466cbSJens Wiklander * Process cached data first 632817466cbSJens Wiklander */ 633817466cbSJens Wiklander if( 0 != ctx->unprocessed_len ) 634817466cbSJens Wiklander { 635817466cbSJens Wiklander copy_len = block_size - ctx->unprocessed_len; 636817466cbSJens Wiklander 637817466cbSJens Wiklander memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, 638817466cbSJens Wiklander copy_len ); 639817466cbSJens Wiklander 640817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 641817466cbSJens Wiklander ctx->operation, block_size, ctx->iv, 642817466cbSJens Wiklander ctx->unprocessed_data, output ) ) ) 643817466cbSJens Wiklander { 644817466cbSJens Wiklander return( ret ); 645817466cbSJens Wiklander } 646817466cbSJens Wiklander 647817466cbSJens Wiklander *olen += block_size; 648817466cbSJens Wiklander output += block_size; 649817466cbSJens Wiklander ctx->unprocessed_len = 0; 650817466cbSJens Wiklander 651817466cbSJens Wiklander input += copy_len; 652817466cbSJens Wiklander ilen -= copy_len; 653817466cbSJens Wiklander } 654817466cbSJens Wiklander 655817466cbSJens Wiklander /* 656817466cbSJens Wiklander * Cache final, incomplete block 657817466cbSJens Wiklander */ 658817466cbSJens Wiklander if( 0 != ilen ) 659817466cbSJens Wiklander { 6603d3b0591SJens Wiklander /* Encryption: only cache partial blocks 6613d3b0591SJens Wiklander * Decryption w/ padding: always keep at least one whole block 6623d3b0591SJens Wiklander * Decryption w/o padding: only cache partial blocks 6633d3b0591SJens Wiklander */ 664817466cbSJens Wiklander copy_len = ilen % block_size; 6653d3b0591SJens Wiklander if( copy_len == 0 && 6663d3b0591SJens Wiklander ctx->operation == MBEDTLS_DECRYPT && 6673d3b0591SJens Wiklander NULL != ctx->add_padding) 6683d3b0591SJens Wiklander { 669817466cbSJens Wiklander copy_len = block_size; 6703d3b0591SJens Wiklander } 671817466cbSJens Wiklander 672817466cbSJens Wiklander memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), 673817466cbSJens Wiklander copy_len ); 674817466cbSJens Wiklander 675817466cbSJens Wiklander ctx->unprocessed_len += copy_len; 676817466cbSJens Wiklander ilen -= copy_len; 677817466cbSJens Wiklander } 678817466cbSJens Wiklander 679817466cbSJens Wiklander /* 680817466cbSJens Wiklander * Process remaining full blocks 681817466cbSJens Wiklander */ 682817466cbSJens Wiklander if( ilen ) 683817466cbSJens Wiklander { 684817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 685817466cbSJens Wiklander ctx->operation, ilen, ctx->iv, input, output ) ) ) 686817466cbSJens Wiklander { 687817466cbSJens Wiklander return( ret ); 688817466cbSJens Wiklander } 689817466cbSJens Wiklander 690817466cbSJens Wiklander *olen += ilen; 691817466cbSJens Wiklander } 692817466cbSJens Wiklander 693817466cbSJens Wiklander return( 0 ); 694817466cbSJens Wiklander } 695817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */ 696817466cbSJens Wiklander 697817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CFB) 698817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) 699817466cbSJens Wiklander { 700817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, 701817466cbSJens Wiklander ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, 702817466cbSJens Wiklander input, output ) ) ) 703817466cbSJens Wiklander { 704817466cbSJens Wiklander return( ret ); 705817466cbSJens Wiklander } 706817466cbSJens Wiklander 707817466cbSJens Wiklander *olen = ilen; 708817466cbSJens Wiklander 709817466cbSJens Wiklander return( 0 ); 710817466cbSJens Wiklander } 711817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CFB */ 712817466cbSJens Wiklander 7133d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_OFB) 7143d3b0591SJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) 7153d3b0591SJens Wiklander { 7163d3b0591SJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, 7173d3b0591SJens Wiklander ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) 7183d3b0591SJens Wiklander { 7193d3b0591SJens Wiklander return( ret ); 7203d3b0591SJens Wiklander } 7213d3b0591SJens Wiklander 7223d3b0591SJens Wiklander *olen = ilen; 7233d3b0591SJens Wiklander 7243d3b0591SJens Wiklander return( 0 ); 7253d3b0591SJens Wiklander } 7263d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_OFB */ 7273d3b0591SJens Wiklander 728817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CTR) 729817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) 730817466cbSJens Wiklander { 731817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, 732817466cbSJens Wiklander ilen, &ctx->unprocessed_len, ctx->iv, 733817466cbSJens Wiklander ctx->unprocessed_data, input, output ) ) ) 734817466cbSJens Wiklander { 735817466cbSJens Wiklander return( ret ); 736817466cbSJens Wiklander } 737817466cbSJens Wiklander 738817466cbSJens Wiklander *olen = ilen; 739817466cbSJens Wiklander 740817466cbSJens Wiklander return( 0 ); 741817466cbSJens Wiklander } 742817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CTR */ 743817466cbSJens Wiklander 7443d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_XTS) 7453d3b0591SJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) 7463d3b0591SJens Wiklander { 7473d3b0591SJens Wiklander if( ctx->unprocessed_len > 0 ) { 7483d3b0591SJens Wiklander /* We can only process an entire data unit at a time. */ 7493d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 7503d3b0591SJens Wiklander } 7513d3b0591SJens Wiklander 7523d3b0591SJens Wiklander ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, 7533d3b0591SJens Wiklander ctx->operation, ilen, ctx->iv, input, output ); 7543d3b0591SJens Wiklander if( ret != 0 ) 7553d3b0591SJens Wiklander { 7563d3b0591SJens Wiklander return( ret ); 7573d3b0591SJens Wiklander } 7583d3b0591SJens Wiklander 7593d3b0591SJens Wiklander *olen = ilen; 7603d3b0591SJens Wiklander 7613d3b0591SJens Wiklander return( 0 ); 7623d3b0591SJens Wiklander } 7633d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_XTS */ 7643d3b0591SJens Wiklander 765817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_STREAM) 766817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) 767817466cbSJens Wiklander { 768817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, 769817466cbSJens Wiklander ilen, input, output ) ) ) 770817466cbSJens Wiklander { 771817466cbSJens Wiklander return( ret ); 772817466cbSJens Wiklander } 773817466cbSJens Wiklander 774817466cbSJens Wiklander *olen = ilen; 775817466cbSJens Wiklander 776817466cbSJens Wiklander return( 0 ); 777817466cbSJens Wiklander } 778817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_STREAM */ 779817466cbSJens Wiklander 780817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 781817466cbSJens Wiklander } 782817466cbSJens Wiklander 783817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 784817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 785817466cbSJens Wiklander /* 786817466cbSJens Wiklander * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len 787817466cbSJens Wiklander */ 788817466cbSJens Wiklander static void add_pkcs_padding( unsigned char *output, size_t output_len, 789817466cbSJens Wiklander size_t data_len ) 790817466cbSJens Wiklander { 791817466cbSJens Wiklander size_t padding_len = output_len - data_len; 792817466cbSJens Wiklander unsigned char i; 793817466cbSJens Wiklander 794817466cbSJens Wiklander for( i = 0; i < padding_len; i++ ) 795817466cbSJens Wiklander output[data_len + i] = (unsigned char) padding_len; 796817466cbSJens Wiklander } 797817466cbSJens Wiklander 798817466cbSJens Wiklander static int get_pkcs_padding( unsigned char *input, size_t input_len, 799817466cbSJens Wiklander size_t *data_len ) 800817466cbSJens Wiklander { 801817466cbSJens Wiklander size_t i, pad_idx; 802817466cbSJens Wiklander unsigned char padding_len, bad = 0; 803817466cbSJens Wiklander 804817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 805817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 806817466cbSJens Wiklander 807817466cbSJens Wiklander padding_len = input[input_len - 1]; 808817466cbSJens Wiklander *data_len = input_len - padding_len; 809817466cbSJens Wiklander 810817466cbSJens Wiklander /* Avoid logical || since it results in a branch */ 811817466cbSJens Wiklander bad |= padding_len > input_len; 812817466cbSJens Wiklander bad |= padding_len == 0; 813817466cbSJens Wiklander 814817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len, 815817466cbSJens Wiklander * so pick input_len, which is usually 8 or 16 (one block) */ 816817466cbSJens Wiklander pad_idx = input_len - padding_len; 817817466cbSJens Wiklander for( i = 0; i < input_len; i++ ) 818817466cbSJens Wiklander bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); 819817466cbSJens Wiklander 820817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 821817466cbSJens Wiklander } 822817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ 823817466cbSJens Wiklander 824817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) 825817466cbSJens Wiklander /* 826817466cbSJens Wiklander * One and zeros padding: fill with 80 00 ... 00 827817466cbSJens Wiklander */ 828817466cbSJens Wiklander static void add_one_and_zeros_padding( unsigned char *output, 829817466cbSJens Wiklander size_t output_len, size_t data_len ) 830817466cbSJens Wiklander { 831817466cbSJens Wiklander size_t padding_len = output_len - data_len; 832817466cbSJens Wiklander unsigned char i = 0; 833817466cbSJens Wiklander 834817466cbSJens Wiklander output[data_len] = 0x80; 835817466cbSJens Wiklander for( i = 1; i < padding_len; i++ ) 836817466cbSJens Wiklander output[data_len + i] = 0x00; 837817466cbSJens Wiklander } 838817466cbSJens Wiklander 839817466cbSJens Wiklander static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, 840817466cbSJens Wiklander size_t *data_len ) 841817466cbSJens Wiklander { 842817466cbSJens Wiklander size_t i; 843817466cbSJens Wiklander unsigned char done = 0, prev_done, bad; 844817466cbSJens Wiklander 845817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 846817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 847817466cbSJens Wiklander 8483d3b0591SJens Wiklander bad = 0x80; 849817466cbSJens Wiklander *data_len = 0; 850817466cbSJens Wiklander for( i = input_len; i > 0; i-- ) 851817466cbSJens Wiklander { 852817466cbSJens Wiklander prev_done = done; 853817466cbSJens Wiklander done |= ( input[i - 1] != 0 ); 854817466cbSJens Wiklander *data_len |= ( i - 1 ) * ( done != prev_done ); 8553d3b0591SJens Wiklander bad ^= input[i - 1] * ( done != prev_done ); 856817466cbSJens Wiklander } 857817466cbSJens Wiklander 858817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 859817466cbSJens Wiklander 860817466cbSJens Wiklander } 861817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ 862817466cbSJens Wiklander 863817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) 864817466cbSJens Wiklander /* 865817466cbSJens Wiklander * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length 866817466cbSJens Wiklander */ 867817466cbSJens Wiklander static void add_zeros_and_len_padding( unsigned char *output, 868817466cbSJens Wiklander size_t output_len, size_t data_len ) 869817466cbSJens Wiklander { 870817466cbSJens Wiklander size_t padding_len = output_len - data_len; 871817466cbSJens Wiklander unsigned char i = 0; 872817466cbSJens Wiklander 873817466cbSJens Wiklander for( i = 1; i < padding_len; i++ ) 874817466cbSJens Wiklander output[data_len + i - 1] = 0x00; 875817466cbSJens Wiklander output[output_len - 1] = (unsigned char) padding_len; 876817466cbSJens Wiklander } 877817466cbSJens Wiklander 878817466cbSJens Wiklander static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, 879817466cbSJens Wiklander size_t *data_len ) 880817466cbSJens Wiklander { 881817466cbSJens Wiklander size_t i, pad_idx; 882817466cbSJens Wiklander unsigned char padding_len, bad = 0; 883817466cbSJens Wiklander 884817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 885817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 886817466cbSJens Wiklander 887817466cbSJens Wiklander padding_len = input[input_len - 1]; 888817466cbSJens Wiklander *data_len = input_len - padding_len; 889817466cbSJens Wiklander 890817466cbSJens Wiklander /* Avoid logical || since it results in a branch */ 891817466cbSJens Wiklander bad |= padding_len > input_len; 892817466cbSJens Wiklander bad |= padding_len == 0; 893817466cbSJens Wiklander 894817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len */ 895817466cbSJens Wiklander pad_idx = input_len - padding_len; 896817466cbSJens Wiklander for( i = 0; i < input_len - 1; i++ ) 897817466cbSJens Wiklander bad |= input[i] * ( i >= pad_idx ); 898817466cbSJens Wiklander 899817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 900817466cbSJens Wiklander } 901817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ 902817466cbSJens Wiklander 903817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) 904817466cbSJens Wiklander /* 905817466cbSJens Wiklander * Zero padding: fill with 00 ... 00 906817466cbSJens Wiklander */ 907817466cbSJens Wiklander static void add_zeros_padding( unsigned char *output, 908817466cbSJens Wiklander size_t output_len, size_t data_len ) 909817466cbSJens Wiklander { 910817466cbSJens Wiklander size_t i; 911817466cbSJens Wiklander 912817466cbSJens Wiklander for( i = data_len; i < output_len; i++ ) 913817466cbSJens Wiklander output[i] = 0x00; 914817466cbSJens Wiklander } 915817466cbSJens Wiklander 916817466cbSJens Wiklander static int get_zeros_padding( unsigned char *input, size_t input_len, 917817466cbSJens Wiklander size_t *data_len ) 918817466cbSJens Wiklander { 919817466cbSJens Wiklander size_t i; 920817466cbSJens Wiklander unsigned char done = 0, prev_done; 921817466cbSJens Wiklander 922817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 923817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 924817466cbSJens Wiklander 925817466cbSJens Wiklander *data_len = 0; 926817466cbSJens Wiklander for( i = input_len; i > 0; i-- ) 927817466cbSJens Wiklander { 928817466cbSJens Wiklander prev_done = done; 929817466cbSJens Wiklander done |= ( input[i-1] != 0 ); 930817466cbSJens Wiklander *data_len |= i * ( done != prev_done ); 931817466cbSJens Wiklander } 932817466cbSJens Wiklander 933817466cbSJens Wiklander return( 0 ); 934817466cbSJens Wiklander } 935817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ 936817466cbSJens Wiklander 937817466cbSJens Wiklander /* 938817466cbSJens Wiklander * No padding: don't pad :) 939817466cbSJens Wiklander * 940817466cbSJens Wiklander * There is no add_padding function (check for NULL in mbedtls_cipher_finish) 941817466cbSJens Wiklander * but a trivial get_padding function 942817466cbSJens Wiklander */ 943817466cbSJens Wiklander static int get_no_padding( unsigned char *input, size_t input_len, 944817466cbSJens Wiklander size_t *data_len ) 945817466cbSJens Wiklander { 946817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 947817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 948817466cbSJens Wiklander 949817466cbSJens Wiklander *data_len = input_len; 950817466cbSJens Wiklander 951817466cbSJens Wiklander return( 0 ); 952817466cbSJens Wiklander } 953817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 954817466cbSJens Wiklander 955817466cbSJens Wiklander int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, 956817466cbSJens Wiklander unsigned char *output, size_t *olen ) 957817466cbSJens Wiklander { 9583d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 9593d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 9603d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 9613d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 962817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 963817466cbSJens Wiklander 96411fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 96511fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 96611fa71b9SJerome Forissier { 96711fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 96811fa71b9SJerome Forissier * operations, we currently don't make it 96911fa71b9SJerome Forissier * accessible through the cipher layer. */ 97011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 97111fa71b9SJerome Forissier } 97211fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 97311fa71b9SJerome Forissier 974817466cbSJens Wiklander *olen = 0; 975817466cbSJens Wiklander 976817466cbSJens Wiklander if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || 9773d3b0591SJens Wiklander MBEDTLS_MODE_OFB == ctx->cipher_info->mode || 978817466cbSJens Wiklander MBEDTLS_MODE_CTR == ctx->cipher_info->mode || 979817466cbSJens Wiklander MBEDTLS_MODE_GCM == ctx->cipher_info->mode || 9803d3b0591SJens Wiklander MBEDTLS_MODE_XTS == ctx->cipher_info->mode || 981817466cbSJens Wiklander MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) 982817466cbSJens Wiklander { 983817466cbSJens Wiklander return( 0 ); 984817466cbSJens Wiklander } 985817466cbSJens Wiklander 9863d3b0591SJens Wiklander if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || 9873d3b0591SJens Wiklander ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) 9883d3b0591SJens Wiklander { 9893d3b0591SJens Wiklander return( 0 ); 9903d3b0591SJens Wiklander } 9913d3b0591SJens Wiklander 992817466cbSJens Wiklander if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) 993817466cbSJens Wiklander { 994817466cbSJens Wiklander if( ctx->unprocessed_len != 0 ) 995817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 996817466cbSJens Wiklander 997817466cbSJens Wiklander return( 0 ); 998817466cbSJens Wiklander } 999817466cbSJens Wiklander 1000817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC) 1001817466cbSJens Wiklander if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) 1002817466cbSJens Wiklander { 1003817466cbSJens Wiklander int ret = 0; 1004817466cbSJens Wiklander 1005817466cbSJens Wiklander if( MBEDTLS_ENCRYPT == ctx->operation ) 1006817466cbSJens Wiklander { 1007817466cbSJens Wiklander /* check for 'no padding' mode */ 1008817466cbSJens Wiklander if( NULL == ctx->add_padding ) 1009817466cbSJens Wiklander { 1010817466cbSJens Wiklander if( 0 != ctx->unprocessed_len ) 1011817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 1012817466cbSJens Wiklander 1013817466cbSJens Wiklander return( 0 ); 1014817466cbSJens Wiklander } 1015817466cbSJens Wiklander 1016817466cbSJens Wiklander ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), 1017817466cbSJens Wiklander ctx->unprocessed_len ); 1018817466cbSJens Wiklander } 1019817466cbSJens Wiklander else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) 1020817466cbSJens Wiklander { 1021817466cbSJens Wiklander /* 1022817466cbSJens Wiklander * For decrypt operations, expect a full block, 1023817466cbSJens Wiklander * or an empty block if no padding 1024817466cbSJens Wiklander */ 1025817466cbSJens Wiklander if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) 1026817466cbSJens Wiklander return( 0 ); 1027817466cbSJens Wiklander 1028817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 1029817466cbSJens Wiklander } 1030817466cbSJens Wiklander 1031817466cbSJens Wiklander /* cipher block */ 1032817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 1033817466cbSJens Wiklander ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, 1034817466cbSJens Wiklander ctx->unprocessed_data, output ) ) ) 1035817466cbSJens Wiklander { 1036817466cbSJens Wiklander return( ret ); 1037817466cbSJens Wiklander } 1038817466cbSJens Wiklander 1039817466cbSJens Wiklander /* Set output size for decryption */ 1040817466cbSJens Wiklander if( MBEDTLS_DECRYPT == ctx->operation ) 10413d3b0591SJens Wiklander return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), 10423d3b0591SJens Wiklander olen ) ); 1043817466cbSJens Wiklander 1044817466cbSJens Wiklander /* Set output size for encryption */ 1045817466cbSJens Wiklander *olen = mbedtls_cipher_get_block_size( ctx ); 1046817466cbSJens Wiklander return( 0 ); 1047817466cbSJens Wiklander } 1048817466cbSJens Wiklander #else 1049817466cbSJens Wiklander ((void) output); 1050817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */ 1051817466cbSJens Wiklander 1052817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1053817466cbSJens Wiklander } 1054817466cbSJens Wiklander 1055817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 10563d3b0591SJens Wiklander int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, 10573d3b0591SJens Wiklander mbedtls_cipher_padding_t mode ) 1058817466cbSJens Wiklander { 10593d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 10603d3b0591SJens Wiklander 10613d3b0591SJens Wiklander if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) 1062817466cbSJens Wiklander { 1063817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1064817466cbSJens Wiklander } 1065817466cbSJens Wiklander 106611fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 106711fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 106811fa71b9SJerome Forissier { 106911fa71b9SJerome Forissier /* While PSA Crypto knows about CBC padding 107011fa71b9SJerome Forissier * schemes, we currently don't make them 107111fa71b9SJerome Forissier * accessible through the cipher layer. */ 107211fa71b9SJerome Forissier if( mode != MBEDTLS_PADDING_NONE ) 107311fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 107411fa71b9SJerome Forissier 107511fa71b9SJerome Forissier return( 0 ); 107611fa71b9SJerome Forissier } 107711fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 107811fa71b9SJerome Forissier 1079817466cbSJens Wiklander switch( mode ) 1080817466cbSJens Wiklander { 1081817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 1082817466cbSJens Wiklander case MBEDTLS_PADDING_PKCS7: 1083817466cbSJens Wiklander ctx->add_padding = add_pkcs_padding; 1084817466cbSJens Wiklander ctx->get_padding = get_pkcs_padding; 1085817466cbSJens Wiklander break; 1086817466cbSJens Wiklander #endif 1087817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) 1088817466cbSJens Wiklander case MBEDTLS_PADDING_ONE_AND_ZEROS: 1089817466cbSJens Wiklander ctx->add_padding = add_one_and_zeros_padding; 1090817466cbSJens Wiklander ctx->get_padding = get_one_and_zeros_padding; 1091817466cbSJens Wiklander break; 1092817466cbSJens Wiklander #endif 1093817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) 1094817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS_AND_LEN: 1095817466cbSJens Wiklander ctx->add_padding = add_zeros_and_len_padding; 1096817466cbSJens Wiklander ctx->get_padding = get_zeros_and_len_padding; 1097817466cbSJens Wiklander break; 1098817466cbSJens Wiklander #endif 1099817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) 1100817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS: 1101817466cbSJens Wiklander ctx->add_padding = add_zeros_padding; 1102817466cbSJens Wiklander ctx->get_padding = get_zeros_padding; 1103817466cbSJens Wiklander break; 1104817466cbSJens Wiklander #endif 1105817466cbSJens Wiklander case MBEDTLS_PADDING_NONE: 1106817466cbSJens Wiklander ctx->add_padding = NULL; 1107817466cbSJens Wiklander ctx->get_padding = get_no_padding; 1108817466cbSJens Wiklander break; 1109817466cbSJens Wiklander 1110817466cbSJens Wiklander default: 1111817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1112817466cbSJens Wiklander } 1113817466cbSJens Wiklander 1114817466cbSJens Wiklander return( 0 ); 1115817466cbSJens Wiklander } 1116817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 1117817466cbSJens Wiklander 11183d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 1119817466cbSJens Wiklander int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, 1120817466cbSJens Wiklander unsigned char *tag, size_t tag_len ) 1121817466cbSJens Wiklander { 11223d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 11233d3b0591SJens Wiklander CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 11243d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 1125817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1126817466cbSJens Wiklander 1127817466cbSJens Wiklander if( MBEDTLS_ENCRYPT != ctx->operation ) 1128817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1129817466cbSJens Wiklander 113011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 113111fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 113211fa71b9SJerome Forissier { 113311fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 113411fa71b9SJerome Forissier * operations, we currently don't make it 113511fa71b9SJerome Forissier * accessible through the cipher layer. */ 113611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 113711fa71b9SJerome Forissier } 113811fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 113911fa71b9SJerome Forissier 11403d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 1141817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 11423d3b0591SJens Wiklander return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, 11433d3b0591SJens Wiklander tag, tag_len ) ); 11443d3b0591SJens Wiklander #endif 11453d3b0591SJens Wiklander 11463d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 11473d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 11483d3b0591SJens Wiklander { 11493d3b0591SJens Wiklander /* Don't allow truncated MAC for Poly1305 */ 11503d3b0591SJens Wiklander if ( tag_len != 16U ) 11513d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 11523d3b0591SJens Wiklander 115311fa71b9SJerome Forissier return( mbedtls_chachapoly_finish( 115411fa71b9SJerome Forissier (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) ); 11553d3b0591SJens Wiklander } 11563d3b0591SJens Wiklander #endif 1157817466cbSJens Wiklander 1158817466cbSJens Wiklander return( 0 ); 1159817466cbSJens Wiklander } 1160817466cbSJens Wiklander 1161817466cbSJens Wiklander int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, 1162817466cbSJens Wiklander const unsigned char *tag, size_t tag_len ) 1163817466cbSJens Wiklander { 11643d3b0591SJens Wiklander unsigned char check_tag[16]; 116511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1166817466cbSJens Wiklander 11673d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 11683d3b0591SJens Wiklander CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 11693d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 11703d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 11713d3b0591SJens Wiklander 11723d3b0591SJens Wiklander if( MBEDTLS_DECRYPT != ctx->operation ) 1173817466cbSJens Wiklander { 1174817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1175817466cbSJens Wiklander } 1176817466cbSJens Wiklander 117711fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 117811fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 117911fa71b9SJerome Forissier { 118011fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 118111fa71b9SJerome Forissier * operations, we currently don't make it 118211fa71b9SJerome Forissier * accessible through the cipher layer. */ 118311fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 118411fa71b9SJerome Forissier } 118511fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 118611fa71b9SJerome Forissier 11873d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 1188817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1189817466cbSJens Wiklander { 1190817466cbSJens Wiklander if( tag_len > sizeof( check_tag ) ) 1191817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1192817466cbSJens Wiklander 119311fa71b9SJerome Forissier if( 0 != ( ret = mbedtls_gcm_finish( 119411fa71b9SJerome Forissier (mbedtls_gcm_context *) ctx->cipher_ctx, 1195817466cbSJens Wiklander check_tag, tag_len ) ) ) 1196817466cbSJens Wiklander { 1197817466cbSJens Wiklander return( ret ); 1198817466cbSJens Wiklander } 1199817466cbSJens Wiklander 1200817466cbSJens Wiklander /* Check the tag in "constant-time" */ 12013d3b0591SJens Wiklander if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) 1202817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); 1203817466cbSJens Wiklander 1204817466cbSJens Wiklander return( 0 ); 1205817466cbSJens Wiklander } 12063d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C */ 12073d3b0591SJens Wiklander 12083d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 12093d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 12103d3b0591SJens Wiklander { 12113d3b0591SJens Wiklander /* Don't allow truncated MAC for Poly1305 */ 12123d3b0591SJens Wiklander if ( tag_len != sizeof( check_tag ) ) 12133d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 12143d3b0591SJens Wiklander 121511fa71b9SJerome Forissier ret = mbedtls_chachapoly_finish( 121611fa71b9SJerome Forissier (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag ); 12173d3b0591SJens Wiklander if ( ret != 0 ) 12183d3b0591SJens Wiklander { 12193d3b0591SJens Wiklander return( ret ); 12203d3b0591SJens Wiklander } 12213d3b0591SJens Wiklander 12223d3b0591SJens Wiklander /* Check the tag in "constant-time" */ 12233d3b0591SJens Wiklander if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) 12243d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); 1225817466cbSJens Wiklander 1226817466cbSJens Wiklander return( 0 ); 1227817466cbSJens Wiklander } 12283d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 12293d3b0591SJens Wiklander 12303d3b0591SJens Wiklander return( 0 ); 12313d3b0591SJens Wiklander } 12323d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 1233817466cbSJens Wiklander 1234817466cbSJens Wiklander /* 1235817466cbSJens Wiklander * Packet-oriented wrapper for non-AEAD modes 1236817466cbSJens Wiklander */ 1237817466cbSJens Wiklander int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, 1238817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1239817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1240817466cbSJens Wiklander unsigned char *output, size_t *olen ) 1241817466cbSJens Wiklander { 124211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1243817466cbSJens Wiklander size_t finish_olen; 1244817466cbSJens Wiklander 12453d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 12463d3b0591SJens Wiklander CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 12473d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 12483d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 12493d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 12503d3b0591SJens Wiklander 125111fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 125211fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 125311fa71b9SJerome Forissier { 125411fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 125511fa71b9SJerome Forissier * a key has been set. If not, the key slot will 125611fa71b9SJerome Forissier * still be in its default state of 0, which is 125711fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 125811fa71b9SJerome Forissier * below will gracefully fail. */ 125911fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 126011fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 126111fa71b9SJerome Forissier 126211fa71b9SJerome Forissier psa_status_t status; 126311fa71b9SJerome Forissier psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; 126411fa71b9SJerome Forissier size_t part_len; 126511fa71b9SJerome Forissier 126611fa71b9SJerome Forissier if( ctx->operation == MBEDTLS_DECRYPT ) 126711fa71b9SJerome Forissier { 126811fa71b9SJerome Forissier status = psa_cipher_decrypt_setup( &cipher_op, 126911fa71b9SJerome Forissier cipher_psa->slot, 127011fa71b9SJerome Forissier cipher_psa->alg ); 127111fa71b9SJerome Forissier } 127211fa71b9SJerome Forissier else if( ctx->operation == MBEDTLS_ENCRYPT ) 127311fa71b9SJerome Forissier { 127411fa71b9SJerome Forissier status = psa_cipher_encrypt_setup( &cipher_op, 127511fa71b9SJerome Forissier cipher_psa->slot, 127611fa71b9SJerome Forissier cipher_psa->alg ); 127711fa71b9SJerome Forissier } 127811fa71b9SJerome Forissier else 127911fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 128011fa71b9SJerome Forissier 128111fa71b9SJerome Forissier /* In the following, we can immediately return on an error, 128211fa71b9SJerome Forissier * because the PSA Crypto API guarantees that cipher operations 128311fa71b9SJerome Forissier * are terminated by unsuccessful calls to psa_cipher_update(), 128411fa71b9SJerome Forissier * and by any call to psa_cipher_finish(). */ 128511fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 128611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 128711fa71b9SJerome Forissier 128811fa71b9SJerome Forissier status = psa_cipher_set_iv( &cipher_op, iv, iv_len ); 128911fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 129011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 129111fa71b9SJerome Forissier 129211fa71b9SJerome Forissier status = psa_cipher_update( &cipher_op, 129311fa71b9SJerome Forissier input, ilen, 129411fa71b9SJerome Forissier output, ilen, olen ); 129511fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 129611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 129711fa71b9SJerome Forissier 129811fa71b9SJerome Forissier status = psa_cipher_finish( &cipher_op, 129911fa71b9SJerome Forissier output + *olen, ilen - *olen, 130011fa71b9SJerome Forissier &part_len ); 130111fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 130211fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 130311fa71b9SJerome Forissier 130411fa71b9SJerome Forissier *olen += part_len; 130511fa71b9SJerome Forissier return( 0 ); 130611fa71b9SJerome Forissier } 130711fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 130811fa71b9SJerome Forissier 1309817466cbSJens Wiklander if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) 1310817466cbSJens Wiklander return( ret ); 1311817466cbSJens Wiklander 1312817466cbSJens Wiklander if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) 1313817466cbSJens Wiklander return( ret ); 1314817466cbSJens Wiklander 131511fa71b9SJerome Forissier if( ( ret = mbedtls_cipher_update( ctx, input, ilen, 131611fa71b9SJerome Forissier output, olen ) ) != 0 ) 1317817466cbSJens Wiklander return( ret ); 1318817466cbSJens Wiklander 131911fa71b9SJerome Forissier if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, 132011fa71b9SJerome Forissier &finish_olen ) ) != 0 ) 1321817466cbSJens Wiklander return( ret ); 1322817466cbSJens Wiklander 1323817466cbSJens Wiklander *olen += finish_olen; 1324817466cbSJens Wiklander 1325817466cbSJens Wiklander return( 0 ); 1326817466cbSJens Wiklander } 1327817466cbSJens Wiklander 1328817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_AEAD) 1329817466cbSJens Wiklander /* 1330*7901324dSJerome Forissier * Packet-oriented encryption for AEAD modes: internal function shared by 1331*7901324dSJerome Forissier * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext(). 1332817466cbSJens Wiklander */ 1333*7901324dSJerome Forissier static int mbedtls_cipher_aead_encrypt( mbedtls_cipher_context_t *ctx, 1334817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1335817466cbSJens Wiklander const unsigned char *ad, size_t ad_len, 1336817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1337817466cbSJens Wiklander unsigned char *output, size_t *olen, 1338817466cbSJens Wiklander unsigned char *tag, size_t tag_len ) 1339817466cbSJens Wiklander { 134011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 134111fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 134211fa71b9SJerome Forissier { 134311fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 134411fa71b9SJerome Forissier * a key has been set. If not, the key slot will 134511fa71b9SJerome Forissier * still be in its default state of 0, which is 134611fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 134711fa71b9SJerome Forissier * below will gracefully fail. */ 134811fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 134911fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 135011fa71b9SJerome Forissier 135111fa71b9SJerome Forissier psa_status_t status; 135211fa71b9SJerome Forissier 135311fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag 135411fa71b9SJerome Forissier * at the end of the encrypted message. */ 1355*7901324dSJerome Forissier if( output == NULL || tag != output + ilen ) 135611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 135711fa71b9SJerome Forissier 135811fa71b9SJerome Forissier status = psa_aead_encrypt( cipher_psa->slot, 135911fa71b9SJerome Forissier cipher_psa->alg, 136011fa71b9SJerome Forissier iv, iv_len, 136111fa71b9SJerome Forissier ad, ad_len, 136211fa71b9SJerome Forissier input, ilen, 136311fa71b9SJerome Forissier output, ilen + tag_len, olen ); 136411fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 136511fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 136611fa71b9SJerome Forissier 136711fa71b9SJerome Forissier *olen -= tag_len; 136811fa71b9SJerome Forissier return( 0 ); 136911fa71b9SJerome Forissier } 137011fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 137111fa71b9SJerome Forissier 1372817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 1373817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1374817466cbSJens Wiklander { 1375817466cbSJens Wiklander *olen = ilen; 137611fa71b9SJerome Forissier return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, 137711fa71b9SJerome Forissier ilen, iv, iv_len, ad, ad_len, 137811fa71b9SJerome Forissier input, output, tag_len, tag ) ); 1379817466cbSJens Wiklander } 1380817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1381817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 1382817466cbSJens Wiklander if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) 1383817466cbSJens Wiklander { 1384817466cbSJens Wiklander *olen = ilen; 1385817466cbSJens Wiklander return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, 1386817466cbSJens Wiklander iv, iv_len, ad, ad_len, input, output, 1387817466cbSJens Wiklander tag, tag_len ) ); 1388817466cbSJens Wiklander } 1389817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */ 13903d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 13913d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 13923d3b0591SJens Wiklander { 13933d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */ 13943d3b0591SJens Wiklander if ( ( iv_len != ctx->cipher_info->iv_size ) || 13953d3b0591SJens Wiklander ( tag_len != 16U ) ) 13963d3b0591SJens Wiklander { 13973d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 13983d3b0591SJens Wiklander } 13993d3b0591SJens Wiklander 14003d3b0591SJens Wiklander *olen = ilen; 14013d3b0591SJens Wiklander return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, 14023d3b0591SJens Wiklander ilen, iv, ad, ad_len, input, output, tag ) ); 14033d3b0591SJens Wiklander } 14043d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 1405817466cbSJens Wiklander 1406817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1407817466cbSJens Wiklander } 1408817466cbSJens Wiklander 1409817466cbSJens Wiklander /* 1410*7901324dSJerome Forissier * Packet-oriented encryption for AEAD modes: internal function shared by 1411*7901324dSJerome Forissier * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext(). 1412817466cbSJens Wiklander */ 1413*7901324dSJerome Forissier static int mbedtls_cipher_aead_decrypt( mbedtls_cipher_context_t *ctx, 1414817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1415817466cbSJens Wiklander const unsigned char *ad, size_t ad_len, 1416817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1417817466cbSJens Wiklander unsigned char *output, size_t *olen, 1418817466cbSJens Wiklander const unsigned char *tag, size_t tag_len ) 1419817466cbSJens Wiklander { 142011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 142111fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 142211fa71b9SJerome Forissier { 142311fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 142411fa71b9SJerome Forissier * a key has been set. If not, the key slot will 142511fa71b9SJerome Forissier * still be in its default state of 0, which is 142611fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 142711fa71b9SJerome Forissier * below will gracefully fail. */ 142811fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 142911fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 143011fa71b9SJerome Forissier 143111fa71b9SJerome Forissier psa_status_t status; 143211fa71b9SJerome Forissier 143311fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag 143411fa71b9SJerome Forissier * at the end of the encrypted message. */ 1435*7901324dSJerome Forissier if( input == NULL || tag != input + ilen ) 143611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 143711fa71b9SJerome Forissier 143811fa71b9SJerome Forissier status = psa_aead_decrypt( cipher_psa->slot, 143911fa71b9SJerome Forissier cipher_psa->alg, 144011fa71b9SJerome Forissier iv, iv_len, 144111fa71b9SJerome Forissier ad, ad_len, 144211fa71b9SJerome Forissier input, ilen + tag_len, 144311fa71b9SJerome Forissier output, ilen, olen ); 144411fa71b9SJerome Forissier if( status == PSA_ERROR_INVALID_SIGNATURE ) 144511fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); 144611fa71b9SJerome Forissier else if( status != PSA_SUCCESS ) 144711fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 144811fa71b9SJerome Forissier 144911fa71b9SJerome Forissier return( 0 ); 145011fa71b9SJerome Forissier } 145111fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 145211fa71b9SJerome Forissier 1453817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 1454817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1455817466cbSJens Wiklander { 145611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1457817466cbSJens Wiklander 1458817466cbSJens Wiklander *olen = ilen; 1459817466cbSJens Wiklander ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, 1460817466cbSJens Wiklander iv, iv_len, ad, ad_len, 1461817466cbSJens Wiklander tag, tag_len, input, output ); 1462817466cbSJens Wiklander 1463817466cbSJens Wiklander if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) 1464817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1465817466cbSJens Wiklander 1466817466cbSJens Wiklander return( ret ); 1467817466cbSJens Wiklander } 1468817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1469817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 1470817466cbSJens Wiklander if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) 1471817466cbSJens Wiklander { 147211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1473817466cbSJens Wiklander 1474817466cbSJens Wiklander *olen = ilen; 1475817466cbSJens Wiklander ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, 1476817466cbSJens Wiklander iv, iv_len, ad, ad_len, 1477817466cbSJens Wiklander input, output, tag, tag_len ); 1478817466cbSJens Wiklander 1479817466cbSJens Wiklander if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) 1480817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1481817466cbSJens Wiklander 1482817466cbSJens Wiklander return( ret ); 1483817466cbSJens Wiklander } 1484817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */ 14853d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 14863d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 14873d3b0591SJens Wiklander { 148811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 14893d3b0591SJens Wiklander 14903d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */ 14913d3b0591SJens Wiklander if ( ( iv_len != ctx->cipher_info->iv_size ) || 14923d3b0591SJens Wiklander ( tag_len != 16U ) ) 14933d3b0591SJens Wiklander { 14943d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 14953d3b0591SJens Wiklander } 14963d3b0591SJens Wiklander 14973d3b0591SJens Wiklander *olen = ilen; 14983d3b0591SJens Wiklander ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, 14993d3b0591SJens Wiklander iv, ad, ad_len, tag, input, output ); 15003d3b0591SJens Wiklander 15013d3b0591SJens Wiklander if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) 15023d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 15033d3b0591SJens Wiklander 15043d3b0591SJens Wiklander return( ret ); 15053d3b0591SJens Wiklander } 15063d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 1507*7901324dSJerome Forissier 1508*7901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1509*7901324dSJerome Forissier } 1510*7901324dSJerome Forissier 1511*7901324dSJerome Forissier #if !defined(MBEDTLS_DEPRECATED_REMOVED) 1512*7901324dSJerome Forissier /* 1513*7901324dSJerome Forissier * Packet-oriented encryption for AEAD modes: public legacy function. 1514*7901324dSJerome Forissier */ 1515*7901324dSJerome Forissier int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, 1516*7901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 1517*7901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 1518*7901324dSJerome Forissier const unsigned char *input, size_t ilen, 1519*7901324dSJerome Forissier unsigned char *output, size_t *olen, 1520*7901324dSJerome Forissier unsigned char *tag, size_t tag_len ) 1521*7901324dSJerome Forissier { 1522*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ctx != NULL ); 1523*7901324dSJerome Forissier CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 1524*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 1525*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 1526*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || output != NULL ); 1527*7901324dSJerome Forissier CIPHER_VALIDATE_RET( olen != NULL ); 1528*7901324dSJerome Forissier CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 1529*7901324dSJerome Forissier 1530*7901324dSJerome Forissier return( mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len, 1531*7901324dSJerome Forissier input, ilen, output, olen, 1532*7901324dSJerome Forissier tag, tag_len ) ); 1533*7901324dSJerome Forissier } 1534*7901324dSJerome Forissier 1535*7901324dSJerome Forissier /* 1536*7901324dSJerome Forissier * Packet-oriented decryption for AEAD modes: public legacy function. 1537*7901324dSJerome Forissier */ 1538*7901324dSJerome Forissier int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, 1539*7901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 1540*7901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 1541*7901324dSJerome Forissier const unsigned char *input, size_t ilen, 1542*7901324dSJerome Forissier unsigned char *output, size_t *olen, 1543*7901324dSJerome Forissier const unsigned char *tag, size_t tag_len ) 1544*7901324dSJerome Forissier { 1545*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ctx != NULL ); 1546*7901324dSJerome Forissier CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 1547*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 1548*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 1549*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || output != NULL ); 1550*7901324dSJerome Forissier CIPHER_VALIDATE_RET( olen != NULL ); 1551*7901324dSJerome Forissier CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 1552*7901324dSJerome Forissier 1553*7901324dSJerome Forissier return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len, 1554*7901324dSJerome Forissier input, ilen, output, olen, 1555*7901324dSJerome Forissier tag, tag_len ) ); 1556*7901324dSJerome Forissier } 1557*7901324dSJerome Forissier #endif /* !MBEDTLS_DEPRECATED_REMOVED */ 1558*7901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 1559*7901324dSJerome Forissier 1560*7901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) 1561*7901324dSJerome Forissier /* 1562*7901324dSJerome Forissier * Packet-oriented encryption for AEAD/NIST_KW: public function. 1563*7901324dSJerome Forissier */ 1564*7901324dSJerome Forissier int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx, 1565*7901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 1566*7901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 1567*7901324dSJerome Forissier const unsigned char *input, size_t ilen, 1568*7901324dSJerome Forissier unsigned char *output, size_t output_len, 1569*7901324dSJerome Forissier size_t *olen, size_t tag_len ) 1570*7901324dSJerome Forissier { 1571*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ctx != NULL ); 1572*7901324dSJerome Forissier CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 1573*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 1574*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 1575*7901324dSJerome Forissier CIPHER_VALIDATE_RET( output != NULL ); 1576*7901324dSJerome Forissier CIPHER_VALIDATE_RET( olen != NULL ); 1577*7901324dSJerome Forissier 157811fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 1579*7901324dSJerome Forissier if( 1580*7901324dSJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1581*7901324dSJerome Forissier ctx->psa_enabled == 0 && 1582*7901324dSJerome Forissier #endif 1583*7901324dSJerome Forissier ( MBEDTLS_MODE_KW == ctx->cipher_info->mode || 1584*7901324dSJerome Forissier MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) ) 158511fa71b9SJerome Forissier { 158611fa71b9SJerome Forissier mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? 158711fa71b9SJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; 158811fa71b9SJerome Forissier 1589*7901324dSJerome Forissier /* There is no iv, tag or ad associated with KW and KWP, 1590*7901324dSJerome Forissier * so these length should be 0 as documented. */ 159111fa71b9SJerome Forissier if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) 159211fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 159311fa71b9SJerome Forissier 1594*7901324dSJerome Forissier (void) iv; 1595*7901324dSJerome Forissier (void) ad; 1596*7901324dSJerome Forissier 1597*7901324dSJerome Forissier return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen, 1598*7901324dSJerome Forissier output, olen, output_len ) ); 159911fa71b9SJerome Forissier } 160011fa71b9SJerome Forissier #endif /* MBEDTLS_NIST_KW_C */ 1601817466cbSJens Wiklander 1602*7901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) 1603*7901324dSJerome Forissier /* AEAD case: check length before passing on to shared function */ 1604*7901324dSJerome Forissier if( output_len < ilen + tag_len ) 1605*7901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1606*7901324dSJerome Forissier 1607*7901324dSJerome Forissier int ret = mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len, 1608*7901324dSJerome Forissier input, ilen, output, olen, 1609*7901324dSJerome Forissier output + ilen, tag_len ); 1610*7901324dSJerome Forissier *olen += tag_len; 1611*7901324dSJerome Forissier return( ret ); 1612*7901324dSJerome Forissier #else 1613817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1614817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 1615*7901324dSJerome Forissier } 1616*7901324dSJerome Forissier 1617*7901324dSJerome Forissier /* 1618*7901324dSJerome Forissier * Packet-oriented decryption for AEAD/NIST_KW: public function. 1619*7901324dSJerome Forissier */ 1620*7901324dSJerome Forissier int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx, 1621*7901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 1622*7901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 1623*7901324dSJerome Forissier const unsigned char *input, size_t ilen, 1624*7901324dSJerome Forissier unsigned char *output, size_t output_len, 1625*7901324dSJerome Forissier size_t *olen, size_t tag_len ) 1626*7901324dSJerome Forissier { 1627*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ctx != NULL ); 1628*7901324dSJerome Forissier CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 1629*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 1630*7901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 1631*7901324dSJerome Forissier CIPHER_VALIDATE_RET( output_len == 0 || output != NULL ); 1632*7901324dSJerome Forissier CIPHER_VALIDATE_RET( olen != NULL ); 1633*7901324dSJerome Forissier 1634*7901324dSJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 1635*7901324dSJerome Forissier if( 1636*7901324dSJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1637*7901324dSJerome Forissier ctx->psa_enabled == 0 && 1638*7901324dSJerome Forissier #endif 1639*7901324dSJerome Forissier ( MBEDTLS_MODE_KW == ctx->cipher_info->mode || 1640*7901324dSJerome Forissier MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) ) 1641*7901324dSJerome Forissier { 1642*7901324dSJerome Forissier mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? 1643*7901324dSJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; 1644*7901324dSJerome Forissier 1645*7901324dSJerome Forissier /* There is no iv, tag or ad associated with KW and KWP, 1646*7901324dSJerome Forissier * so these length should be 0 as documented. */ 1647*7901324dSJerome Forissier if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) 1648*7901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1649*7901324dSJerome Forissier 1650*7901324dSJerome Forissier (void) iv; 1651*7901324dSJerome Forissier (void) ad; 1652*7901324dSJerome Forissier 1653*7901324dSJerome Forissier return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen, 1654*7901324dSJerome Forissier output, olen, output_len ) ); 1655*7901324dSJerome Forissier } 1656*7901324dSJerome Forissier #endif /* MBEDTLS_NIST_KW_C */ 1657*7901324dSJerome Forissier 1658*7901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) 1659*7901324dSJerome Forissier /* AEAD case: check length before passing on to shared function */ 1660*7901324dSJerome Forissier if( ilen < tag_len || output_len < ilen - tag_len ) 1661*7901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1662*7901324dSJerome Forissier 1663*7901324dSJerome Forissier return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len, 1664*7901324dSJerome Forissier input, ilen - tag_len, output, olen, 1665*7901324dSJerome Forissier input + ilen - tag_len, tag_len ) ); 1666*7901324dSJerome Forissier #else 1667*7901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1668*7901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 1669*7901324dSJerome Forissier } 1670*7901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ 1671817466cbSJens Wiklander 1672817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_C */ 1673