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 * 87901324dSJerome Forissier * Copyright The Mbed TLS Contributors 97901324dSJerome 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 247901324dSJerome 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" 32*039e02dfSJerome Forissier #include "mbedtls/constant_time.h" 33817466cbSJens Wiklander 34817466cbSJens Wiklander #include <stdlib.h> 35817466cbSJens Wiklander #include <string.h> 36817466cbSJens Wiklander 373d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 383d3b0591SJens Wiklander #include "mbedtls/chachapoly.h" 393d3b0591SJens Wiklander #endif 403d3b0591SJens Wiklander 41817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 42817466cbSJens Wiklander #include "mbedtls/gcm.h" 43817466cbSJens Wiklander #endif 44817466cbSJens Wiklander 45817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 46817466cbSJens Wiklander #include "mbedtls/ccm.h" 47817466cbSJens Wiklander #endif 48817466cbSJens Wiklander 493d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C) 503d3b0591SJens Wiklander #include "mbedtls/chacha20.h" 513d3b0591SJens Wiklander #endif 523d3b0591SJens Wiklander 53817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C) 54817466cbSJens Wiklander #include "mbedtls/cmac.h" 55817466cbSJens Wiklander #endif 56817466cbSJens Wiklander 5711fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 5811fa71b9SJerome Forissier #include "psa/crypto.h" 5911fa71b9SJerome Forissier #include "mbedtls/psa_util.h" 6011fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 6111fa71b9SJerome Forissier 6211fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 6311fa71b9SJerome Forissier #include "mbedtls/nist_kw.h" 6411fa71b9SJerome Forissier #endif 6511fa71b9SJerome Forissier 66817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 67817466cbSJens Wiklander #include "mbedtls/platform.h" 68817466cbSJens Wiklander #else 69817466cbSJens Wiklander #define mbedtls_calloc calloc 70817466cbSJens Wiklander #define mbedtls_free free 71817466cbSJens Wiklander #endif 72817466cbSJens Wiklander 733d3b0591SJens Wiklander #define CIPHER_VALIDATE_RET( cond ) \ 743d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) 753d3b0591SJens Wiklander #define CIPHER_VALIDATE( cond ) \ 763d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE( cond ) 77817466cbSJens Wiklander 78817466cbSJens Wiklander static int supported_init = 0; 79817466cbSJens Wiklander 80817466cbSJens Wiklander const int *mbedtls_cipher_list( void ) 81817466cbSJens Wiklander { 82817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 83817466cbSJens Wiklander int *type; 84817466cbSJens Wiklander 85817466cbSJens Wiklander if( ! supported_init ) 86817466cbSJens Wiklander { 87817466cbSJens Wiklander def = mbedtls_cipher_definitions; 88817466cbSJens Wiklander type = mbedtls_cipher_supported; 89817466cbSJens Wiklander 90817466cbSJens Wiklander while( def->type != 0 ) 91817466cbSJens Wiklander *type++ = (*def++).type; 92817466cbSJens Wiklander 93817466cbSJens Wiklander *type = 0; 94817466cbSJens Wiklander 95817466cbSJens Wiklander supported_init = 1; 96817466cbSJens Wiklander } 97817466cbSJens Wiklander 98817466cbSJens Wiklander return( mbedtls_cipher_supported ); 99817466cbSJens Wiklander } 100817466cbSJens Wiklander 10111fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( 10211fa71b9SJerome Forissier const mbedtls_cipher_type_t cipher_type ) 103817466cbSJens Wiklander { 104817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 105817466cbSJens Wiklander 106817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 107817466cbSJens Wiklander if( def->type == cipher_type ) 108817466cbSJens Wiklander return( def->info ); 109817466cbSJens Wiklander 110817466cbSJens Wiklander return( NULL ); 111817466cbSJens Wiklander } 112817466cbSJens Wiklander 11311fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( 11411fa71b9SJerome Forissier const char *cipher_name ) 115817466cbSJens Wiklander { 116817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 117817466cbSJens Wiklander 118817466cbSJens Wiklander if( NULL == cipher_name ) 119817466cbSJens Wiklander return( NULL ); 120817466cbSJens Wiklander 121817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 122817466cbSJens Wiklander if( ! strcmp( def->info->name, cipher_name ) ) 123817466cbSJens Wiklander return( def->info ); 124817466cbSJens Wiklander 125817466cbSJens Wiklander return( NULL ); 126817466cbSJens Wiklander } 127817466cbSJens Wiklander 12811fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( 12911fa71b9SJerome Forissier const mbedtls_cipher_id_t cipher_id, 130817466cbSJens Wiklander int key_bitlen, 131817466cbSJens Wiklander const mbedtls_cipher_mode_t mode ) 132817466cbSJens Wiklander { 133817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 134817466cbSJens Wiklander 135817466cbSJens Wiklander for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) 136817466cbSJens Wiklander if( def->info->base->cipher == cipher_id && 137817466cbSJens Wiklander def->info->key_bitlen == (unsigned) key_bitlen && 138817466cbSJens Wiklander def->info->mode == mode ) 139817466cbSJens Wiklander return( def->info ); 140817466cbSJens Wiklander 141817466cbSJens Wiklander return( NULL ); 142817466cbSJens Wiklander } 143817466cbSJens Wiklander 144817466cbSJens Wiklander void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) 145817466cbSJens Wiklander { 1463d3b0591SJens Wiklander CIPHER_VALIDATE( ctx != NULL ); 147817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 148817466cbSJens Wiklander } 149817466cbSJens Wiklander 150817466cbSJens Wiklander void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) 151817466cbSJens Wiklander { 152817466cbSJens Wiklander if( ctx == NULL ) 153817466cbSJens Wiklander return; 154817466cbSJens Wiklander 15511fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 15611fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 15711fa71b9SJerome Forissier { 15811fa71b9SJerome Forissier if( ctx->cipher_ctx != NULL ) 15911fa71b9SJerome Forissier { 16011fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 16111fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 16211fa71b9SJerome Forissier 16311fa71b9SJerome Forissier if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED ) 16411fa71b9SJerome Forissier { 16511fa71b9SJerome Forissier /* xxx_free() doesn't allow to return failures. */ 16611fa71b9SJerome Forissier (void) psa_destroy_key( cipher_psa->slot ); 16711fa71b9SJerome Forissier } 16811fa71b9SJerome Forissier 16911fa71b9SJerome Forissier mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) ); 17011fa71b9SJerome Forissier mbedtls_free( cipher_psa ); 17111fa71b9SJerome Forissier } 17211fa71b9SJerome Forissier 17311fa71b9SJerome Forissier mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); 17411fa71b9SJerome Forissier return; 17511fa71b9SJerome Forissier } 17611fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 17711fa71b9SJerome Forissier 178817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C) 179817466cbSJens Wiklander if( ctx->cmac_ctx ) 180817466cbSJens Wiklander { 1813d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx->cmac_ctx, 1823d3b0591SJens Wiklander sizeof( mbedtls_cmac_context_t ) ); 183817466cbSJens Wiklander mbedtls_free( ctx->cmac_ctx ); 184817466cbSJens Wiklander } 185817466cbSJens Wiklander #endif 186817466cbSJens Wiklander 187817466cbSJens Wiklander if( ctx->cipher_ctx ) 188817466cbSJens Wiklander ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); 189817466cbSJens Wiklander 1903d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); 191817466cbSJens Wiklander } 192817466cbSJens Wiklander 19312484fc7SEdison Ai int mbedtls_cipher_clone( mbedtls_cipher_context_t *dst, 19412484fc7SEdison Ai const mbedtls_cipher_context_t *src ) 19512484fc7SEdison Ai { 19612484fc7SEdison Ai if( dst == NULL || dst->cipher_info == NULL || 19712484fc7SEdison Ai src == NULL || src->cipher_info == NULL) 19812484fc7SEdison Ai { 19912484fc7SEdison Ai return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 20012484fc7SEdison Ai } 20112484fc7SEdison Ai 20212484fc7SEdison Ai dst->cipher_info = src->cipher_info; 20312484fc7SEdison Ai dst->key_bitlen = src->key_bitlen; 20412484fc7SEdison Ai dst->operation = src->operation; 20512484fc7SEdison Ai #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 20612484fc7SEdison Ai dst->add_padding = src->add_padding; 20712484fc7SEdison Ai dst->get_padding = src->get_padding; 20812484fc7SEdison Ai #endif 20912484fc7SEdison Ai memcpy( dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH ); 21012484fc7SEdison Ai dst->unprocessed_len = src->unprocessed_len; 21112484fc7SEdison Ai memcpy( dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH ); 21212484fc7SEdison Ai dst->iv_size = src->iv_size; 21312484fc7SEdison Ai if( dst->cipher_info->base->ctx_clone_func ) 21412484fc7SEdison Ai dst->cipher_info->base->ctx_clone_func( dst->cipher_ctx, src->cipher_ctx ); 21512484fc7SEdison Ai 21612484fc7SEdison Ai #if defined(MBEDTLS_CMAC_C) 21712484fc7SEdison Ai if( dst->cmac_ctx != NULL && src->cmac_ctx != NULL ) 21812484fc7SEdison Ai memcpy( dst->cmac_ctx, src->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); 21912484fc7SEdison Ai #endif 22012484fc7SEdison Ai return( 0 ); 22112484fc7SEdison Ai } 22212484fc7SEdison Ai 22311fa71b9SJerome Forissier int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, 22411fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info ) 225817466cbSJens Wiklander { 2263d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 2273d3b0591SJens Wiklander if( cipher_info == NULL ) 228817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 229817466cbSJens Wiklander 230817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 231817466cbSJens Wiklander 232817466cbSJens Wiklander if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) 233817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 234817466cbSJens Wiklander 235817466cbSJens Wiklander ctx->cipher_info = cipher_info; 236817466cbSJens Wiklander 237817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 238817466cbSJens Wiklander /* 239817466cbSJens Wiklander * Ignore possible errors caused by a cipher mode that doesn't use padding 240817466cbSJens Wiklander */ 241817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 242817466cbSJens Wiklander (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); 243817466cbSJens Wiklander #else 244817466cbSJens Wiklander (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); 245817466cbSJens Wiklander #endif 246817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 247817466cbSJens Wiklander 248817466cbSJens Wiklander return( 0 ); 249817466cbSJens Wiklander } 250817466cbSJens Wiklander 25111fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 25211fa71b9SJerome Forissier int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, 25311fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info, 25411fa71b9SJerome Forissier size_t taglen ) 25511fa71b9SJerome Forissier { 25611fa71b9SJerome Forissier psa_algorithm_t alg; 25711fa71b9SJerome Forissier mbedtls_cipher_context_psa *cipher_psa; 25811fa71b9SJerome Forissier 25911fa71b9SJerome Forissier if( NULL == cipher_info || NULL == ctx ) 26011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 26111fa71b9SJerome Forissier 26211fa71b9SJerome Forissier /* Check that the underlying cipher mode and cipher type are 26311fa71b9SJerome Forissier * supported by the underlying PSA Crypto implementation. */ 26411fa71b9SJerome Forissier alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen ); 26511fa71b9SJerome Forissier if( alg == 0 ) 26611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 26711fa71b9SJerome Forissier if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 ) 26811fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 26911fa71b9SJerome Forissier 27011fa71b9SJerome Forissier memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); 27111fa71b9SJerome Forissier 27211fa71b9SJerome Forissier cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) ); 27311fa71b9SJerome Forissier if( cipher_psa == NULL ) 27411fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 27511fa71b9SJerome Forissier cipher_psa->alg = alg; 27611fa71b9SJerome Forissier ctx->cipher_ctx = cipher_psa; 27711fa71b9SJerome Forissier ctx->cipher_info = cipher_info; 27811fa71b9SJerome Forissier ctx->psa_enabled = 1; 27911fa71b9SJerome Forissier return( 0 ); 28011fa71b9SJerome Forissier } 28111fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 28211fa71b9SJerome Forissier 28312484fc7SEdison Ai int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) 28412484fc7SEdison Ai { 28512484fc7SEdison Ai if( NULL == cipher_info || NULL == ctx ) 28612484fc7SEdison Ai return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 28712484fc7SEdison Ai 28812484fc7SEdison Ai ctx->cipher_info = cipher_info; 28912484fc7SEdison Ai return( 0 ); 29012484fc7SEdison Ai } 29112484fc7SEdison Ai 2923d3b0591SJens Wiklander int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, 2933d3b0591SJens Wiklander const unsigned char *key, 2943d3b0591SJens Wiklander int key_bitlen, 2953d3b0591SJens Wiklander const mbedtls_operation_t operation ) 296817466cbSJens Wiklander { 2973d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 2983d3b0591SJens Wiklander CIPHER_VALIDATE_RET( key != NULL ); 2993d3b0591SJens Wiklander CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || 3003d3b0591SJens Wiklander operation == MBEDTLS_DECRYPT ); 3013d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 302817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 303817466cbSJens Wiklander 30411fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 30511fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 30611fa71b9SJerome Forissier { 30711fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 30811fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 30911fa71b9SJerome Forissier 31011fa71b9SJerome Forissier size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8; 31111fa71b9SJerome Forissier 31211fa71b9SJerome Forissier psa_status_t status; 31311fa71b9SJerome Forissier psa_key_type_t key_type; 31411fa71b9SJerome Forissier psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 31511fa71b9SJerome Forissier 31611fa71b9SJerome Forissier /* PSA Crypto API only accepts byte-aligned keys. */ 31711fa71b9SJerome Forissier if( key_bitlen % 8 != 0 ) 31811fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 31911fa71b9SJerome Forissier 32011fa71b9SJerome Forissier /* Don't allow keys to be set multiple times. */ 32111fa71b9SJerome Forissier if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET ) 32211fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 32311fa71b9SJerome Forissier 32411fa71b9SJerome Forissier key_type = mbedtls_psa_translate_cipher_type( 32511fa71b9SJerome Forissier ctx->cipher_info->type ); 32611fa71b9SJerome Forissier if( key_type == 0 ) 32711fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 32811fa71b9SJerome Forissier psa_set_key_type( &attributes, key_type ); 32911fa71b9SJerome Forissier 33011fa71b9SJerome Forissier /* Mbed TLS' cipher layer doesn't enforce the mode of operation 33111fa71b9SJerome Forissier * (encrypt vs. decrypt): it is possible to setup a key for encryption 33211fa71b9SJerome Forissier * and use it for AEAD decryption. Until tests relying on this 33311fa71b9SJerome Forissier * are changed, allow any usage in PSA. */ 33411fa71b9SJerome Forissier psa_set_key_usage_flags( &attributes, 33511fa71b9SJerome Forissier /* mbedtls_psa_translate_cipher_operation( operation ); */ 33611fa71b9SJerome Forissier PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); 33711fa71b9SJerome Forissier psa_set_key_algorithm( &attributes, cipher_psa->alg ); 33811fa71b9SJerome Forissier 33911fa71b9SJerome Forissier status = psa_import_key( &attributes, key, key_bytelen, 34011fa71b9SJerome Forissier &cipher_psa->slot ); 34111fa71b9SJerome Forissier switch( status ) 34211fa71b9SJerome Forissier { 34311fa71b9SJerome Forissier case PSA_SUCCESS: 34411fa71b9SJerome Forissier break; 34511fa71b9SJerome Forissier case PSA_ERROR_INSUFFICIENT_MEMORY: 34611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 34711fa71b9SJerome Forissier case PSA_ERROR_NOT_SUPPORTED: 34811fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 34911fa71b9SJerome Forissier default: 35011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 35111fa71b9SJerome Forissier } 35211fa71b9SJerome Forissier /* Indicate that we own the key slot and need to 35311fa71b9SJerome Forissier * destroy it in mbedtls_cipher_free(). */ 35411fa71b9SJerome Forissier cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; 35511fa71b9SJerome Forissier 35611fa71b9SJerome Forissier ctx->key_bitlen = key_bitlen; 35711fa71b9SJerome Forissier ctx->operation = operation; 35811fa71b9SJerome Forissier return( 0 ); 35911fa71b9SJerome Forissier } 36011fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 36111fa71b9SJerome Forissier 362817466cbSJens Wiklander if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && 363817466cbSJens Wiklander (int) ctx->cipher_info->key_bitlen != key_bitlen ) 364817466cbSJens Wiklander { 365817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 366817466cbSJens Wiklander } 367817466cbSJens Wiklander 368817466cbSJens Wiklander ctx->key_bitlen = key_bitlen; 369817466cbSJens Wiklander ctx->operation = operation; 370817466cbSJens Wiklander 371817466cbSJens Wiklander /* 3723d3b0591SJens Wiklander * For OFB, CFB and CTR mode always use the encryption key schedule 373817466cbSJens Wiklander */ 374817466cbSJens Wiklander if( MBEDTLS_ENCRYPT == operation || 375817466cbSJens Wiklander MBEDTLS_MODE_CFB == ctx->cipher_info->mode || 3763d3b0591SJens Wiklander MBEDTLS_MODE_OFB == ctx->cipher_info->mode || 377817466cbSJens Wiklander MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) 378817466cbSJens Wiklander { 3793d3b0591SJens Wiklander return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, 3803d3b0591SJens Wiklander ctx->key_bitlen ) ); 381817466cbSJens Wiklander } 382817466cbSJens Wiklander 383817466cbSJens Wiklander if( MBEDTLS_DECRYPT == operation ) 3843d3b0591SJens Wiklander return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, 3853d3b0591SJens Wiklander ctx->key_bitlen ) ); 386817466cbSJens Wiklander 387817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 388817466cbSJens Wiklander } 389817466cbSJens Wiklander 390817466cbSJens Wiklander int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, 3913d3b0591SJens Wiklander const unsigned char *iv, 3923d3b0591SJens Wiklander size_t iv_len ) 393817466cbSJens Wiklander { 394817466cbSJens Wiklander size_t actual_iv_size; 395817466cbSJens Wiklander 3963d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 3973d3b0591SJens Wiklander CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 3983d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 399817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 40011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 40111fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 40211fa71b9SJerome Forissier { 40311fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 40411fa71b9SJerome Forissier * operations, we currently don't make it 40511fa71b9SJerome Forissier * accessible through the cipher layer. */ 40611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 40711fa71b9SJerome Forissier } 40811fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 409817466cbSJens Wiklander 410817466cbSJens Wiklander /* avoid buffer overflow in ctx->iv */ 411817466cbSJens Wiklander if( iv_len > MBEDTLS_MAX_IV_LENGTH ) 412817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 413817466cbSJens Wiklander 414817466cbSJens Wiklander if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) 415817466cbSJens Wiklander actual_iv_size = iv_len; 416817466cbSJens Wiklander else 417817466cbSJens Wiklander { 418817466cbSJens Wiklander actual_iv_size = ctx->cipher_info->iv_size; 419817466cbSJens Wiklander 420817466cbSJens Wiklander /* avoid reading past the end of input buffer */ 421817466cbSJens Wiklander if( actual_iv_size > iv_len ) 422817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 423817466cbSJens Wiklander } 424817466cbSJens Wiklander 4253d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C) 4263d3b0591SJens Wiklander if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) 4273d3b0591SJens Wiklander { 428*039e02dfSJerome Forissier /* Even though the actual_iv_size is overwritten with a correct value 429*039e02dfSJerome Forissier * of 12 from the cipher info, return an error to indicate that 430*039e02dfSJerome Forissier * the input iv_len is wrong. */ 431*039e02dfSJerome Forissier if( iv_len != 12 ) 432*039e02dfSJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 433*039e02dfSJerome Forissier 4343d3b0591SJens Wiklander if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, 4353d3b0591SJens Wiklander iv, 4363d3b0591SJens Wiklander 0U ) ) /* Initial counter value */ 4373d3b0591SJens Wiklander { 4383d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 4393d3b0591SJens Wiklander } 4403d3b0591SJens Wiklander } 441*039e02dfSJerome Forissier #if defined(MBEDTLS_CHACHAPOLY_C) 442*039e02dfSJerome Forissier if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 && 443*039e02dfSJerome Forissier iv_len != 12 ) 444*039e02dfSJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 445*039e02dfSJerome Forissier #endif 4463d3b0591SJens Wiklander #endif 4473d3b0591SJens Wiklander 4483d3b0591SJens Wiklander if ( actual_iv_size != 0 ) 4493d3b0591SJens Wiklander { 450817466cbSJens Wiklander memcpy( ctx->iv, iv, actual_iv_size ); 451817466cbSJens Wiklander ctx->iv_size = actual_iv_size; 4523d3b0591SJens Wiklander } 453817466cbSJens Wiklander 454817466cbSJens Wiklander return( 0 ); 455817466cbSJens Wiklander } 456817466cbSJens Wiklander 457817466cbSJens Wiklander int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) 458817466cbSJens Wiklander { 4593d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 4603d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 461817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 462817466cbSJens Wiklander 46311fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 46411fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 46511fa71b9SJerome Forissier { 46611fa71b9SJerome Forissier /* We don't support resetting PSA-based 46711fa71b9SJerome Forissier * cipher contexts, yet. */ 46811fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 46911fa71b9SJerome Forissier } 47011fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 47111fa71b9SJerome Forissier 472817466cbSJens Wiklander ctx->unprocessed_len = 0; 473817466cbSJens Wiklander 474817466cbSJens Wiklander return( 0 ); 475817466cbSJens Wiklander } 476817466cbSJens Wiklander 4773d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 478817466cbSJens Wiklander int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, 479817466cbSJens Wiklander const unsigned char *ad, size_t ad_len ) 480817466cbSJens Wiklander { 4813d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 4823d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 4833d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 484817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 485817466cbSJens Wiklander 48611fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 48711fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 48811fa71b9SJerome Forissier { 48911fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 49011fa71b9SJerome Forissier * operations, we currently don't make it 49111fa71b9SJerome Forissier * accessible through the cipher layer. */ 49211fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 49311fa71b9SJerome Forissier } 49411fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 49511fa71b9SJerome Forissier 4963d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 497817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 498817466cbSJens Wiklander { 4993d3b0591SJens Wiklander return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, 5003d3b0591SJens Wiklander ctx->iv, ctx->iv_size, ad, ad_len ) ); 501817466cbSJens Wiklander } 5023d3b0591SJens Wiklander #endif 5033d3b0591SJens Wiklander 5043d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 5053d3b0591SJens Wiklander if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 5063d3b0591SJens Wiklander { 5073d3b0591SJens Wiklander int result; 5083d3b0591SJens Wiklander mbedtls_chachapoly_mode_t mode; 5093d3b0591SJens Wiklander 5103d3b0591SJens Wiklander mode = ( ctx->operation == MBEDTLS_ENCRYPT ) 5113d3b0591SJens Wiklander ? MBEDTLS_CHACHAPOLY_ENCRYPT 5123d3b0591SJens Wiklander : MBEDTLS_CHACHAPOLY_DECRYPT; 5133d3b0591SJens Wiklander 5143d3b0591SJens Wiklander result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 5153d3b0591SJens Wiklander ctx->iv, 5163d3b0591SJens Wiklander mode ); 5173d3b0591SJens Wiklander if ( result != 0 ) 5183d3b0591SJens Wiklander return( result ); 5193d3b0591SJens Wiklander 5203d3b0591SJens Wiklander return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 5213d3b0591SJens Wiklander ad, ad_len ) ); 5223d3b0591SJens Wiklander } 5233d3b0591SJens Wiklander #endif 524817466cbSJens Wiklander 525817466cbSJens Wiklander return( 0 ); 526817466cbSJens Wiklander } 5273d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 528817466cbSJens Wiklander 529817466cbSJens Wiklander int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, 530817466cbSJens Wiklander size_t ilen, unsigned char *output, size_t *olen ) 531817466cbSJens Wiklander { 53211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 5333d3b0591SJens Wiklander size_t block_size; 534817466cbSJens Wiklander 5353d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 5363d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 5373d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 5383d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 5393d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 540817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 541817466cbSJens Wiklander 54211fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 54311fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 54411fa71b9SJerome Forissier { 54511fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 54611fa71b9SJerome Forissier * operations, we currently don't make it 54711fa71b9SJerome Forissier * accessible through the cipher layer. */ 54811fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 54911fa71b9SJerome Forissier } 55011fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 55111fa71b9SJerome Forissier 552817466cbSJens Wiklander *olen = 0; 553817466cbSJens Wiklander block_size = mbedtls_cipher_get_block_size( ctx ); 5545b25c76aSJerome Forissier if ( 0 == block_size ) 5555b25c76aSJerome Forissier { 5565b25c76aSJerome Forissier return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); 5575b25c76aSJerome Forissier } 558817466cbSJens Wiklander 559817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) 560817466cbSJens Wiklander { 561817466cbSJens Wiklander if( ilen != block_size ) 562817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 563817466cbSJens Wiklander 564817466cbSJens Wiklander *olen = ilen; 565817466cbSJens Wiklander 566817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, 567817466cbSJens Wiklander ctx->operation, input, output ) ) ) 568817466cbSJens Wiklander { 569817466cbSJens Wiklander return( ret ); 570817466cbSJens Wiklander } 571817466cbSJens Wiklander 572817466cbSJens Wiklander return( 0 ); 573817466cbSJens Wiklander } 574817466cbSJens Wiklander 575817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 576817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) 577817466cbSJens Wiklander { 578817466cbSJens Wiklander *olen = ilen; 5793d3b0591SJens Wiklander return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, 5803d3b0591SJens Wiklander output ) ); 5813d3b0591SJens Wiklander } 5823d3b0591SJens Wiklander #endif 5833d3b0591SJens Wiklander 5843d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 5853d3b0591SJens Wiklander if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) 5863d3b0591SJens Wiklander { 5873d3b0591SJens Wiklander *olen = ilen; 5883d3b0591SJens Wiklander return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, 5893d3b0591SJens Wiklander ilen, input, output ) ); 590817466cbSJens Wiklander } 591817466cbSJens Wiklander #endif 592817466cbSJens Wiklander 593817466cbSJens Wiklander if( input == output && 594817466cbSJens Wiklander ( ctx->unprocessed_len != 0 || ilen % block_size ) ) 595817466cbSJens Wiklander { 596817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 597817466cbSJens Wiklander } 598817466cbSJens Wiklander 599817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC) 600817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) 601817466cbSJens Wiklander { 602817466cbSJens Wiklander size_t copy_len = 0; 603817466cbSJens Wiklander 604817466cbSJens Wiklander /* 605817466cbSJens Wiklander * If there is not enough data for a full block, cache it. 606817466cbSJens Wiklander */ 6073d3b0591SJens Wiklander if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && 608817466cbSJens Wiklander ilen <= block_size - ctx->unprocessed_len ) || 6093d3b0591SJens Wiklander ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && 6103d3b0591SJens Wiklander ilen < block_size - ctx->unprocessed_len ) || 611817466cbSJens Wiklander ( ctx->operation == MBEDTLS_ENCRYPT && 612817466cbSJens Wiklander ilen < block_size - ctx->unprocessed_len ) ) 613817466cbSJens Wiklander { 614817466cbSJens Wiklander memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, 615817466cbSJens Wiklander ilen ); 616817466cbSJens Wiklander 617817466cbSJens Wiklander ctx->unprocessed_len += ilen; 618817466cbSJens Wiklander return( 0 ); 619817466cbSJens Wiklander } 620817466cbSJens Wiklander 621817466cbSJens Wiklander /* 622817466cbSJens Wiklander * Process cached data first 623817466cbSJens Wiklander */ 624817466cbSJens Wiklander if( 0 != ctx->unprocessed_len ) 625817466cbSJens Wiklander { 626817466cbSJens Wiklander copy_len = block_size - ctx->unprocessed_len; 627817466cbSJens Wiklander 628817466cbSJens Wiklander memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, 629817466cbSJens Wiklander copy_len ); 630817466cbSJens Wiklander 631817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 632817466cbSJens Wiklander ctx->operation, block_size, ctx->iv, 633817466cbSJens Wiklander ctx->unprocessed_data, output ) ) ) 634817466cbSJens Wiklander { 635817466cbSJens Wiklander return( ret ); 636817466cbSJens Wiklander } 637817466cbSJens Wiklander 638817466cbSJens Wiklander *olen += block_size; 639817466cbSJens Wiklander output += block_size; 640817466cbSJens Wiklander ctx->unprocessed_len = 0; 641817466cbSJens Wiklander 642817466cbSJens Wiklander input += copy_len; 643817466cbSJens Wiklander ilen -= copy_len; 644817466cbSJens Wiklander } 645817466cbSJens Wiklander 646817466cbSJens Wiklander /* 647817466cbSJens Wiklander * Cache final, incomplete block 648817466cbSJens Wiklander */ 649817466cbSJens Wiklander if( 0 != ilen ) 650817466cbSJens Wiklander { 6513d3b0591SJens Wiklander /* Encryption: only cache partial blocks 6523d3b0591SJens Wiklander * Decryption w/ padding: always keep at least one whole block 6533d3b0591SJens Wiklander * Decryption w/o padding: only cache partial blocks 6543d3b0591SJens Wiklander */ 655817466cbSJens Wiklander copy_len = ilen % block_size; 6563d3b0591SJens Wiklander if( copy_len == 0 && 6573d3b0591SJens Wiklander ctx->operation == MBEDTLS_DECRYPT && 6583d3b0591SJens Wiklander NULL != ctx->add_padding) 6593d3b0591SJens Wiklander { 660817466cbSJens Wiklander copy_len = block_size; 6613d3b0591SJens Wiklander } 662817466cbSJens Wiklander 663817466cbSJens Wiklander memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), 664817466cbSJens Wiklander copy_len ); 665817466cbSJens Wiklander 666817466cbSJens Wiklander ctx->unprocessed_len += copy_len; 667817466cbSJens Wiklander ilen -= copy_len; 668817466cbSJens Wiklander } 669817466cbSJens Wiklander 670817466cbSJens Wiklander /* 671817466cbSJens Wiklander * Process remaining full blocks 672817466cbSJens Wiklander */ 673817466cbSJens Wiklander if( ilen ) 674817466cbSJens Wiklander { 675817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 676817466cbSJens Wiklander ctx->operation, ilen, ctx->iv, input, output ) ) ) 677817466cbSJens Wiklander { 678817466cbSJens Wiklander return( ret ); 679817466cbSJens Wiklander } 680817466cbSJens Wiklander 681817466cbSJens Wiklander *olen += ilen; 682817466cbSJens Wiklander } 683817466cbSJens Wiklander 684817466cbSJens Wiklander return( 0 ); 685817466cbSJens Wiklander } 686817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */ 687817466cbSJens Wiklander 688817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CFB) 689817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) 690817466cbSJens Wiklander { 691817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, 692817466cbSJens Wiklander ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, 693817466cbSJens Wiklander input, output ) ) ) 694817466cbSJens Wiklander { 695817466cbSJens Wiklander return( ret ); 696817466cbSJens Wiklander } 697817466cbSJens Wiklander 698817466cbSJens Wiklander *olen = ilen; 699817466cbSJens Wiklander 700817466cbSJens Wiklander return( 0 ); 701817466cbSJens Wiklander } 702817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CFB */ 703817466cbSJens Wiklander 7043d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_OFB) 7053d3b0591SJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) 7063d3b0591SJens Wiklander { 7073d3b0591SJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, 7083d3b0591SJens Wiklander ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) 7093d3b0591SJens Wiklander { 7103d3b0591SJens Wiklander return( ret ); 7113d3b0591SJens Wiklander } 7123d3b0591SJens Wiklander 7133d3b0591SJens Wiklander *olen = ilen; 7143d3b0591SJens Wiklander 7153d3b0591SJens Wiklander return( 0 ); 7163d3b0591SJens Wiklander } 7173d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_OFB */ 7183d3b0591SJens Wiklander 719817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CTR) 720817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) 721817466cbSJens Wiklander { 722817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, 723817466cbSJens Wiklander ilen, &ctx->unprocessed_len, ctx->iv, 724817466cbSJens Wiklander ctx->unprocessed_data, input, output ) ) ) 725817466cbSJens Wiklander { 726817466cbSJens Wiklander return( ret ); 727817466cbSJens Wiklander } 728817466cbSJens Wiklander 729817466cbSJens Wiklander *olen = ilen; 730817466cbSJens Wiklander 731817466cbSJens Wiklander return( 0 ); 732817466cbSJens Wiklander } 733817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CTR */ 734817466cbSJens Wiklander 7353d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_XTS) 7363d3b0591SJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) 7373d3b0591SJens Wiklander { 7383d3b0591SJens Wiklander if( ctx->unprocessed_len > 0 ) { 7393d3b0591SJens Wiklander /* We can only process an entire data unit at a time. */ 7403d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 7413d3b0591SJens Wiklander } 7423d3b0591SJens Wiklander 7433d3b0591SJens Wiklander ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, 7443d3b0591SJens Wiklander ctx->operation, ilen, ctx->iv, input, output ); 7453d3b0591SJens Wiklander if( ret != 0 ) 7463d3b0591SJens Wiklander { 7473d3b0591SJens Wiklander return( ret ); 7483d3b0591SJens Wiklander } 7493d3b0591SJens Wiklander 7503d3b0591SJens Wiklander *olen = ilen; 7513d3b0591SJens Wiklander 7523d3b0591SJens Wiklander return( 0 ); 7533d3b0591SJens Wiklander } 7543d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_XTS */ 7553d3b0591SJens Wiklander 756817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_STREAM) 757817466cbSJens Wiklander if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) 758817466cbSJens Wiklander { 759817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, 760817466cbSJens Wiklander ilen, input, output ) ) ) 761817466cbSJens Wiklander { 762817466cbSJens Wiklander return( ret ); 763817466cbSJens Wiklander } 764817466cbSJens Wiklander 765817466cbSJens Wiklander *olen = ilen; 766817466cbSJens Wiklander 767817466cbSJens Wiklander return( 0 ); 768817466cbSJens Wiklander } 769817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_STREAM */ 770817466cbSJens Wiklander 771817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 772817466cbSJens Wiklander } 773817466cbSJens Wiklander 774817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 775817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 776817466cbSJens Wiklander /* 777817466cbSJens Wiklander * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len 778817466cbSJens Wiklander */ 779817466cbSJens Wiklander static void add_pkcs_padding( unsigned char *output, size_t output_len, 780817466cbSJens Wiklander size_t data_len ) 781817466cbSJens Wiklander { 782817466cbSJens Wiklander size_t padding_len = output_len - data_len; 783817466cbSJens Wiklander unsigned char i; 784817466cbSJens Wiklander 785817466cbSJens Wiklander for( i = 0; i < padding_len; i++ ) 786817466cbSJens Wiklander output[data_len + i] = (unsigned char) padding_len; 787817466cbSJens Wiklander } 788817466cbSJens Wiklander 789817466cbSJens Wiklander static int get_pkcs_padding( unsigned char *input, size_t input_len, 790817466cbSJens Wiklander size_t *data_len ) 791817466cbSJens Wiklander { 792817466cbSJens Wiklander size_t i, pad_idx; 793817466cbSJens Wiklander unsigned char padding_len, bad = 0; 794817466cbSJens Wiklander 795817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 796817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 797817466cbSJens Wiklander 798817466cbSJens Wiklander padding_len = input[input_len - 1]; 799817466cbSJens Wiklander *data_len = input_len - padding_len; 800817466cbSJens Wiklander 801817466cbSJens Wiklander /* Avoid logical || since it results in a branch */ 802817466cbSJens Wiklander bad |= padding_len > input_len; 803817466cbSJens Wiklander bad |= padding_len == 0; 804817466cbSJens Wiklander 805817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len, 806817466cbSJens Wiklander * so pick input_len, which is usually 8 or 16 (one block) */ 807817466cbSJens Wiklander pad_idx = input_len - padding_len; 808817466cbSJens Wiklander for( i = 0; i < input_len; i++ ) 809817466cbSJens Wiklander bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); 810817466cbSJens Wiklander 811817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 812817466cbSJens Wiklander } 813817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ 814817466cbSJens Wiklander 815817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) 816817466cbSJens Wiklander /* 817817466cbSJens Wiklander * One and zeros padding: fill with 80 00 ... 00 818817466cbSJens Wiklander */ 819817466cbSJens Wiklander static void add_one_and_zeros_padding( unsigned char *output, 820817466cbSJens Wiklander size_t output_len, size_t data_len ) 821817466cbSJens Wiklander { 822817466cbSJens Wiklander size_t padding_len = output_len - data_len; 823817466cbSJens Wiklander unsigned char i = 0; 824817466cbSJens Wiklander 825817466cbSJens Wiklander output[data_len] = 0x80; 826817466cbSJens Wiklander for( i = 1; i < padding_len; i++ ) 827817466cbSJens Wiklander output[data_len + i] = 0x00; 828817466cbSJens Wiklander } 829817466cbSJens Wiklander 830817466cbSJens Wiklander static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, 831817466cbSJens Wiklander size_t *data_len ) 832817466cbSJens Wiklander { 833817466cbSJens Wiklander size_t i; 834817466cbSJens Wiklander unsigned char done = 0, prev_done, bad; 835817466cbSJens Wiklander 836817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 837817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 838817466cbSJens Wiklander 8393d3b0591SJens Wiklander bad = 0x80; 840817466cbSJens Wiklander *data_len = 0; 841817466cbSJens Wiklander for( i = input_len; i > 0; i-- ) 842817466cbSJens Wiklander { 843817466cbSJens Wiklander prev_done = done; 844817466cbSJens Wiklander done |= ( input[i - 1] != 0 ); 845817466cbSJens Wiklander *data_len |= ( i - 1 ) * ( done != prev_done ); 8463d3b0591SJens Wiklander bad ^= input[i - 1] * ( done != prev_done ); 847817466cbSJens Wiklander } 848817466cbSJens Wiklander 849817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 850817466cbSJens Wiklander 851817466cbSJens Wiklander } 852817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ 853817466cbSJens Wiklander 854817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) 855817466cbSJens Wiklander /* 856817466cbSJens Wiklander * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length 857817466cbSJens Wiklander */ 858817466cbSJens Wiklander static void add_zeros_and_len_padding( unsigned char *output, 859817466cbSJens Wiklander size_t output_len, size_t data_len ) 860817466cbSJens Wiklander { 861817466cbSJens Wiklander size_t padding_len = output_len - data_len; 862817466cbSJens Wiklander unsigned char i = 0; 863817466cbSJens Wiklander 864817466cbSJens Wiklander for( i = 1; i < padding_len; i++ ) 865817466cbSJens Wiklander output[data_len + i - 1] = 0x00; 866817466cbSJens Wiklander output[output_len - 1] = (unsigned char) padding_len; 867817466cbSJens Wiklander } 868817466cbSJens Wiklander 869817466cbSJens Wiklander static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, 870817466cbSJens Wiklander size_t *data_len ) 871817466cbSJens Wiklander { 872817466cbSJens Wiklander size_t i, pad_idx; 873817466cbSJens Wiklander unsigned char padding_len, bad = 0; 874817466cbSJens Wiklander 875817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 876817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 877817466cbSJens Wiklander 878817466cbSJens Wiklander padding_len = input[input_len - 1]; 879817466cbSJens Wiklander *data_len = input_len - padding_len; 880817466cbSJens Wiklander 881817466cbSJens Wiklander /* Avoid logical || since it results in a branch */ 882817466cbSJens Wiklander bad |= padding_len > input_len; 883817466cbSJens Wiklander bad |= padding_len == 0; 884817466cbSJens Wiklander 885817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len */ 886817466cbSJens Wiklander pad_idx = input_len - padding_len; 887817466cbSJens Wiklander for( i = 0; i < input_len - 1; i++ ) 888817466cbSJens Wiklander bad |= input[i] * ( i >= pad_idx ); 889817466cbSJens Wiklander 890817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); 891817466cbSJens Wiklander } 892817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ 893817466cbSJens Wiklander 894817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) 895817466cbSJens Wiklander /* 896817466cbSJens Wiklander * Zero padding: fill with 00 ... 00 897817466cbSJens Wiklander */ 898817466cbSJens Wiklander static void add_zeros_padding( unsigned char *output, 899817466cbSJens Wiklander size_t output_len, size_t data_len ) 900817466cbSJens Wiklander { 901817466cbSJens Wiklander size_t i; 902817466cbSJens Wiklander 903817466cbSJens Wiklander for( i = data_len; i < output_len; i++ ) 904817466cbSJens Wiklander output[i] = 0x00; 905817466cbSJens Wiklander } 906817466cbSJens Wiklander 907817466cbSJens Wiklander static int get_zeros_padding( unsigned char *input, size_t input_len, 908817466cbSJens Wiklander size_t *data_len ) 909817466cbSJens Wiklander { 910817466cbSJens Wiklander size_t i; 911817466cbSJens Wiklander unsigned char done = 0, prev_done; 912817466cbSJens Wiklander 913817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 914817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 915817466cbSJens Wiklander 916817466cbSJens Wiklander *data_len = 0; 917817466cbSJens Wiklander for( i = input_len; i > 0; i-- ) 918817466cbSJens Wiklander { 919817466cbSJens Wiklander prev_done = done; 920817466cbSJens Wiklander done |= ( input[i-1] != 0 ); 921817466cbSJens Wiklander *data_len |= i * ( done != prev_done ); 922817466cbSJens Wiklander } 923817466cbSJens Wiklander 924817466cbSJens Wiklander return( 0 ); 925817466cbSJens Wiklander } 926817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ 927817466cbSJens Wiklander 928817466cbSJens Wiklander /* 929817466cbSJens Wiklander * No padding: don't pad :) 930817466cbSJens Wiklander * 931817466cbSJens Wiklander * There is no add_padding function (check for NULL in mbedtls_cipher_finish) 932817466cbSJens Wiklander * but a trivial get_padding function 933817466cbSJens Wiklander */ 934817466cbSJens Wiklander static int get_no_padding( unsigned char *input, size_t input_len, 935817466cbSJens Wiklander size_t *data_len ) 936817466cbSJens Wiklander { 937817466cbSJens Wiklander if( NULL == input || NULL == data_len ) 938817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 939817466cbSJens Wiklander 940817466cbSJens Wiklander *data_len = input_len; 941817466cbSJens Wiklander 942817466cbSJens Wiklander return( 0 ); 943817466cbSJens Wiklander } 944817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 945817466cbSJens Wiklander 946817466cbSJens Wiklander int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, 947817466cbSJens Wiklander unsigned char *output, size_t *olen ) 948817466cbSJens Wiklander { 9493d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 9503d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 9513d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 9523d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 953817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 954817466cbSJens Wiklander 95511fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 95611fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 95711fa71b9SJerome Forissier { 95811fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 95911fa71b9SJerome Forissier * operations, we currently don't make it 96011fa71b9SJerome Forissier * accessible through the cipher layer. */ 96111fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 96211fa71b9SJerome Forissier } 96311fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 96411fa71b9SJerome Forissier 965817466cbSJens Wiklander *olen = 0; 966817466cbSJens Wiklander 967817466cbSJens Wiklander if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || 9683d3b0591SJens Wiklander MBEDTLS_MODE_OFB == ctx->cipher_info->mode || 969817466cbSJens Wiklander MBEDTLS_MODE_CTR == ctx->cipher_info->mode || 970817466cbSJens Wiklander MBEDTLS_MODE_GCM == ctx->cipher_info->mode || 9713d3b0591SJens Wiklander MBEDTLS_MODE_XTS == ctx->cipher_info->mode || 972817466cbSJens Wiklander MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) 973817466cbSJens Wiklander { 974817466cbSJens Wiklander return( 0 ); 975817466cbSJens Wiklander } 976817466cbSJens Wiklander 9773d3b0591SJens Wiklander if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || 9783d3b0591SJens Wiklander ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) 9793d3b0591SJens Wiklander { 9803d3b0591SJens Wiklander return( 0 ); 9813d3b0591SJens Wiklander } 9823d3b0591SJens Wiklander 983817466cbSJens Wiklander if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) 984817466cbSJens Wiklander { 985817466cbSJens Wiklander if( ctx->unprocessed_len != 0 ) 986817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 987817466cbSJens Wiklander 988817466cbSJens Wiklander return( 0 ); 989817466cbSJens Wiklander } 990817466cbSJens Wiklander 991817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC) 992817466cbSJens Wiklander if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) 993817466cbSJens Wiklander { 994817466cbSJens Wiklander int ret = 0; 995817466cbSJens Wiklander 996817466cbSJens Wiklander if( MBEDTLS_ENCRYPT == ctx->operation ) 997817466cbSJens Wiklander { 998817466cbSJens Wiklander /* check for 'no padding' mode */ 999817466cbSJens Wiklander if( NULL == ctx->add_padding ) 1000817466cbSJens Wiklander { 1001817466cbSJens Wiklander if( 0 != ctx->unprocessed_len ) 1002817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 1003817466cbSJens Wiklander 1004817466cbSJens Wiklander return( 0 ); 1005817466cbSJens Wiklander } 1006817466cbSJens Wiklander 1007817466cbSJens Wiklander ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), 1008817466cbSJens Wiklander ctx->unprocessed_len ); 1009817466cbSJens Wiklander } 1010817466cbSJens Wiklander else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) 1011817466cbSJens Wiklander { 1012817466cbSJens Wiklander /* 1013817466cbSJens Wiklander * For decrypt operations, expect a full block, 1014817466cbSJens Wiklander * or an empty block if no padding 1015817466cbSJens Wiklander */ 1016817466cbSJens Wiklander if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) 1017817466cbSJens Wiklander return( 0 ); 1018817466cbSJens Wiklander 1019817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); 1020817466cbSJens Wiklander } 1021817466cbSJens Wiklander 1022817466cbSJens Wiklander /* cipher block */ 1023817466cbSJens Wiklander if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, 1024817466cbSJens Wiklander ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, 1025817466cbSJens Wiklander ctx->unprocessed_data, output ) ) ) 1026817466cbSJens Wiklander { 1027817466cbSJens Wiklander return( ret ); 1028817466cbSJens Wiklander } 1029817466cbSJens Wiklander 1030817466cbSJens Wiklander /* Set output size for decryption */ 1031817466cbSJens Wiklander if( MBEDTLS_DECRYPT == ctx->operation ) 10323d3b0591SJens Wiklander return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), 10333d3b0591SJens Wiklander olen ) ); 1034817466cbSJens Wiklander 1035817466cbSJens Wiklander /* Set output size for encryption */ 1036817466cbSJens Wiklander *olen = mbedtls_cipher_get_block_size( ctx ); 1037817466cbSJens Wiklander return( 0 ); 1038817466cbSJens Wiklander } 1039817466cbSJens Wiklander #else 1040817466cbSJens Wiklander ((void) output); 1041817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */ 1042817466cbSJens Wiklander 1043817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1044817466cbSJens Wiklander } 1045817466cbSJens Wiklander 1046817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 10473d3b0591SJens Wiklander int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, 10483d3b0591SJens Wiklander mbedtls_cipher_padding_t mode ) 1049817466cbSJens Wiklander { 10503d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 10513d3b0591SJens Wiklander 10523d3b0591SJens Wiklander if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) 1053817466cbSJens Wiklander { 1054817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1055817466cbSJens Wiklander } 1056817466cbSJens Wiklander 105711fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 105811fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 105911fa71b9SJerome Forissier { 106011fa71b9SJerome Forissier /* While PSA Crypto knows about CBC padding 106111fa71b9SJerome Forissier * schemes, we currently don't make them 106211fa71b9SJerome Forissier * accessible through the cipher layer. */ 106311fa71b9SJerome Forissier if( mode != MBEDTLS_PADDING_NONE ) 106411fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 106511fa71b9SJerome Forissier 106611fa71b9SJerome Forissier return( 0 ); 106711fa71b9SJerome Forissier } 106811fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 106911fa71b9SJerome Forissier 1070817466cbSJens Wiklander switch( mode ) 1071817466cbSJens Wiklander { 1072817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 1073817466cbSJens Wiklander case MBEDTLS_PADDING_PKCS7: 1074817466cbSJens Wiklander ctx->add_padding = add_pkcs_padding; 1075817466cbSJens Wiklander ctx->get_padding = get_pkcs_padding; 1076817466cbSJens Wiklander break; 1077817466cbSJens Wiklander #endif 1078817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) 1079817466cbSJens Wiklander case MBEDTLS_PADDING_ONE_AND_ZEROS: 1080817466cbSJens Wiklander ctx->add_padding = add_one_and_zeros_padding; 1081817466cbSJens Wiklander ctx->get_padding = get_one_and_zeros_padding; 1082817466cbSJens Wiklander break; 1083817466cbSJens Wiklander #endif 1084817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) 1085817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS_AND_LEN: 1086817466cbSJens Wiklander ctx->add_padding = add_zeros_and_len_padding; 1087817466cbSJens Wiklander ctx->get_padding = get_zeros_and_len_padding; 1088817466cbSJens Wiklander break; 1089817466cbSJens Wiklander #endif 1090817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) 1091817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS: 1092817466cbSJens Wiklander ctx->add_padding = add_zeros_padding; 1093817466cbSJens Wiklander ctx->get_padding = get_zeros_padding; 1094817466cbSJens Wiklander break; 1095817466cbSJens Wiklander #endif 1096817466cbSJens Wiklander case MBEDTLS_PADDING_NONE: 1097817466cbSJens Wiklander ctx->add_padding = NULL; 1098817466cbSJens Wiklander ctx->get_padding = get_no_padding; 1099817466cbSJens Wiklander break; 1100817466cbSJens Wiklander 1101817466cbSJens Wiklander default: 1102817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1103817466cbSJens Wiklander } 1104817466cbSJens Wiklander 1105817466cbSJens Wiklander return( 0 ); 1106817466cbSJens Wiklander } 1107817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 1108817466cbSJens Wiklander 11093d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 1110817466cbSJens Wiklander int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, 1111817466cbSJens Wiklander unsigned char *tag, size_t tag_len ) 1112817466cbSJens Wiklander { 11133d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 11143d3b0591SJens Wiklander CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 11153d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 1116817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1117817466cbSJens Wiklander 1118817466cbSJens Wiklander if( MBEDTLS_ENCRYPT != ctx->operation ) 1119817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1120817466cbSJens Wiklander 112111fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 112211fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 112311fa71b9SJerome Forissier { 112411fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 112511fa71b9SJerome Forissier * operations, we currently don't make it 112611fa71b9SJerome Forissier * accessible through the cipher layer. */ 112711fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 112811fa71b9SJerome Forissier } 112911fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 113011fa71b9SJerome Forissier 11313d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 1132817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 11333d3b0591SJens Wiklander return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, 11343d3b0591SJens Wiklander tag, tag_len ) ); 11353d3b0591SJens Wiklander #endif 11363d3b0591SJens Wiklander 11373d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 11383d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 11393d3b0591SJens Wiklander { 11403d3b0591SJens Wiklander /* Don't allow truncated MAC for Poly1305 */ 11413d3b0591SJens Wiklander if ( tag_len != 16U ) 11423d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 11433d3b0591SJens Wiklander 114411fa71b9SJerome Forissier return( mbedtls_chachapoly_finish( 114511fa71b9SJerome Forissier (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) ); 11463d3b0591SJens Wiklander } 11473d3b0591SJens Wiklander #endif 1148817466cbSJens Wiklander 1149817466cbSJens Wiklander return( 0 ); 1150817466cbSJens Wiklander } 1151817466cbSJens Wiklander 1152817466cbSJens Wiklander int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, 1153817466cbSJens Wiklander const unsigned char *tag, size_t tag_len ) 1154817466cbSJens Wiklander { 11553d3b0591SJens Wiklander unsigned char check_tag[16]; 115611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1157817466cbSJens Wiklander 11583d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 11593d3b0591SJens Wiklander CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 11603d3b0591SJens Wiklander if( ctx->cipher_info == NULL ) 11613d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 11623d3b0591SJens Wiklander 11633d3b0591SJens Wiklander if( MBEDTLS_DECRYPT != ctx->operation ) 1164817466cbSJens Wiklander { 1165817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1166817466cbSJens Wiklander } 1167817466cbSJens Wiklander 116811fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 116911fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 117011fa71b9SJerome Forissier { 117111fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 117211fa71b9SJerome Forissier * operations, we currently don't make it 117311fa71b9SJerome Forissier * accessible through the cipher layer. */ 117411fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 117511fa71b9SJerome Forissier } 117611fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 117711fa71b9SJerome Forissier 1178*039e02dfSJerome Forissier /* Status to return on a non-authenticated algorithm. It would make sense 1179*039e02dfSJerome Forissier * to return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT or perhaps 1180*039e02dfSJerome Forissier * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, but at the time I write this our 1181*039e02dfSJerome Forissier * unit tests assume 0. */ 1182*039e02dfSJerome Forissier ret = 0; 1183*039e02dfSJerome Forissier 11843d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 1185817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1186817466cbSJens Wiklander { 1187817466cbSJens Wiklander if( tag_len > sizeof( check_tag ) ) 1188817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1189817466cbSJens Wiklander 119011fa71b9SJerome Forissier if( 0 != ( ret = mbedtls_gcm_finish( 119111fa71b9SJerome Forissier (mbedtls_gcm_context *) ctx->cipher_ctx, 1192817466cbSJens Wiklander check_tag, tag_len ) ) ) 1193817466cbSJens Wiklander { 1194817466cbSJens Wiklander return( ret ); 1195817466cbSJens Wiklander } 1196817466cbSJens Wiklander 1197817466cbSJens Wiklander /* Check the tag in "constant-time" */ 1198*039e02dfSJerome Forissier if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 ) 1199*039e02dfSJerome Forissier { 1200*039e02dfSJerome Forissier ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1201*039e02dfSJerome Forissier goto exit; 1202*039e02dfSJerome Forissier } 1203817466cbSJens Wiklander } 12043d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C */ 12053d3b0591SJens Wiklander 12063d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 12073d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 12083d3b0591SJens Wiklander { 12093d3b0591SJens Wiklander /* Don't allow truncated MAC for Poly1305 */ 12103d3b0591SJens Wiklander if ( tag_len != sizeof( check_tag ) ) 12113d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 12123d3b0591SJens Wiklander 121311fa71b9SJerome Forissier ret = mbedtls_chachapoly_finish( 121411fa71b9SJerome Forissier (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag ); 12153d3b0591SJens Wiklander if ( ret != 0 ) 12163d3b0591SJens Wiklander { 12173d3b0591SJens Wiklander return( ret ); 12183d3b0591SJens Wiklander } 12193d3b0591SJens Wiklander 12203d3b0591SJens Wiklander /* Check the tag in "constant-time" */ 1221*039e02dfSJerome Forissier if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 ) 1222*039e02dfSJerome Forissier { 1223*039e02dfSJerome Forissier ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1224*039e02dfSJerome Forissier goto exit; 1225*039e02dfSJerome Forissier } 1226817466cbSJens Wiklander } 12273d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 12283d3b0591SJens Wiklander 1229*039e02dfSJerome Forissier exit: 1230*039e02dfSJerome Forissier mbedtls_platform_zeroize( check_tag, tag_len ); 1231*039e02dfSJerome Forissier return( ret ); 12323d3b0591SJens Wiklander } 12333d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 1234817466cbSJens Wiklander 1235817466cbSJens Wiklander /* 1236817466cbSJens Wiklander * Packet-oriented wrapper for non-AEAD modes 1237817466cbSJens Wiklander */ 1238817466cbSJens Wiklander int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, 1239817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1240817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1241817466cbSJens Wiklander unsigned char *output, size_t *olen ) 1242817466cbSJens Wiklander { 124311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1244817466cbSJens Wiklander size_t finish_olen; 1245817466cbSJens Wiklander 12463d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ctx != NULL ); 12473d3b0591SJens Wiklander CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 12483d3b0591SJens Wiklander CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 12493d3b0591SJens Wiklander CIPHER_VALIDATE_RET( output != NULL ); 12503d3b0591SJens Wiklander CIPHER_VALIDATE_RET( olen != NULL ); 12513d3b0591SJens Wiklander 125211fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 125311fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 125411fa71b9SJerome Forissier { 125511fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 125611fa71b9SJerome Forissier * a key has been set. If not, the key slot will 125711fa71b9SJerome Forissier * still be in its default state of 0, which is 125811fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 125911fa71b9SJerome Forissier * below will gracefully fail. */ 126011fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 126111fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 126211fa71b9SJerome Forissier 126311fa71b9SJerome Forissier psa_status_t status; 126411fa71b9SJerome Forissier psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; 126511fa71b9SJerome Forissier size_t part_len; 126611fa71b9SJerome Forissier 126711fa71b9SJerome Forissier if( ctx->operation == MBEDTLS_DECRYPT ) 126811fa71b9SJerome Forissier { 126911fa71b9SJerome Forissier status = psa_cipher_decrypt_setup( &cipher_op, 127011fa71b9SJerome Forissier cipher_psa->slot, 127111fa71b9SJerome Forissier cipher_psa->alg ); 127211fa71b9SJerome Forissier } 127311fa71b9SJerome Forissier else if( ctx->operation == MBEDTLS_ENCRYPT ) 127411fa71b9SJerome Forissier { 127511fa71b9SJerome Forissier status = psa_cipher_encrypt_setup( &cipher_op, 127611fa71b9SJerome Forissier cipher_psa->slot, 127711fa71b9SJerome Forissier cipher_psa->alg ); 127811fa71b9SJerome Forissier } 127911fa71b9SJerome Forissier else 128011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 128111fa71b9SJerome Forissier 128211fa71b9SJerome Forissier /* In the following, we can immediately return on an error, 128311fa71b9SJerome Forissier * because the PSA Crypto API guarantees that cipher operations 128411fa71b9SJerome Forissier * are terminated by unsuccessful calls to psa_cipher_update(), 128511fa71b9SJerome Forissier * and by any call to psa_cipher_finish(). */ 128611fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 128711fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 128811fa71b9SJerome Forissier 1289*039e02dfSJerome Forissier if( ctx->cipher_info->mode != MBEDTLS_MODE_ECB ) 1290*039e02dfSJerome Forissier { 129111fa71b9SJerome Forissier status = psa_cipher_set_iv( &cipher_op, iv, iv_len ); 129211fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 129311fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 1294*039e02dfSJerome Forissier } 129511fa71b9SJerome Forissier 129611fa71b9SJerome Forissier status = psa_cipher_update( &cipher_op, 129711fa71b9SJerome Forissier input, ilen, 129811fa71b9SJerome Forissier output, ilen, olen ); 129911fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 130011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 130111fa71b9SJerome Forissier 130211fa71b9SJerome Forissier status = psa_cipher_finish( &cipher_op, 130311fa71b9SJerome Forissier output + *olen, ilen - *olen, 130411fa71b9SJerome Forissier &part_len ); 130511fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 130611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 130711fa71b9SJerome Forissier 130811fa71b9SJerome Forissier *olen += part_len; 130911fa71b9SJerome Forissier return( 0 ); 131011fa71b9SJerome Forissier } 131111fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 131211fa71b9SJerome Forissier 1313817466cbSJens Wiklander if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) 1314817466cbSJens Wiklander return( ret ); 1315817466cbSJens Wiklander 1316817466cbSJens Wiklander if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) 1317817466cbSJens Wiklander return( ret ); 1318817466cbSJens Wiklander 131911fa71b9SJerome Forissier if( ( ret = mbedtls_cipher_update( ctx, input, ilen, 132011fa71b9SJerome Forissier output, olen ) ) != 0 ) 1321817466cbSJens Wiklander return( ret ); 1322817466cbSJens Wiklander 132311fa71b9SJerome Forissier if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, 132411fa71b9SJerome Forissier &finish_olen ) ) != 0 ) 1325817466cbSJens Wiklander return( ret ); 1326817466cbSJens Wiklander 1327817466cbSJens Wiklander *olen += finish_olen; 1328817466cbSJens Wiklander 1329817466cbSJens Wiklander return( 0 ); 1330817466cbSJens Wiklander } 1331817466cbSJens Wiklander 1332817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_AEAD) 1333817466cbSJens Wiklander /* 13347901324dSJerome Forissier * Packet-oriented encryption for AEAD modes: internal function shared by 13357901324dSJerome Forissier * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext(). 1336817466cbSJens Wiklander */ 13377901324dSJerome Forissier static int mbedtls_cipher_aead_encrypt( mbedtls_cipher_context_t *ctx, 1338817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1339817466cbSJens Wiklander const unsigned char *ad, size_t ad_len, 1340817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1341817466cbSJens Wiklander unsigned char *output, size_t *olen, 1342817466cbSJens Wiklander unsigned char *tag, size_t tag_len ) 1343817466cbSJens Wiklander { 134411fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 134511fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 134611fa71b9SJerome Forissier { 134711fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 134811fa71b9SJerome Forissier * a key has been set. If not, the key slot will 134911fa71b9SJerome Forissier * still be in its default state of 0, which is 135011fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 135111fa71b9SJerome Forissier * below will gracefully fail. */ 135211fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 135311fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 135411fa71b9SJerome Forissier 135511fa71b9SJerome Forissier psa_status_t status; 135611fa71b9SJerome Forissier 135711fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag 135811fa71b9SJerome Forissier * at the end of the encrypted message. */ 13597901324dSJerome Forissier if( output == NULL || tag != output + ilen ) 136011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 136111fa71b9SJerome Forissier 136211fa71b9SJerome Forissier status = psa_aead_encrypt( cipher_psa->slot, 136311fa71b9SJerome Forissier cipher_psa->alg, 136411fa71b9SJerome Forissier iv, iv_len, 136511fa71b9SJerome Forissier ad, ad_len, 136611fa71b9SJerome Forissier input, ilen, 136711fa71b9SJerome Forissier output, ilen + tag_len, olen ); 136811fa71b9SJerome Forissier if( status != PSA_SUCCESS ) 136911fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 137011fa71b9SJerome Forissier 137111fa71b9SJerome Forissier *olen -= tag_len; 137211fa71b9SJerome Forissier return( 0 ); 137311fa71b9SJerome Forissier } 137411fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 137511fa71b9SJerome Forissier 1376817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 1377817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1378817466cbSJens Wiklander { 1379817466cbSJens Wiklander *olen = ilen; 138011fa71b9SJerome Forissier return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, 138111fa71b9SJerome Forissier ilen, iv, iv_len, ad, ad_len, 138211fa71b9SJerome Forissier input, output, tag_len, tag ) ); 1383817466cbSJens Wiklander } 1384817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1385817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 1386817466cbSJens Wiklander if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) 1387817466cbSJens Wiklander { 1388817466cbSJens Wiklander *olen = ilen; 1389817466cbSJens Wiklander return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, 1390817466cbSJens Wiklander iv, iv_len, ad, ad_len, input, output, 1391817466cbSJens Wiklander tag, tag_len ) ); 1392817466cbSJens Wiklander } 1393817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */ 13943d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 13953d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 13963d3b0591SJens Wiklander { 13973d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */ 13983d3b0591SJens Wiklander if ( ( iv_len != ctx->cipher_info->iv_size ) || 13993d3b0591SJens Wiklander ( tag_len != 16U ) ) 14003d3b0591SJens Wiklander { 14013d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 14023d3b0591SJens Wiklander } 14033d3b0591SJens Wiklander 14043d3b0591SJens Wiklander *olen = ilen; 14053d3b0591SJens Wiklander return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, 14063d3b0591SJens Wiklander ilen, iv, ad, ad_len, input, output, tag ) ); 14073d3b0591SJens Wiklander } 14083d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 1409817466cbSJens Wiklander 1410817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1411817466cbSJens Wiklander } 1412817466cbSJens Wiklander 1413817466cbSJens Wiklander /* 14147901324dSJerome Forissier * Packet-oriented encryption for AEAD modes: internal function shared by 14157901324dSJerome Forissier * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext(). 1416817466cbSJens Wiklander */ 14177901324dSJerome Forissier static int mbedtls_cipher_aead_decrypt( mbedtls_cipher_context_t *ctx, 1418817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1419817466cbSJens Wiklander const unsigned char *ad, size_t ad_len, 1420817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1421817466cbSJens Wiklander unsigned char *output, size_t *olen, 1422817466cbSJens Wiklander const unsigned char *tag, size_t tag_len ) 1423817466cbSJens Wiklander { 142411fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 142511fa71b9SJerome Forissier if( ctx->psa_enabled == 1 ) 142611fa71b9SJerome Forissier { 142711fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 142811fa71b9SJerome Forissier * a key has been set. If not, the key slot will 142911fa71b9SJerome Forissier * still be in its default state of 0, which is 143011fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 143111fa71b9SJerome Forissier * below will gracefully fail. */ 143211fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 143311fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 143411fa71b9SJerome Forissier 143511fa71b9SJerome Forissier psa_status_t status; 143611fa71b9SJerome Forissier 143711fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag 143811fa71b9SJerome Forissier * at the end of the encrypted message. */ 14397901324dSJerome Forissier if( input == NULL || tag != input + ilen ) 144011fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 144111fa71b9SJerome Forissier 144211fa71b9SJerome Forissier status = psa_aead_decrypt( cipher_psa->slot, 144311fa71b9SJerome Forissier cipher_psa->alg, 144411fa71b9SJerome Forissier iv, iv_len, 144511fa71b9SJerome Forissier ad, ad_len, 144611fa71b9SJerome Forissier input, ilen + tag_len, 144711fa71b9SJerome Forissier output, ilen, olen ); 144811fa71b9SJerome Forissier if( status == PSA_ERROR_INVALID_SIGNATURE ) 144911fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); 145011fa71b9SJerome Forissier else if( status != PSA_SUCCESS ) 145111fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); 145211fa71b9SJerome Forissier 145311fa71b9SJerome Forissier return( 0 ); 145411fa71b9SJerome Forissier } 145511fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 145611fa71b9SJerome Forissier 1457817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 1458817466cbSJens Wiklander if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) 1459817466cbSJens Wiklander { 146011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1461817466cbSJens Wiklander 1462817466cbSJens Wiklander *olen = ilen; 1463817466cbSJens Wiklander ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, 1464817466cbSJens Wiklander iv, iv_len, ad, ad_len, 1465817466cbSJens Wiklander tag, tag_len, input, output ); 1466817466cbSJens Wiklander 1467817466cbSJens Wiklander if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) 1468817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1469817466cbSJens Wiklander 1470817466cbSJens Wiklander return( ret ); 1471817466cbSJens Wiklander } 1472817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1473817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 1474817466cbSJens Wiklander if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) 1475817466cbSJens Wiklander { 147611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1477817466cbSJens Wiklander 1478817466cbSJens Wiklander *olen = ilen; 1479817466cbSJens Wiklander ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, 1480817466cbSJens Wiklander iv, iv_len, ad, ad_len, 1481817466cbSJens Wiklander input, output, tag, tag_len ); 1482817466cbSJens Wiklander 1483817466cbSJens Wiklander if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) 1484817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1485817466cbSJens Wiklander 1486817466cbSJens Wiklander return( ret ); 1487817466cbSJens Wiklander } 1488817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */ 14893d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 14903d3b0591SJens Wiklander if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) 14913d3b0591SJens Wiklander { 149211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 14933d3b0591SJens Wiklander 14943d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */ 14953d3b0591SJens Wiklander if ( ( iv_len != ctx->cipher_info->iv_size ) || 14963d3b0591SJens Wiklander ( tag_len != 16U ) ) 14973d3b0591SJens Wiklander { 14983d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 14993d3b0591SJens Wiklander } 15003d3b0591SJens Wiklander 15013d3b0591SJens Wiklander *olen = ilen; 15023d3b0591SJens Wiklander ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, 15033d3b0591SJens Wiklander iv, ad, ad_len, tag, input, output ); 15043d3b0591SJens Wiklander 15053d3b0591SJens Wiklander if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) 15063d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 15073d3b0591SJens Wiklander 15083d3b0591SJens Wiklander return( ret ); 15093d3b0591SJens Wiklander } 15103d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 15117901324dSJerome Forissier 15127901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 15137901324dSJerome Forissier } 15147901324dSJerome Forissier 15157901324dSJerome Forissier #if !defined(MBEDTLS_DEPRECATED_REMOVED) 15167901324dSJerome Forissier /* 15177901324dSJerome Forissier * Packet-oriented encryption for AEAD modes: public legacy function. 15187901324dSJerome Forissier */ 15197901324dSJerome Forissier int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, 15207901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 15217901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 15227901324dSJerome Forissier const unsigned char *input, size_t ilen, 15237901324dSJerome Forissier unsigned char *output, size_t *olen, 15247901324dSJerome Forissier unsigned char *tag, size_t tag_len ) 15257901324dSJerome Forissier { 15267901324dSJerome Forissier CIPHER_VALIDATE_RET( ctx != NULL ); 15277901324dSJerome Forissier CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 15287901324dSJerome Forissier CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 15297901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 15307901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || output != NULL ); 15317901324dSJerome Forissier CIPHER_VALIDATE_RET( olen != NULL ); 15327901324dSJerome Forissier CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 15337901324dSJerome Forissier 15347901324dSJerome Forissier return( mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len, 15357901324dSJerome Forissier input, ilen, output, olen, 15367901324dSJerome Forissier tag, tag_len ) ); 15377901324dSJerome Forissier } 15387901324dSJerome Forissier 15397901324dSJerome Forissier /* 15407901324dSJerome Forissier * Packet-oriented decryption for AEAD modes: public legacy function. 15417901324dSJerome Forissier */ 15427901324dSJerome Forissier int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, 15437901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 15447901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 15457901324dSJerome Forissier const unsigned char *input, size_t ilen, 15467901324dSJerome Forissier unsigned char *output, size_t *olen, 15477901324dSJerome Forissier const unsigned char *tag, size_t tag_len ) 15487901324dSJerome Forissier { 15497901324dSJerome Forissier CIPHER_VALIDATE_RET( ctx != NULL ); 15507901324dSJerome Forissier CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 15517901324dSJerome Forissier CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 15527901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 15537901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || output != NULL ); 15547901324dSJerome Forissier CIPHER_VALIDATE_RET( olen != NULL ); 15557901324dSJerome Forissier CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); 15567901324dSJerome Forissier 15577901324dSJerome Forissier return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len, 15587901324dSJerome Forissier input, ilen, output, olen, 15597901324dSJerome Forissier tag, tag_len ) ); 15607901324dSJerome Forissier } 15617901324dSJerome Forissier #endif /* !MBEDTLS_DEPRECATED_REMOVED */ 15627901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 15637901324dSJerome Forissier 15647901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) 15657901324dSJerome Forissier /* 15667901324dSJerome Forissier * Packet-oriented encryption for AEAD/NIST_KW: public function. 15677901324dSJerome Forissier */ 15687901324dSJerome Forissier int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx, 15697901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 15707901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 15717901324dSJerome Forissier const unsigned char *input, size_t ilen, 15727901324dSJerome Forissier unsigned char *output, size_t output_len, 15737901324dSJerome Forissier size_t *olen, size_t tag_len ) 15747901324dSJerome Forissier { 15757901324dSJerome Forissier CIPHER_VALIDATE_RET( ctx != NULL ); 15767901324dSJerome Forissier CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 15777901324dSJerome Forissier CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 15787901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 15797901324dSJerome Forissier CIPHER_VALIDATE_RET( output != NULL ); 15807901324dSJerome Forissier CIPHER_VALIDATE_RET( olen != NULL ); 15817901324dSJerome Forissier 158211fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 15837901324dSJerome Forissier if( 15847901324dSJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 15857901324dSJerome Forissier ctx->psa_enabled == 0 && 15867901324dSJerome Forissier #endif 15877901324dSJerome Forissier ( MBEDTLS_MODE_KW == ctx->cipher_info->mode || 15887901324dSJerome Forissier MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) ) 158911fa71b9SJerome Forissier { 159011fa71b9SJerome Forissier mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? 159111fa71b9SJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; 159211fa71b9SJerome Forissier 15937901324dSJerome Forissier /* There is no iv, tag or ad associated with KW and KWP, 15947901324dSJerome Forissier * so these length should be 0 as documented. */ 159511fa71b9SJerome Forissier if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) 159611fa71b9SJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 159711fa71b9SJerome Forissier 15987901324dSJerome Forissier (void) iv; 15997901324dSJerome Forissier (void) ad; 16007901324dSJerome Forissier 16017901324dSJerome Forissier return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen, 16027901324dSJerome Forissier output, olen, output_len ) ); 160311fa71b9SJerome Forissier } 160411fa71b9SJerome Forissier #endif /* MBEDTLS_NIST_KW_C */ 1605817466cbSJens Wiklander 16067901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) 16077901324dSJerome Forissier /* AEAD case: check length before passing on to shared function */ 16087901324dSJerome Forissier if( output_len < ilen + tag_len ) 16097901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 16107901324dSJerome Forissier 16117901324dSJerome Forissier int ret = mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len, 16127901324dSJerome Forissier input, ilen, output, olen, 16137901324dSJerome Forissier output + ilen, tag_len ); 16147901324dSJerome Forissier *olen += tag_len; 16157901324dSJerome Forissier return( ret ); 16167901324dSJerome Forissier #else 1617817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1618817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 16197901324dSJerome Forissier } 16207901324dSJerome Forissier 16217901324dSJerome Forissier /* 16227901324dSJerome Forissier * Packet-oriented decryption for AEAD/NIST_KW: public function. 16237901324dSJerome Forissier */ 16247901324dSJerome Forissier int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx, 16257901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 16267901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 16277901324dSJerome Forissier const unsigned char *input, size_t ilen, 16287901324dSJerome Forissier unsigned char *output, size_t output_len, 16297901324dSJerome Forissier size_t *olen, size_t tag_len ) 16307901324dSJerome Forissier { 16317901324dSJerome Forissier CIPHER_VALIDATE_RET( ctx != NULL ); 16327901324dSJerome Forissier CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); 16337901324dSJerome Forissier CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); 16347901324dSJerome Forissier CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); 16357901324dSJerome Forissier CIPHER_VALIDATE_RET( output_len == 0 || output != NULL ); 16367901324dSJerome Forissier CIPHER_VALIDATE_RET( olen != NULL ); 16377901324dSJerome Forissier 16387901324dSJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 16397901324dSJerome Forissier if( 16407901324dSJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 16417901324dSJerome Forissier ctx->psa_enabled == 0 && 16427901324dSJerome Forissier #endif 16437901324dSJerome Forissier ( MBEDTLS_MODE_KW == ctx->cipher_info->mode || 16447901324dSJerome Forissier MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) ) 16457901324dSJerome Forissier { 16467901324dSJerome Forissier mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? 16477901324dSJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; 16487901324dSJerome Forissier 16497901324dSJerome Forissier /* There is no iv, tag or ad associated with KW and KWP, 16507901324dSJerome Forissier * so these length should be 0 as documented. */ 16517901324dSJerome Forissier if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) 16527901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 16537901324dSJerome Forissier 16547901324dSJerome Forissier (void) iv; 16557901324dSJerome Forissier (void) ad; 16567901324dSJerome Forissier 16577901324dSJerome Forissier return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen, 16587901324dSJerome Forissier output, olen, output_len ) ); 16597901324dSJerome Forissier } 16607901324dSJerome Forissier #endif /* MBEDTLS_NIST_KW_C */ 16617901324dSJerome Forissier 16627901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) 16637901324dSJerome Forissier /* AEAD case: check length before passing on to shared function */ 16647901324dSJerome Forissier if( ilen < tag_len || output_len < ilen - tag_len ) 16657901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 16667901324dSJerome Forissier 16677901324dSJerome Forissier return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len, 16687901324dSJerome Forissier input, ilen - tag_len, output, olen, 16697901324dSJerome Forissier input + ilen - tag_len, tag_len ) ); 16707901324dSJerome Forissier #else 16717901324dSJerome Forissier return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 16727901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 16737901324dSJerome Forissier } 16747901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ 1675817466cbSJens Wiklander 1676817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_C */ 1677