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" 29*32b31808SJens Wiklander #include "cipher_wrap.h" 303d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 3111fa71b9SJerome Forissier #include "mbedtls/error.h" 32039e02dfSJerome 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 #include "mbedtls/platform.h" 67817466cbSJens Wiklander 68817466cbSJens Wiklander static int supported_init = 0; 69817466cbSJens Wiklander 70817466cbSJens Wiklander const int *mbedtls_cipher_list(void) 71817466cbSJens Wiklander { 72817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 73817466cbSJens Wiklander int *type; 74817466cbSJens Wiklander 75*32b31808SJens Wiklander if (!supported_init) { 76817466cbSJens Wiklander def = mbedtls_cipher_definitions; 77817466cbSJens Wiklander type = mbedtls_cipher_supported; 78817466cbSJens Wiklander 79*32b31808SJens Wiklander while (def->type != 0) { 80817466cbSJens Wiklander *type++ = (*def++).type; 81*32b31808SJens Wiklander } 82817466cbSJens Wiklander 83817466cbSJens Wiklander *type = 0; 84817466cbSJens Wiklander 85817466cbSJens Wiklander supported_init = 1; 86817466cbSJens Wiklander } 87817466cbSJens Wiklander 88*32b31808SJens Wiklander return mbedtls_cipher_supported; 89817466cbSJens Wiklander } 90817466cbSJens Wiklander 9111fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( 9211fa71b9SJerome Forissier const mbedtls_cipher_type_t cipher_type) 93817466cbSJens Wiklander { 94817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 95817466cbSJens Wiklander 96*32b31808SJens Wiklander for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { 97*32b31808SJens Wiklander if (def->type == cipher_type) { 98*32b31808SJens Wiklander return def->info; 99*32b31808SJens Wiklander } 100*32b31808SJens Wiklander } 101817466cbSJens Wiklander 102*32b31808SJens Wiklander return NULL; 103817466cbSJens Wiklander } 104817466cbSJens Wiklander 10511fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( 10611fa71b9SJerome Forissier const char *cipher_name) 107817466cbSJens Wiklander { 108817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 109817466cbSJens Wiklander 110*32b31808SJens Wiklander if (NULL == cipher_name) { 111*32b31808SJens Wiklander return NULL; 112*32b31808SJens Wiklander } 113817466cbSJens Wiklander 114*32b31808SJens Wiklander for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { 115*32b31808SJens Wiklander if (!strcmp(def->info->name, cipher_name)) { 116*32b31808SJens Wiklander return def->info; 117*32b31808SJens Wiklander } 118*32b31808SJens Wiklander } 119817466cbSJens Wiklander 120*32b31808SJens Wiklander return NULL; 121817466cbSJens Wiklander } 122817466cbSJens Wiklander 12311fa71b9SJerome Forissier const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( 12411fa71b9SJerome Forissier const mbedtls_cipher_id_t cipher_id, 125817466cbSJens Wiklander int key_bitlen, 126817466cbSJens Wiklander const mbedtls_cipher_mode_t mode) 127817466cbSJens Wiklander { 128817466cbSJens Wiklander const mbedtls_cipher_definition_t *def; 129817466cbSJens Wiklander 130*32b31808SJens Wiklander for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { 131817466cbSJens Wiklander if (def->info->base->cipher == cipher_id && 132817466cbSJens Wiklander def->info->key_bitlen == (unsigned) key_bitlen && 133*32b31808SJens Wiklander def->info->mode == mode) { 134*32b31808SJens Wiklander return def->info; 135*32b31808SJens Wiklander } 136*32b31808SJens Wiklander } 137817466cbSJens Wiklander 138*32b31808SJens Wiklander return NULL; 139817466cbSJens Wiklander } 140817466cbSJens Wiklander 141817466cbSJens Wiklander void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx) 142817466cbSJens Wiklander { 143817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); 144817466cbSJens Wiklander } 145817466cbSJens Wiklander 146817466cbSJens Wiklander void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx) 147817466cbSJens Wiklander { 148*32b31808SJens Wiklander if (ctx == NULL) { 149817466cbSJens Wiklander return; 150*32b31808SJens Wiklander } 151817466cbSJens Wiklander 15211fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 153*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 154*32b31808SJens Wiklander if (ctx->cipher_ctx != NULL) { 15511fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 15611fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 15711fa71b9SJerome Forissier 158*32b31808SJens Wiklander if (cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED) { 15911fa71b9SJerome Forissier /* xxx_free() doesn't allow to return failures. */ 16011fa71b9SJerome Forissier (void) psa_destroy_key(cipher_psa->slot); 16111fa71b9SJerome Forissier } 16211fa71b9SJerome Forissier 16311fa71b9SJerome Forissier mbedtls_platform_zeroize(cipher_psa, sizeof(*cipher_psa)); 16411fa71b9SJerome Forissier mbedtls_free(cipher_psa); 16511fa71b9SJerome Forissier } 16611fa71b9SJerome Forissier 16711fa71b9SJerome Forissier mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t)); 16811fa71b9SJerome Forissier return; 16911fa71b9SJerome Forissier } 17011fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 17111fa71b9SJerome Forissier 172817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C) 173*32b31808SJens Wiklander if (ctx->cmac_ctx) { 1743d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx->cmac_ctx, 1753d3b0591SJens Wiklander sizeof(mbedtls_cmac_context_t)); 176817466cbSJens Wiklander mbedtls_free(ctx->cmac_ctx); 177817466cbSJens Wiklander } 178817466cbSJens Wiklander #endif 179817466cbSJens Wiklander 180*32b31808SJens Wiklander if (ctx->cipher_ctx) { 181817466cbSJens Wiklander ctx->cipher_info->base->ctx_free_func(ctx->cipher_ctx); 182*32b31808SJens Wiklander } 183817466cbSJens Wiklander 1843d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t)); 185817466cbSJens Wiklander } 186817466cbSJens Wiklander 18712484fc7SEdison Ai int mbedtls_cipher_clone(mbedtls_cipher_context_t *dst, 18812484fc7SEdison Ai const mbedtls_cipher_context_t *src) 18912484fc7SEdison Ai { 19012484fc7SEdison Ai if (dst == NULL || dst->cipher_info == NULL || 191*32b31808SJens Wiklander src == NULL || src->cipher_info == NULL) { 192*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 19312484fc7SEdison Ai } 19412484fc7SEdison Ai 19512484fc7SEdison Ai dst->cipher_info = src->cipher_info; 19612484fc7SEdison Ai dst->key_bitlen = src->key_bitlen; 19712484fc7SEdison Ai dst->operation = src->operation; 19812484fc7SEdison Ai #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 19912484fc7SEdison Ai dst->add_padding = src->add_padding; 20012484fc7SEdison Ai dst->get_padding = src->get_padding; 20112484fc7SEdison Ai #endif 20212484fc7SEdison Ai memcpy(dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH); 20312484fc7SEdison Ai dst->unprocessed_len = src->unprocessed_len; 20412484fc7SEdison Ai memcpy(dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH); 20512484fc7SEdison Ai dst->iv_size = src->iv_size; 20612484fc7SEdison Ai if (dst->cipher_info->base->ctx_clone_func) 20712484fc7SEdison Ai dst->cipher_info->base->ctx_clone_func(dst->cipher_ctx, src->cipher_ctx); 20812484fc7SEdison Ai 20912484fc7SEdison Ai #if defined(MBEDTLS_CMAC_C) 21012484fc7SEdison Ai if (dst->cmac_ctx != NULL && src->cmac_ctx != NULL) 21112484fc7SEdison Ai memcpy(dst->cmac_ctx, src->cmac_ctx, sizeof(mbedtls_cmac_context_t)); 21212484fc7SEdison Ai #endif 213*32b31808SJens Wiklander return 0; 21412484fc7SEdison Ai } 21512484fc7SEdison Ai 21611fa71b9SJerome Forissier int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, 21711fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info) 218817466cbSJens Wiklander { 219*32b31808SJens Wiklander if (cipher_info == NULL) { 220*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 221*32b31808SJens Wiklander } 222817466cbSJens Wiklander 223817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); 224817466cbSJens Wiklander 225*32b31808SJens Wiklander if (NULL == (ctx->cipher_ctx = cipher_info->base->ctx_alloc_func())) { 226*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; 227*32b31808SJens Wiklander } 228817466cbSJens Wiklander 229817466cbSJens Wiklander ctx->cipher_info = cipher_info; 230817466cbSJens Wiklander 231817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 232817466cbSJens Wiklander /* 233817466cbSJens Wiklander * Ignore possible errors caused by a cipher mode that doesn't use padding 234817466cbSJens Wiklander */ 235817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 236817466cbSJens Wiklander (void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_PKCS7); 237817466cbSJens Wiklander #else 238817466cbSJens Wiklander (void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_NONE); 239817466cbSJens Wiklander #endif 240817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 241817466cbSJens Wiklander 242*32b31808SJens Wiklander return 0; 243817466cbSJens Wiklander } 244817466cbSJens Wiklander 24511fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 246*32b31808SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED) 24711fa71b9SJerome Forissier int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, 24811fa71b9SJerome Forissier const mbedtls_cipher_info_t *cipher_info, 24911fa71b9SJerome Forissier size_t taglen) 25011fa71b9SJerome Forissier { 25111fa71b9SJerome Forissier psa_algorithm_t alg; 25211fa71b9SJerome Forissier mbedtls_cipher_context_psa *cipher_psa; 25311fa71b9SJerome Forissier 254*32b31808SJens Wiklander if (NULL == cipher_info || NULL == ctx) { 255*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 256*32b31808SJens Wiklander } 25711fa71b9SJerome Forissier 25811fa71b9SJerome Forissier /* Check that the underlying cipher mode and cipher type are 25911fa71b9SJerome Forissier * supported by the underlying PSA Crypto implementation. */ 26011fa71b9SJerome Forissier alg = mbedtls_psa_translate_cipher_mode(cipher_info->mode, taglen); 261*32b31808SJens Wiklander if (alg == 0) { 262*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 263*32b31808SJens Wiklander } 264*32b31808SJens Wiklander if (mbedtls_psa_translate_cipher_type(cipher_info->type) == 0) { 265*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 266*32b31808SJens Wiklander } 26711fa71b9SJerome Forissier 26811fa71b9SJerome Forissier memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); 26911fa71b9SJerome Forissier 27011fa71b9SJerome Forissier cipher_psa = mbedtls_calloc(1, sizeof(mbedtls_cipher_context_psa)); 271*32b31808SJens Wiklander if (cipher_psa == NULL) { 272*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; 273*32b31808SJens Wiklander } 27411fa71b9SJerome Forissier cipher_psa->alg = alg; 27511fa71b9SJerome Forissier ctx->cipher_ctx = cipher_psa; 27611fa71b9SJerome Forissier ctx->cipher_info = cipher_info; 27711fa71b9SJerome Forissier ctx->psa_enabled = 1; 278*32b31808SJens Wiklander return 0; 27911fa71b9SJerome Forissier } 280*32b31808SJens Wiklander #endif /* MBEDTLS_DEPRECATED_REMOVED */ 28111fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 28211fa71b9SJerome Forissier 283*32b31808SJens Wiklander int mbedtls_cipher_setup_info(mbedtls_cipher_context_t *ctx, 284*32b31808SJens Wiklander const mbedtls_cipher_info_t *cipher_info ) 28512484fc7SEdison Ai { 28612484fc7SEdison Ai if (NULL == cipher_info || NULL == ctx) 287*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 28812484fc7SEdison Ai 28912484fc7SEdison Ai ctx->cipher_info = cipher_info; 290*32b31808SJens Wiklander return 0; 29112484fc7SEdison Ai } 29212484fc7SEdison Ai 2933d3b0591SJens Wiklander int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, 2943d3b0591SJens Wiklander const unsigned char *key, 2953d3b0591SJens Wiklander int key_bitlen, 2963d3b0591SJens Wiklander const mbedtls_operation_t operation) 297817466cbSJens Wiklander { 298*32b31808SJens Wiklander if (operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT) { 299*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 300*32b31808SJens Wiklander } 301*32b31808SJens Wiklander if (ctx->cipher_info == NULL) { 302*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 303*32b31808SJens Wiklander } 304817466cbSJens Wiklander 30511fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 306*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 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. */ 317*32b31808SJens Wiklander if (key_bitlen % 8 != 0) { 318*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 319*32b31808SJens Wiklander } 32011fa71b9SJerome Forissier 32111fa71b9SJerome Forissier /* Don't allow keys to be set multiple times. */ 322*32b31808SJens Wiklander if (cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET) { 323*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 324*32b31808SJens Wiklander } 32511fa71b9SJerome Forissier 32611fa71b9SJerome Forissier key_type = mbedtls_psa_translate_cipher_type( 32711fa71b9SJerome Forissier ctx->cipher_info->type); 328*32b31808SJens Wiklander if (key_type == 0) { 329*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 330*32b31808SJens Wiklander } 33111fa71b9SJerome Forissier psa_set_key_type(&attributes, key_type); 33211fa71b9SJerome Forissier 33311fa71b9SJerome Forissier /* Mbed TLS' cipher layer doesn't enforce the mode of operation 33411fa71b9SJerome Forissier * (encrypt vs. decrypt): it is possible to setup a key for encryption 33511fa71b9SJerome Forissier * and use it for AEAD decryption. Until tests relying on this 33611fa71b9SJerome Forissier * are changed, allow any usage in PSA. */ 33711fa71b9SJerome Forissier psa_set_key_usage_flags(&attributes, 33811fa71b9SJerome Forissier /* mbedtls_psa_translate_cipher_operation( operation ); */ 33911fa71b9SJerome Forissier PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); 34011fa71b9SJerome Forissier psa_set_key_algorithm(&attributes, cipher_psa->alg); 34111fa71b9SJerome Forissier 34211fa71b9SJerome Forissier status = psa_import_key(&attributes, key, key_bytelen, 34311fa71b9SJerome Forissier &cipher_psa->slot); 344*32b31808SJens Wiklander switch (status) { 34511fa71b9SJerome Forissier case PSA_SUCCESS: 34611fa71b9SJerome Forissier break; 34711fa71b9SJerome Forissier case PSA_ERROR_INSUFFICIENT_MEMORY: 348*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; 34911fa71b9SJerome Forissier case PSA_ERROR_NOT_SUPPORTED: 350*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 35111fa71b9SJerome Forissier default: 352*32b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 35311fa71b9SJerome Forissier } 35411fa71b9SJerome Forissier /* Indicate that we own the key slot and need to 35511fa71b9SJerome Forissier * destroy it in mbedtls_cipher_free(). */ 35611fa71b9SJerome Forissier cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; 35711fa71b9SJerome Forissier 35811fa71b9SJerome Forissier ctx->key_bitlen = key_bitlen; 35911fa71b9SJerome Forissier ctx->operation = operation; 360*32b31808SJens Wiklander return 0; 36111fa71b9SJerome Forissier } 36211fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 36311fa71b9SJerome Forissier 364817466cbSJens Wiklander if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN) == 0 && 365*32b31808SJens Wiklander (int) ctx->cipher_info->key_bitlen != key_bitlen) { 366*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 367817466cbSJens Wiklander } 368817466cbSJens Wiklander 369817466cbSJens Wiklander ctx->key_bitlen = key_bitlen; 370817466cbSJens Wiklander ctx->operation = operation; 371817466cbSJens Wiklander 372817466cbSJens Wiklander /* 3733d3b0591SJens Wiklander * For OFB, CFB and CTR mode always use the encryption key schedule 374817466cbSJens Wiklander */ 375817466cbSJens Wiklander if (MBEDTLS_ENCRYPT == operation || 376817466cbSJens Wiklander MBEDTLS_MODE_CFB == ctx->cipher_info->mode || 3773d3b0591SJens Wiklander MBEDTLS_MODE_OFB == ctx->cipher_info->mode || 378*32b31808SJens Wiklander MBEDTLS_MODE_CTR == ctx->cipher_info->mode) { 379*32b31808SJens Wiklander return ctx->cipher_info->base->setkey_enc_func(ctx->cipher_ctx, key, 380*32b31808SJens Wiklander ctx->key_bitlen); 381817466cbSJens Wiklander } 382817466cbSJens Wiklander 383*32b31808SJens Wiklander if (MBEDTLS_DECRYPT == operation) { 384*32b31808SJens Wiklander return ctx->cipher_info->base->setkey_dec_func(ctx->cipher_ctx, key, 385*32b31808SJens Wiklander ctx->key_bitlen); 386*32b31808SJens Wiklander } 387817466cbSJens Wiklander 388*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 389817466cbSJens Wiklander } 390817466cbSJens Wiklander 391817466cbSJens Wiklander int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, 3923d3b0591SJens Wiklander const unsigned char *iv, 3933d3b0591SJens Wiklander size_t iv_len) 394817466cbSJens Wiklander { 395817466cbSJens Wiklander size_t actual_iv_size; 396817466cbSJens Wiklander 397*32b31808SJens Wiklander if (ctx->cipher_info == NULL) { 398*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 399*32b31808SJens Wiklander } 40011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 401*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 40211fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 40311fa71b9SJerome Forissier * operations, we currently don't make it 40411fa71b9SJerome Forissier * accessible through the cipher layer. */ 405*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 40611fa71b9SJerome Forissier } 40711fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 408817466cbSJens Wiklander 409817466cbSJens Wiklander /* avoid buffer overflow in ctx->iv */ 410*32b31808SJens Wiklander if (iv_len > MBEDTLS_MAX_IV_LENGTH) { 411*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 412*32b31808SJens Wiklander } 413817466cbSJens Wiklander 414*32b31808SJens Wiklander if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN) != 0) { 415817466cbSJens Wiklander actual_iv_size = iv_len; 416*32b31808SJens Wiklander } else { 417817466cbSJens Wiklander actual_iv_size = ctx->cipher_info->iv_size; 418817466cbSJens Wiklander 419817466cbSJens Wiklander /* avoid reading past the end of input buffer */ 420*32b31808SJens Wiklander if (actual_iv_size > iv_len) { 421*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 422*32b31808SJens Wiklander } 423817466cbSJens Wiklander } 424817466cbSJens Wiklander 4253d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C) 426*32b31808SJens Wiklander if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20) { 427039e02dfSJerome Forissier /* Even though the actual_iv_size is overwritten with a correct value 428039e02dfSJerome Forissier * of 12 from the cipher info, return an error to indicate that 429039e02dfSJerome Forissier * the input iv_len is wrong. */ 430*32b31808SJens Wiklander if (iv_len != 12) { 431*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 432*32b31808SJens Wiklander } 433039e02dfSJerome Forissier 4343d3b0591SJens Wiklander if (0 != mbedtls_chacha20_starts((mbedtls_chacha20_context *) ctx->cipher_ctx, 4353d3b0591SJens Wiklander iv, 436*32b31808SJens Wiklander 0U)) { /* Initial counter value */ 437*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 4383d3b0591SJens Wiklander } 4393d3b0591SJens Wiklander } 440039e02dfSJerome Forissier #if defined(MBEDTLS_CHACHAPOLY_C) 441039e02dfSJerome Forissier if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 && 442*32b31808SJens Wiklander iv_len != 12) { 443*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 444*32b31808SJens Wiklander } 445039e02dfSJerome Forissier #endif 4463d3b0591SJens Wiklander #endif 4473d3b0591SJens Wiklander 448*32b31808SJens Wiklander #if defined(MBEDTLS_GCM_C) 449*32b31808SJens Wiklander if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { 450*32b31808SJens Wiklander return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx, 451*32b31808SJens Wiklander ctx->operation, 452*32b31808SJens Wiklander iv, iv_len); 453*32b31808SJens Wiklander } 454*32b31808SJens Wiklander #endif 455*32b31808SJens Wiklander 456*32b31808SJens Wiklander #if defined(MBEDTLS_CCM_C) 457*32b31808SJens Wiklander if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode) { 458*32b31808SJens Wiklander int set_lengths_result; 459*32b31808SJens Wiklander int ccm_star_mode; 460*32b31808SJens Wiklander 461*32b31808SJens Wiklander set_lengths_result = mbedtls_ccm_set_lengths( 462*32b31808SJens Wiklander (mbedtls_ccm_context *) ctx->cipher_ctx, 463*32b31808SJens Wiklander 0, 0, 0); 464*32b31808SJens Wiklander if (set_lengths_result != 0) { 465*32b31808SJens Wiklander return set_lengths_result; 466*32b31808SJens Wiklander } 467*32b31808SJens Wiklander 468*32b31808SJens Wiklander if (ctx->operation == MBEDTLS_DECRYPT) { 469*32b31808SJens Wiklander ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT; 470*32b31808SJens Wiklander } else if (ctx->operation == MBEDTLS_ENCRYPT) { 471*32b31808SJens Wiklander ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT; 472*32b31808SJens Wiklander } else { 473*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 474*32b31808SJens Wiklander } 475*32b31808SJens Wiklander 476*32b31808SJens Wiklander return mbedtls_ccm_starts((mbedtls_ccm_context *) ctx->cipher_ctx, 477*32b31808SJens Wiklander ccm_star_mode, 478*32b31808SJens Wiklander iv, iv_len); 479*32b31808SJens Wiklander } 480*32b31808SJens Wiklander #endif 481*32b31808SJens Wiklander 482*32b31808SJens Wiklander if (actual_iv_size != 0) { 483817466cbSJens Wiklander memcpy(ctx->iv, iv, actual_iv_size); 484817466cbSJens Wiklander ctx->iv_size = actual_iv_size; 4853d3b0591SJens Wiklander } 486817466cbSJens Wiklander 487*32b31808SJens Wiklander return 0; 488817466cbSJens Wiklander } 489817466cbSJens Wiklander 490817466cbSJens Wiklander int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx) 491817466cbSJens Wiklander { 492*32b31808SJens Wiklander if (ctx->cipher_info == NULL) { 493*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 494*32b31808SJens Wiklander } 495817466cbSJens Wiklander 49611fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 497*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 49811fa71b9SJerome Forissier /* We don't support resetting PSA-based 49911fa71b9SJerome Forissier * cipher contexts, yet. */ 500*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 50111fa71b9SJerome Forissier } 50211fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 50311fa71b9SJerome Forissier 504817466cbSJens Wiklander ctx->unprocessed_len = 0; 505817466cbSJens Wiklander 506*32b31808SJens Wiklander return 0; 507817466cbSJens Wiklander } 508817466cbSJens Wiklander 5093d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 510817466cbSJens Wiklander int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, 511817466cbSJens Wiklander const unsigned char *ad, size_t ad_len) 512817466cbSJens Wiklander { 513*32b31808SJens Wiklander if (ctx->cipher_info == NULL) { 514*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 515*32b31808SJens Wiklander } 516817466cbSJens Wiklander 51711fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 518*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 51911fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 52011fa71b9SJerome Forissier * operations, we currently don't make it 52111fa71b9SJerome Forissier * accessible through the cipher layer. */ 522*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 52311fa71b9SJerome Forissier } 52411fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 52511fa71b9SJerome Forissier 5263d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 527*32b31808SJens Wiklander if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { 528*32b31808SJens Wiklander return mbedtls_gcm_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx, 529*32b31808SJens Wiklander ad, ad_len); 530817466cbSJens Wiklander } 5313d3b0591SJens Wiklander #endif 5323d3b0591SJens Wiklander 5333d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 534*32b31808SJens Wiklander if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { 5353d3b0591SJens Wiklander int result; 5363d3b0591SJens Wiklander mbedtls_chachapoly_mode_t mode; 5373d3b0591SJens Wiklander 5383d3b0591SJens Wiklander mode = (ctx->operation == MBEDTLS_ENCRYPT) 5393d3b0591SJens Wiklander ? MBEDTLS_CHACHAPOLY_ENCRYPT 5403d3b0591SJens Wiklander : MBEDTLS_CHACHAPOLY_DECRYPT; 5413d3b0591SJens Wiklander 5423d3b0591SJens Wiklander result = mbedtls_chachapoly_starts((mbedtls_chachapoly_context *) ctx->cipher_ctx, 5433d3b0591SJens Wiklander ctx->iv, 5443d3b0591SJens Wiklander mode); 545*32b31808SJens Wiklander if (result != 0) { 546*32b31808SJens Wiklander return result; 547*32b31808SJens Wiklander } 5483d3b0591SJens Wiklander 549*32b31808SJens Wiklander return mbedtls_chachapoly_update_aad((mbedtls_chachapoly_context *) ctx->cipher_ctx, 550*32b31808SJens Wiklander ad, ad_len); 5513d3b0591SJens Wiklander } 5523d3b0591SJens Wiklander #endif 553817466cbSJens Wiklander 554*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 555817466cbSJens Wiklander } 5563d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 557817466cbSJens Wiklander 558817466cbSJens Wiklander int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, 559817466cbSJens Wiklander size_t ilen, unsigned char *output, size_t *olen) 560817466cbSJens Wiklander { 56111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 5623d3b0591SJens Wiklander size_t block_size; 563817466cbSJens Wiklander 564*32b31808SJens Wiklander if (ctx->cipher_info == NULL) { 565*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 566*32b31808SJens Wiklander } 567817466cbSJens Wiklander 56811fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 569*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 57011fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 57111fa71b9SJerome Forissier * operations, we currently don't make it 57211fa71b9SJerome Forissier * accessible through the cipher layer. */ 573*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 57411fa71b9SJerome Forissier } 57511fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 57611fa71b9SJerome Forissier 577817466cbSJens Wiklander *olen = 0; 578817466cbSJens Wiklander block_size = mbedtls_cipher_get_block_size(ctx); 579*32b31808SJens Wiklander if (0 == block_size) { 580*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; 5815b25c76aSJerome Forissier } 582817466cbSJens Wiklander 583*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_ECB) { 584*32b31808SJens Wiklander if (ilen != block_size) { 585*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; 586*32b31808SJens Wiklander } 587817466cbSJens Wiklander 588817466cbSJens Wiklander *olen = ilen; 589817466cbSJens Wiklander 590817466cbSJens Wiklander if (0 != (ret = ctx->cipher_info->base->ecb_func(ctx->cipher_ctx, 591*32b31808SJens Wiklander ctx->operation, input, output))) { 592*32b31808SJens Wiklander return ret; 593817466cbSJens Wiklander } 594817466cbSJens Wiklander 595*32b31808SJens Wiklander return 0; 596817466cbSJens Wiklander } 597817466cbSJens Wiklander 598817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 599*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_GCM) { 600*32b31808SJens Wiklander return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx, 601*32b31808SJens Wiklander input, ilen, 602*32b31808SJens Wiklander output, ilen, olen); 603*32b31808SJens Wiklander } 604*32b31808SJens Wiklander #endif 605*32b31808SJens Wiklander 606*32b31808SJens Wiklander #if defined(MBEDTLS_CCM_C) 607*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_CCM_STAR_NO_TAG) { 608*32b31808SJens Wiklander return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx, 609*32b31808SJens Wiklander input, ilen, 610*32b31808SJens Wiklander output, ilen, olen); 6113d3b0591SJens Wiklander } 6123d3b0591SJens Wiklander #endif 6133d3b0591SJens Wiklander 6143d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 615*32b31808SJens Wiklander if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) { 6163d3b0591SJens Wiklander *olen = ilen; 617*32b31808SJens Wiklander return mbedtls_chachapoly_update((mbedtls_chachapoly_context *) ctx->cipher_ctx, 618*32b31808SJens Wiklander ilen, input, output); 619817466cbSJens Wiklander } 620817466cbSJens Wiklander #endif 621817466cbSJens Wiklander 622817466cbSJens Wiklander if (input == output && 623*32b31808SJens Wiklander (ctx->unprocessed_len != 0 || ilen % block_size)) { 624*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 625817466cbSJens Wiklander } 626817466cbSJens Wiklander 627817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC) 628*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_CBC) { 629817466cbSJens Wiklander size_t copy_len = 0; 630817466cbSJens Wiklander 631817466cbSJens Wiklander /* 632817466cbSJens Wiklander * If there is not enough data for a full block, cache it. 633817466cbSJens Wiklander */ 6343d3b0591SJens Wiklander if ((ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && 635817466cbSJens Wiklander ilen <= block_size - ctx->unprocessed_len) || 6363d3b0591SJens Wiklander (ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && 6373d3b0591SJens Wiklander ilen < block_size - ctx->unprocessed_len) || 638817466cbSJens Wiklander (ctx->operation == MBEDTLS_ENCRYPT && 639*32b31808SJens Wiklander ilen < block_size - ctx->unprocessed_len)) { 640817466cbSJens Wiklander memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, 641817466cbSJens Wiklander ilen); 642817466cbSJens Wiklander 643817466cbSJens Wiklander ctx->unprocessed_len += ilen; 644*32b31808SJens Wiklander return 0; 645817466cbSJens Wiklander } 646817466cbSJens Wiklander 647817466cbSJens Wiklander /* 648817466cbSJens Wiklander * Process cached data first 649817466cbSJens Wiklander */ 650*32b31808SJens Wiklander if (0 != ctx->unprocessed_len) { 651817466cbSJens Wiklander copy_len = block_size - ctx->unprocessed_len; 652817466cbSJens Wiklander 653817466cbSJens Wiklander memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, 654817466cbSJens Wiklander copy_len); 655817466cbSJens Wiklander 656817466cbSJens Wiklander if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx, 657817466cbSJens Wiklander ctx->operation, block_size, ctx->iv, 658*32b31808SJens Wiklander ctx->unprocessed_data, output))) { 659*32b31808SJens Wiklander return ret; 660817466cbSJens Wiklander } 661817466cbSJens Wiklander 662817466cbSJens Wiklander *olen += block_size; 663817466cbSJens Wiklander output += block_size; 664817466cbSJens Wiklander ctx->unprocessed_len = 0; 665817466cbSJens Wiklander 666817466cbSJens Wiklander input += copy_len; 667817466cbSJens Wiklander ilen -= copy_len; 668817466cbSJens Wiklander } 669817466cbSJens Wiklander 670817466cbSJens Wiklander /* 671817466cbSJens Wiklander * Cache final, incomplete block 672817466cbSJens Wiklander */ 673*32b31808SJens Wiklander if (0 != ilen) { 6743d3b0591SJens Wiklander /* Encryption: only cache partial blocks 6753d3b0591SJens Wiklander * Decryption w/ padding: always keep at least one whole block 6763d3b0591SJens Wiklander * Decryption w/o padding: only cache partial blocks 6773d3b0591SJens Wiklander */ 678817466cbSJens Wiklander copy_len = ilen % block_size; 6793d3b0591SJens Wiklander if (copy_len == 0 && 6803d3b0591SJens Wiklander ctx->operation == MBEDTLS_DECRYPT && 681*32b31808SJens Wiklander NULL != ctx->add_padding) { 682817466cbSJens Wiklander copy_len = block_size; 6833d3b0591SJens Wiklander } 684817466cbSJens Wiklander 685817466cbSJens Wiklander memcpy(ctx->unprocessed_data, &(input[ilen - copy_len]), 686817466cbSJens Wiklander copy_len); 687817466cbSJens Wiklander 688817466cbSJens Wiklander ctx->unprocessed_len += copy_len; 689817466cbSJens Wiklander ilen -= copy_len; 690817466cbSJens Wiklander } 691817466cbSJens Wiklander 692817466cbSJens Wiklander /* 693817466cbSJens Wiklander * Process remaining full blocks 694817466cbSJens Wiklander */ 695*32b31808SJens Wiklander if (ilen) { 696817466cbSJens Wiklander if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx, 697*32b31808SJens Wiklander ctx->operation, ilen, ctx->iv, input, 698*32b31808SJens Wiklander output))) { 699*32b31808SJens Wiklander return ret; 700817466cbSJens Wiklander } 701817466cbSJens Wiklander 702817466cbSJens Wiklander *olen += ilen; 703817466cbSJens Wiklander } 704817466cbSJens Wiklander 705*32b31808SJens Wiklander return 0; 706817466cbSJens Wiklander } 707817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */ 708817466cbSJens Wiklander 709817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CFB) 710*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_CFB) { 711817466cbSJens Wiklander if (0 != (ret = ctx->cipher_info->base->cfb_func(ctx->cipher_ctx, 712*32b31808SJens Wiklander ctx->operation, ilen, 713*32b31808SJens Wiklander &ctx->unprocessed_len, ctx->iv, 714*32b31808SJens Wiklander input, output))) { 715*32b31808SJens Wiklander return ret; 716817466cbSJens Wiklander } 717817466cbSJens Wiklander 718817466cbSJens Wiklander *olen = ilen; 719817466cbSJens Wiklander 720*32b31808SJens Wiklander return 0; 721817466cbSJens Wiklander } 722817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CFB */ 723817466cbSJens Wiklander 7243d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_OFB) 725*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_OFB) { 7263d3b0591SJens Wiklander if (0 != (ret = ctx->cipher_info->base->ofb_func(ctx->cipher_ctx, 727*32b31808SJens Wiklander ilen, &ctx->unprocessed_len, ctx->iv, 728*32b31808SJens Wiklander input, output))) { 729*32b31808SJens Wiklander return ret; 7303d3b0591SJens Wiklander } 7313d3b0591SJens Wiklander 7323d3b0591SJens Wiklander *olen = ilen; 7333d3b0591SJens Wiklander 734*32b31808SJens Wiklander return 0; 7353d3b0591SJens Wiklander } 7363d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_OFB */ 7373d3b0591SJens Wiklander 738817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CTR) 739*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_CTR) { 740817466cbSJens Wiklander if (0 != (ret = ctx->cipher_info->base->ctr_func(ctx->cipher_ctx, 741817466cbSJens Wiklander ilen, &ctx->unprocessed_len, ctx->iv, 742*32b31808SJens Wiklander ctx->unprocessed_data, input, output))) { 743*32b31808SJens Wiklander return ret; 744817466cbSJens Wiklander } 745817466cbSJens Wiklander 746817466cbSJens Wiklander *olen = ilen; 747817466cbSJens Wiklander 748*32b31808SJens Wiklander return 0; 749817466cbSJens Wiklander } 750817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CTR */ 751817466cbSJens Wiklander 7523d3b0591SJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_XTS) 753*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_XTS) { 7543d3b0591SJens Wiklander if (ctx->unprocessed_len > 0) { 7553d3b0591SJens Wiklander /* We can only process an entire data unit at a time. */ 756*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 7573d3b0591SJens Wiklander } 7583d3b0591SJens Wiklander 7593d3b0591SJens Wiklander ret = ctx->cipher_info->base->xts_func(ctx->cipher_ctx, 7603d3b0591SJens Wiklander ctx->operation, ilen, ctx->iv, input, output); 761*32b31808SJens Wiklander if (ret != 0) { 762*32b31808SJens Wiklander return ret; 7633d3b0591SJens Wiklander } 7643d3b0591SJens Wiklander 7653d3b0591SJens Wiklander *olen = ilen; 7663d3b0591SJens Wiklander 767*32b31808SJens Wiklander return 0; 7683d3b0591SJens Wiklander } 7693d3b0591SJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_XTS */ 7703d3b0591SJens Wiklander 771817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_STREAM) 772*32b31808SJens Wiklander if (ctx->cipher_info->mode == MBEDTLS_MODE_STREAM) { 773817466cbSJens Wiklander if (0 != (ret = ctx->cipher_info->base->stream_func(ctx->cipher_ctx, 774*32b31808SJens Wiklander ilen, input, output))) { 775*32b31808SJens Wiklander return ret; 776817466cbSJens Wiklander } 777817466cbSJens Wiklander 778817466cbSJens Wiklander *olen = ilen; 779817466cbSJens Wiklander 780*32b31808SJens Wiklander return 0; 781817466cbSJens Wiklander } 782817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_STREAM */ 783817466cbSJens Wiklander 784*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 785817466cbSJens Wiklander } 786817466cbSJens Wiklander 787817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 788817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 789817466cbSJens Wiklander /* 790817466cbSJens Wiklander * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len 791817466cbSJens Wiklander */ 792817466cbSJens Wiklander static void add_pkcs_padding(unsigned char *output, size_t output_len, 793817466cbSJens Wiklander size_t data_len) 794817466cbSJens Wiklander { 795817466cbSJens Wiklander size_t padding_len = output_len - data_len; 796817466cbSJens Wiklander unsigned char i; 797817466cbSJens Wiklander 798*32b31808SJens Wiklander for (i = 0; i < padding_len; i++) { 799817466cbSJens Wiklander output[data_len + i] = (unsigned char) padding_len; 800817466cbSJens Wiklander } 801*32b31808SJens Wiklander } 802817466cbSJens Wiklander 803817466cbSJens Wiklander static int get_pkcs_padding(unsigned char *input, size_t input_len, 804817466cbSJens Wiklander size_t *data_len) 805817466cbSJens Wiklander { 806817466cbSJens Wiklander size_t i, pad_idx; 807817466cbSJens Wiklander unsigned char padding_len, bad = 0; 808817466cbSJens Wiklander 809*32b31808SJens Wiklander if (NULL == input || NULL == data_len) { 810*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 811*32b31808SJens Wiklander } 812817466cbSJens Wiklander 813817466cbSJens Wiklander padding_len = input[input_len - 1]; 814817466cbSJens Wiklander *data_len = input_len - padding_len; 815817466cbSJens Wiklander 816817466cbSJens Wiklander /* Avoid logical || since it results in a branch */ 817817466cbSJens Wiklander bad |= padding_len > input_len; 818817466cbSJens Wiklander bad |= padding_len == 0; 819817466cbSJens Wiklander 820817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len, 821817466cbSJens Wiklander * so pick input_len, which is usually 8 or 16 (one block) */ 822817466cbSJens Wiklander pad_idx = input_len - padding_len; 823*32b31808SJens Wiklander for (i = 0; i < input_len; i++) { 824817466cbSJens Wiklander bad |= (input[i] ^ padding_len) * (i >= pad_idx); 825*32b31808SJens Wiklander } 826817466cbSJens Wiklander 827*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0); 828817466cbSJens Wiklander } 829817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ 830817466cbSJens Wiklander 831817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) 832817466cbSJens Wiklander /* 833817466cbSJens Wiklander * One and zeros padding: fill with 80 00 ... 00 834817466cbSJens Wiklander */ 835817466cbSJens Wiklander static void add_one_and_zeros_padding(unsigned char *output, 836817466cbSJens Wiklander size_t output_len, size_t data_len) 837817466cbSJens Wiklander { 838817466cbSJens Wiklander size_t padding_len = output_len - data_len; 839817466cbSJens Wiklander unsigned char i = 0; 840817466cbSJens Wiklander 841817466cbSJens Wiklander output[data_len] = 0x80; 842*32b31808SJens Wiklander for (i = 1; i < padding_len; i++) { 843817466cbSJens Wiklander output[data_len + i] = 0x00; 844817466cbSJens Wiklander } 845*32b31808SJens Wiklander } 846817466cbSJens Wiklander 847817466cbSJens Wiklander static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, 848817466cbSJens Wiklander size_t *data_len) 849817466cbSJens Wiklander { 850817466cbSJens Wiklander size_t i; 851817466cbSJens Wiklander unsigned char done = 0, prev_done, bad; 852817466cbSJens Wiklander 853*32b31808SJens Wiklander if (NULL == input || NULL == data_len) { 854*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 855*32b31808SJens Wiklander } 856817466cbSJens Wiklander 8573d3b0591SJens Wiklander bad = 0x80; 858817466cbSJens Wiklander *data_len = 0; 859*32b31808SJens Wiklander for (i = input_len; i > 0; i--) { 860817466cbSJens Wiklander prev_done = done; 861817466cbSJens Wiklander done |= (input[i - 1] != 0); 862817466cbSJens Wiklander *data_len |= (i - 1) * (done != prev_done); 8633d3b0591SJens Wiklander bad ^= input[i - 1] * (done != prev_done); 864817466cbSJens Wiklander } 865817466cbSJens Wiklander 866*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0); 867817466cbSJens Wiklander 868817466cbSJens Wiklander } 869817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ 870817466cbSJens Wiklander 871817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) 872817466cbSJens Wiklander /* 873817466cbSJens Wiklander * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length 874817466cbSJens Wiklander */ 875817466cbSJens Wiklander static void add_zeros_and_len_padding(unsigned char *output, 876817466cbSJens Wiklander size_t output_len, size_t data_len) 877817466cbSJens Wiklander { 878817466cbSJens Wiklander size_t padding_len = output_len - data_len; 879817466cbSJens Wiklander unsigned char i = 0; 880817466cbSJens Wiklander 881*32b31808SJens Wiklander for (i = 1; i < padding_len; i++) { 882817466cbSJens Wiklander output[data_len + i - 1] = 0x00; 883*32b31808SJens Wiklander } 884817466cbSJens Wiklander output[output_len - 1] = (unsigned char) padding_len; 885817466cbSJens Wiklander } 886817466cbSJens Wiklander 887817466cbSJens Wiklander static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, 888817466cbSJens Wiklander size_t *data_len) 889817466cbSJens Wiklander { 890817466cbSJens Wiklander size_t i, pad_idx; 891817466cbSJens Wiklander unsigned char padding_len, bad = 0; 892817466cbSJens Wiklander 893*32b31808SJens Wiklander if (NULL == input || NULL == data_len) { 894*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 895*32b31808SJens Wiklander } 896817466cbSJens Wiklander 897817466cbSJens Wiklander padding_len = input[input_len - 1]; 898817466cbSJens Wiklander *data_len = input_len - padding_len; 899817466cbSJens Wiklander 900817466cbSJens Wiklander /* Avoid logical || since it results in a branch */ 901817466cbSJens Wiklander bad |= padding_len > input_len; 902817466cbSJens Wiklander bad |= padding_len == 0; 903817466cbSJens Wiklander 904817466cbSJens Wiklander /* The number of bytes checked must be independent of padding_len */ 905817466cbSJens Wiklander pad_idx = input_len - padding_len; 906*32b31808SJens Wiklander for (i = 0; i < input_len - 1; i++) { 907817466cbSJens Wiklander bad |= input[i] * (i >= pad_idx); 908*32b31808SJens Wiklander } 909817466cbSJens Wiklander 910*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0); 911817466cbSJens Wiklander } 912817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ 913817466cbSJens Wiklander 914817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) 915817466cbSJens Wiklander /* 916817466cbSJens Wiklander * Zero padding: fill with 00 ... 00 917817466cbSJens Wiklander */ 918817466cbSJens Wiklander static void add_zeros_padding(unsigned char *output, 919817466cbSJens Wiklander size_t output_len, size_t data_len) 920817466cbSJens Wiklander { 921817466cbSJens Wiklander size_t i; 922817466cbSJens Wiklander 923*32b31808SJens Wiklander for (i = data_len; i < output_len; i++) { 924817466cbSJens Wiklander output[i] = 0x00; 925817466cbSJens Wiklander } 926*32b31808SJens Wiklander } 927817466cbSJens Wiklander 928817466cbSJens Wiklander static int get_zeros_padding(unsigned char *input, size_t input_len, 929817466cbSJens Wiklander size_t *data_len) 930817466cbSJens Wiklander { 931817466cbSJens Wiklander size_t i; 932817466cbSJens Wiklander unsigned char done = 0, prev_done; 933817466cbSJens Wiklander 934*32b31808SJens Wiklander if (NULL == input || NULL == data_len) { 935*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 936*32b31808SJens Wiklander } 937817466cbSJens Wiklander 938817466cbSJens Wiklander *data_len = 0; 939*32b31808SJens Wiklander for (i = input_len; i > 0; i--) { 940817466cbSJens Wiklander prev_done = done; 941817466cbSJens Wiklander done |= (input[i-1] != 0); 942817466cbSJens Wiklander *data_len |= i * (done != prev_done); 943817466cbSJens Wiklander } 944817466cbSJens Wiklander 945*32b31808SJens Wiklander return 0; 946817466cbSJens Wiklander } 947817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ 948817466cbSJens Wiklander 949817466cbSJens Wiklander /* 950817466cbSJens Wiklander * No padding: don't pad :) 951817466cbSJens Wiklander * 952817466cbSJens Wiklander * There is no add_padding function (check for NULL in mbedtls_cipher_finish) 953817466cbSJens Wiklander * but a trivial get_padding function 954817466cbSJens Wiklander */ 955817466cbSJens Wiklander static int get_no_padding(unsigned char *input, size_t input_len, 956817466cbSJens Wiklander size_t *data_len) 957817466cbSJens Wiklander { 958*32b31808SJens Wiklander if (NULL == input || NULL == data_len) { 959*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 960*32b31808SJens Wiklander } 961817466cbSJens Wiklander 962817466cbSJens Wiklander *data_len = input_len; 963817466cbSJens Wiklander 964*32b31808SJens Wiklander return 0; 965817466cbSJens Wiklander } 966817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 967817466cbSJens Wiklander 968817466cbSJens Wiklander int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, 969817466cbSJens Wiklander unsigned char *output, size_t *olen) 970817466cbSJens Wiklander { 971*32b31808SJens Wiklander if (ctx->cipher_info == NULL) { 972*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 973*32b31808SJens Wiklander } 974817466cbSJens Wiklander 97511fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 976*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 97711fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 97811fa71b9SJerome Forissier * operations, we currently don't make it 97911fa71b9SJerome Forissier * accessible through the cipher layer. */ 980*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 98111fa71b9SJerome Forissier } 98211fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 98311fa71b9SJerome Forissier 984817466cbSJens Wiklander *olen = 0; 985817466cbSJens Wiklander 986817466cbSJens Wiklander if (MBEDTLS_MODE_CFB == ctx->cipher_info->mode || 9873d3b0591SJens Wiklander MBEDTLS_MODE_OFB == ctx->cipher_info->mode || 988817466cbSJens Wiklander MBEDTLS_MODE_CTR == ctx->cipher_info->mode || 989817466cbSJens Wiklander MBEDTLS_MODE_GCM == ctx->cipher_info->mode || 990*32b31808SJens Wiklander MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode || 9913d3b0591SJens Wiklander MBEDTLS_MODE_XTS == ctx->cipher_info->mode || 992*32b31808SJens Wiklander MBEDTLS_MODE_STREAM == ctx->cipher_info->mode) { 993*32b31808SJens Wiklander return 0; 994817466cbSJens Wiklander } 995817466cbSJens Wiklander 9963d3b0591SJens Wiklander if ((MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type) || 997*32b31808SJens Wiklander (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type)) { 998*32b31808SJens Wiklander return 0; 9993d3b0591SJens Wiklander } 10003d3b0591SJens Wiklander 1001*32b31808SJens Wiklander if (MBEDTLS_MODE_ECB == ctx->cipher_info->mode) { 1002*32b31808SJens Wiklander if (ctx->unprocessed_len != 0) { 1003*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; 1004*32b31808SJens Wiklander } 1005817466cbSJens Wiklander 1006*32b31808SJens Wiklander return 0; 1007817466cbSJens Wiklander } 1008817466cbSJens Wiklander 1009817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_CBC) 1010*32b31808SJens Wiklander if (MBEDTLS_MODE_CBC == ctx->cipher_info->mode) { 1011817466cbSJens Wiklander int ret = 0; 1012817466cbSJens Wiklander 1013*32b31808SJens Wiklander if (MBEDTLS_ENCRYPT == ctx->operation) { 1014817466cbSJens Wiklander /* check for 'no padding' mode */ 1015*32b31808SJens Wiklander if (NULL == ctx->add_padding) { 1016*32b31808SJens Wiklander if (0 != ctx->unprocessed_len) { 1017*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; 1018*32b31808SJens Wiklander } 1019817466cbSJens Wiklander 1020*32b31808SJens Wiklander return 0; 1021817466cbSJens Wiklander } 1022817466cbSJens Wiklander 1023817466cbSJens Wiklander ctx->add_padding(ctx->unprocessed_data, mbedtls_cipher_get_iv_size(ctx), 1024817466cbSJens Wiklander ctx->unprocessed_len); 1025*32b31808SJens Wiklander } else if (mbedtls_cipher_get_block_size(ctx) != ctx->unprocessed_len) { 1026817466cbSJens Wiklander /* 1027817466cbSJens Wiklander * For decrypt operations, expect a full block, 1028817466cbSJens Wiklander * or an empty block if no padding 1029817466cbSJens Wiklander */ 1030*32b31808SJens Wiklander if (NULL == ctx->add_padding && 0 == ctx->unprocessed_len) { 1031*32b31808SJens Wiklander return 0; 1032*32b31808SJens Wiklander } 1033817466cbSJens Wiklander 1034*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; 1035817466cbSJens Wiklander } 1036817466cbSJens Wiklander 1037817466cbSJens Wiklander /* cipher block */ 1038817466cbSJens Wiklander if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx, 1039*32b31808SJens Wiklander ctx->operation, 1040*32b31808SJens Wiklander mbedtls_cipher_get_block_size(ctx), 1041*32b31808SJens Wiklander ctx->iv, 1042*32b31808SJens Wiklander ctx->unprocessed_data, output))) { 1043*32b31808SJens Wiklander return ret; 1044817466cbSJens Wiklander } 1045817466cbSJens Wiklander 1046817466cbSJens Wiklander /* Set output size for decryption */ 1047*32b31808SJens Wiklander if (MBEDTLS_DECRYPT == ctx->operation) { 1048*32b31808SJens Wiklander return ctx->get_padding(output, mbedtls_cipher_get_block_size(ctx), 1049*32b31808SJens Wiklander olen); 1050*32b31808SJens Wiklander } 1051817466cbSJens Wiklander 1052817466cbSJens Wiklander /* Set output size for encryption */ 1053817466cbSJens Wiklander *olen = mbedtls_cipher_get_block_size(ctx); 1054*32b31808SJens Wiklander return 0; 1055817466cbSJens Wiklander } 1056817466cbSJens Wiklander #else 1057817466cbSJens Wiklander ((void) output); 1058817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_CBC */ 1059817466cbSJens Wiklander 1060*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1061817466cbSJens Wiklander } 1062817466cbSJens Wiklander 1063817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 10643d3b0591SJens Wiklander int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, 10653d3b0591SJens Wiklander mbedtls_cipher_padding_t mode) 1066817466cbSJens Wiklander { 1067*32b31808SJens Wiklander if (NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode) { 1068*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1069817466cbSJens Wiklander } 1070817466cbSJens Wiklander 107111fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1072*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 107311fa71b9SJerome Forissier /* While PSA Crypto knows about CBC padding 107411fa71b9SJerome Forissier * schemes, we currently don't make them 107511fa71b9SJerome Forissier * accessible through the cipher layer. */ 1076*32b31808SJens Wiklander if (mode != MBEDTLS_PADDING_NONE) { 1077*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1078*32b31808SJens Wiklander } 107911fa71b9SJerome Forissier 1080*32b31808SJens Wiklander return 0; 108111fa71b9SJerome Forissier } 108211fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 108311fa71b9SJerome Forissier 1084*32b31808SJens Wiklander switch (mode) { 1085817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) 1086817466cbSJens Wiklander case MBEDTLS_PADDING_PKCS7: 1087817466cbSJens Wiklander ctx->add_padding = add_pkcs_padding; 1088817466cbSJens Wiklander ctx->get_padding = get_pkcs_padding; 1089817466cbSJens Wiklander break; 1090817466cbSJens Wiklander #endif 1091817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) 1092817466cbSJens Wiklander case MBEDTLS_PADDING_ONE_AND_ZEROS: 1093817466cbSJens Wiklander ctx->add_padding = add_one_and_zeros_padding; 1094817466cbSJens Wiklander ctx->get_padding = get_one_and_zeros_padding; 1095817466cbSJens Wiklander break; 1096817466cbSJens Wiklander #endif 1097817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) 1098817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS_AND_LEN: 1099817466cbSJens Wiklander ctx->add_padding = add_zeros_and_len_padding; 1100817466cbSJens Wiklander ctx->get_padding = get_zeros_and_len_padding; 1101817466cbSJens Wiklander break; 1102817466cbSJens Wiklander #endif 1103817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) 1104817466cbSJens Wiklander case MBEDTLS_PADDING_ZEROS: 1105817466cbSJens Wiklander ctx->add_padding = add_zeros_padding; 1106817466cbSJens Wiklander ctx->get_padding = get_zeros_padding; 1107817466cbSJens Wiklander break; 1108817466cbSJens Wiklander #endif 1109817466cbSJens Wiklander case MBEDTLS_PADDING_NONE: 1110817466cbSJens Wiklander ctx->add_padding = NULL; 1111817466cbSJens Wiklander ctx->get_padding = get_no_padding; 1112817466cbSJens Wiklander break; 1113817466cbSJens Wiklander 1114817466cbSJens Wiklander default: 1115*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1116817466cbSJens Wiklander } 1117817466cbSJens Wiklander 1118*32b31808SJens Wiklander return 0; 1119817466cbSJens Wiklander } 1120817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 1121817466cbSJens Wiklander 11223d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) 1123817466cbSJens Wiklander int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, 1124817466cbSJens Wiklander unsigned char *tag, size_t tag_len) 1125817466cbSJens Wiklander { 1126*32b31808SJens Wiklander if (ctx->cipher_info == NULL) { 1127*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1128*32b31808SJens Wiklander } 1129817466cbSJens Wiklander 1130*32b31808SJens Wiklander if (MBEDTLS_ENCRYPT != ctx->operation) { 1131*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1132*32b31808SJens Wiklander } 1133817466cbSJens Wiklander 113411fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1135*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 113611fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 113711fa71b9SJerome Forissier * operations, we currently don't make it 113811fa71b9SJerome Forissier * accessible through the cipher layer. */ 1139*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 114011fa71b9SJerome Forissier } 114111fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 114211fa71b9SJerome Forissier 11433d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 1144*32b31808SJens Wiklander if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { 1145*32b31808SJens Wiklander size_t output_length; 1146*32b31808SJens Wiklander /* The code here doesn't yet support alternative implementations 1147*32b31808SJens Wiklander * that can delay up to a block of output. */ 1148*32b31808SJens Wiklander return mbedtls_gcm_finish((mbedtls_gcm_context *) ctx->cipher_ctx, 1149*32b31808SJens Wiklander NULL, 0, &output_length, 1150*32b31808SJens Wiklander tag, tag_len); 11513d3b0591SJens Wiklander } 11523d3b0591SJens Wiklander #endif 1153817466cbSJens Wiklander 1154*32b31808SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 1155*32b31808SJens Wiklander if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { 1156*32b31808SJens Wiklander /* Don't allow truncated MAC for Poly1305 */ 1157*32b31808SJens Wiklander if (tag_len != 16U) { 1158*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1159*32b31808SJens Wiklander } 1160*32b31808SJens Wiklander 1161*32b31808SJens Wiklander return mbedtls_chachapoly_finish( 1162*32b31808SJens Wiklander (mbedtls_chachapoly_context *) ctx->cipher_ctx, tag); 1163*32b31808SJens Wiklander } 1164*32b31808SJens Wiklander #endif 1165*32b31808SJens Wiklander 1166*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1167817466cbSJens Wiklander } 1168817466cbSJens Wiklander 1169817466cbSJens Wiklander int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, 1170817466cbSJens Wiklander const unsigned char *tag, size_t tag_len) 1171817466cbSJens Wiklander { 11723d3b0591SJens Wiklander unsigned char check_tag[16]; 117311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1174817466cbSJens Wiklander 1175*32b31808SJens Wiklander if (ctx->cipher_info == NULL) { 1176*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1177*32b31808SJens Wiklander } 11783d3b0591SJens Wiklander 1179*32b31808SJens Wiklander if (MBEDTLS_DECRYPT != ctx->operation) { 1180*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1181817466cbSJens Wiklander } 1182817466cbSJens Wiklander 118311fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1184*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 118511fa71b9SJerome Forissier /* While PSA Crypto has an API for multipart 118611fa71b9SJerome Forissier * operations, we currently don't make it 118711fa71b9SJerome Forissier * accessible through the cipher layer. */ 1188*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 118911fa71b9SJerome Forissier } 119011fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 119111fa71b9SJerome Forissier 1192*32b31808SJens Wiklander /* Status to return on a non-authenticated algorithm. */ 1193*32b31808SJens Wiklander ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1194039e02dfSJerome Forissier 11953d3b0591SJens Wiklander #if defined(MBEDTLS_GCM_C) 1196*32b31808SJens Wiklander if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { 1197*32b31808SJens Wiklander size_t output_length; 1198*32b31808SJens Wiklander /* The code here doesn't yet support alternative implementations 1199*32b31808SJens Wiklander * that can delay up to a block of output. */ 1200*32b31808SJens Wiklander 1201*32b31808SJens Wiklander if (tag_len > sizeof(check_tag)) { 1202*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1203*32b31808SJens Wiklander } 1204817466cbSJens Wiklander 120511fa71b9SJerome Forissier if (0 != (ret = mbedtls_gcm_finish( 120611fa71b9SJerome Forissier (mbedtls_gcm_context *) ctx->cipher_ctx, 1207*32b31808SJens Wiklander NULL, 0, &output_length, 1208*32b31808SJens Wiklander check_tag, tag_len))) { 1209*32b31808SJens Wiklander return ret; 1210817466cbSJens Wiklander } 1211817466cbSJens Wiklander 1212817466cbSJens Wiklander /* Check the tag in "constant-time" */ 1213*32b31808SJens Wiklander if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) { 1214039e02dfSJerome Forissier ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1215039e02dfSJerome Forissier goto exit; 1216039e02dfSJerome Forissier } 1217817466cbSJens Wiklander } 12183d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C */ 12193d3b0591SJens Wiklander 12203d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 1221*32b31808SJens Wiklander if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { 12223d3b0591SJens Wiklander /* Don't allow truncated MAC for Poly1305 */ 1223*32b31808SJens Wiklander if (tag_len != sizeof(check_tag)) { 1224*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1225*32b31808SJens Wiklander } 12263d3b0591SJens Wiklander 122711fa71b9SJerome Forissier ret = mbedtls_chachapoly_finish( 122811fa71b9SJerome Forissier (mbedtls_chachapoly_context *) ctx->cipher_ctx, check_tag); 1229*32b31808SJens Wiklander if (ret != 0) { 1230*32b31808SJens Wiklander return ret; 12313d3b0591SJens Wiklander } 12323d3b0591SJens Wiklander 12333d3b0591SJens Wiklander /* Check the tag in "constant-time" */ 1234*32b31808SJens Wiklander if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) { 1235039e02dfSJerome Forissier ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1236039e02dfSJerome Forissier goto exit; 1237039e02dfSJerome Forissier } 1238817466cbSJens Wiklander } 12393d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 12403d3b0591SJens Wiklander 1241039e02dfSJerome Forissier exit: 1242039e02dfSJerome Forissier mbedtls_platform_zeroize(check_tag, tag_len); 1243*32b31808SJens Wiklander return ret; 12443d3b0591SJens Wiklander } 12453d3b0591SJens Wiklander #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ 1246817466cbSJens Wiklander 1247817466cbSJens Wiklander /* 1248817466cbSJens Wiklander * Packet-oriented wrapper for non-AEAD modes 1249817466cbSJens Wiklander */ 1250817466cbSJens Wiklander int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, 1251817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1252817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1253817466cbSJens Wiklander unsigned char *output, size_t *olen) 1254817466cbSJens Wiklander { 125511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1256817466cbSJens Wiklander size_t finish_olen; 1257817466cbSJens Wiklander 125811fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1259*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 126011fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 126111fa71b9SJerome Forissier * a key has been set. If not, the key slot will 126211fa71b9SJerome Forissier * still be in its default state of 0, which is 126311fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 126411fa71b9SJerome Forissier * below will gracefully fail. */ 126511fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 126611fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 126711fa71b9SJerome Forissier 126811fa71b9SJerome Forissier psa_status_t status; 126911fa71b9SJerome Forissier psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; 127011fa71b9SJerome Forissier size_t part_len; 127111fa71b9SJerome Forissier 1272*32b31808SJens Wiklander if (ctx->operation == MBEDTLS_DECRYPT) { 127311fa71b9SJerome Forissier status = psa_cipher_decrypt_setup(&cipher_op, 127411fa71b9SJerome Forissier cipher_psa->slot, 127511fa71b9SJerome Forissier cipher_psa->alg); 1276*32b31808SJens Wiklander } else if (ctx->operation == MBEDTLS_ENCRYPT) { 127711fa71b9SJerome Forissier status = psa_cipher_encrypt_setup(&cipher_op, 127811fa71b9SJerome Forissier cipher_psa->slot, 127911fa71b9SJerome Forissier cipher_psa->alg); 1280*32b31808SJens Wiklander } else { 1281*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 128211fa71b9SJerome Forissier } 128311fa71b9SJerome Forissier 128411fa71b9SJerome Forissier /* In the following, we can immediately return on an error, 128511fa71b9SJerome Forissier * because the PSA Crypto API guarantees that cipher operations 128611fa71b9SJerome Forissier * are terminated by unsuccessful calls to psa_cipher_update(), 128711fa71b9SJerome Forissier * and by any call to psa_cipher_finish(). */ 1288*32b31808SJens Wiklander if (status != PSA_SUCCESS) { 1289*32b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 1290*32b31808SJens Wiklander } 129111fa71b9SJerome Forissier 1292*32b31808SJens Wiklander if (ctx->cipher_info->mode != MBEDTLS_MODE_ECB) { 129311fa71b9SJerome Forissier status = psa_cipher_set_iv(&cipher_op, iv, iv_len); 1294*32b31808SJens Wiklander if (status != PSA_SUCCESS) { 1295*32b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 1296*32b31808SJens Wiklander } 1297039e02dfSJerome Forissier } 129811fa71b9SJerome Forissier 129911fa71b9SJerome Forissier status = psa_cipher_update(&cipher_op, 130011fa71b9SJerome Forissier input, ilen, 130111fa71b9SJerome Forissier output, ilen, olen); 1302*32b31808SJens Wiklander if (status != PSA_SUCCESS) { 1303*32b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 1304*32b31808SJens Wiklander } 130511fa71b9SJerome Forissier 130611fa71b9SJerome Forissier status = psa_cipher_finish(&cipher_op, 130711fa71b9SJerome Forissier output + *olen, ilen - *olen, 130811fa71b9SJerome Forissier &part_len); 1309*32b31808SJens Wiklander if (status != PSA_SUCCESS) { 1310*32b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 1311*32b31808SJens Wiklander } 131211fa71b9SJerome Forissier 131311fa71b9SJerome Forissier *olen += part_len; 1314*32b31808SJens Wiklander return 0; 131511fa71b9SJerome Forissier } 131611fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 131711fa71b9SJerome Forissier 1318*32b31808SJens Wiklander if ((ret = mbedtls_cipher_set_iv(ctx, iv, iv_len)) != 0) { 1319*32b31808SJens Wiklander return ret; 1320*32b31808SJens Wiklander } 1321817466cbSJens Wiklander 1322*32b31808SJens Wiklander if ((ret = mbedtls_cipher_reset(ctx)) != 0) { 1323*32b31808SJens Wiklander return ret; 1324*32b31808SJens Wiklander } 1325817466cbSJens Wiklander 132611fa71b9SJerome Forissier if ((ret = mbedtls_cipher_update(ctx, input, ilen, 1327*32b31808SJens Wiklander output, olen)) != 0) { 1328*32b31808SJens Wiklander return ret; 1329*32b31808SJens Wiklander } 1330817466cbSJens Wiklander 133111fa71b9SJerome Forissier if ((ret = mbedtls_cipher_finish(ctx, output + *olen, 1332*32b31808SJens Wiklander &finish_olen)) != 0) { 1333*32b31808SJens Wiklander return ret; 1334*32b31808SJens Wiklander } 1335817466cbSJens Wiklander 1336817466cbSJens Wiklander *olen += finish_olen; 1337817466cbSJens Wiklander 1338*32b31808SJens Wiklander return 0; 1339817466cbSJens Wiklander } 1340817466cbSJens Wiklander 1341817466cbSJens Wiklander #if defined(MBEDTLS_CIPHER_MODE_AEAD) 1342817466cbSJens Wiklander /* 1343*32b31808SJens Wiklander * Packet-oriented encryption for AEAD modes: internal function used by 1344*32b31808SJens Wiklander * mbedtls_cipher_auth_encrypt_ext(). 1345817466cbSJens Wiklander */ 13467901324dSJerome Forissier static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, 1347817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1348817466cbSJens Wiklander const unsigned char *ad, size_t ad_len, 1349817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1350817466cbSJens Wiklander unsigned char *output, size_t *olen, 1351817466cbSJens Wiklander unsigned char *tag, size_t tag_len) 1352817466cbSJens Wiklander { 135311fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1354*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 135511fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 135611fa71b9SJerome Forissier * a key has been set. If not, the key slot will 135711fa71b9SJerome Forissier * still be in its default state of 0, which is 135811fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 135911fa71b9SJerome Forissier * below will gracefully fail. */ 136011fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 136111fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 136211fa71b9SJerome Forissier 136311fa71b9SJerome Forissier psa_status_t status; 136411fa71b9SJerome Forissier 136511fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag 136611fa71b9SJerome Forissier * at the end of the encrypted message. */ 1367*32b31808SJens Wiklander if (output == NULL || tag != output + ilen) { 1368*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1369*32b31808SJens Wiklander } 137011fa71b9SJerome Forissier 137111fa71b9SJerome Forissier status = psa_aead_encrypt(cipher_psa->slot, 137211fa71b9SJerome Forissier cipher_psa->alg, 137311fa71b9SJerome Forissier iv, iv_len, 137411fa71b9SJerome Forissier ad, ad_len, 137511fa71b9SJerome Forissier input, ilen, 137611fa71b9SJerome Forissier output, ilen + tag_len, olen); 1377*32b31808SJens Wiklander if (status != PSA_SUCCESS) { 1378*32b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 1379*32b31808SJens Wiklander } 138011fa71b9SJerome Forissier 138111fa71b9SJerome Forissier *olen -= tag_len; 1382*32b31808SJens Wiklander return 0; 138311fa71b9SJerome Forissier } 138411fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 138511fa71b9SJerome Forissier 1386817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 1387*32b31808SJens Wiklander if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { 1388817466cbSJens Wiklander *olen = ilen; 1389*32b31808SJens Wiklander return mbedtls_gcm_crypt_and_tag(ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, 139011fa71b9SJerome Forissier ilen, iv, iv_len, ad, ad_len, 1391*32b31808SJens Wiklander input, output, tag_len, tag); 1392817466cbSJens Wiklander } 1393817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1394817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 1395*32b31808SJens Wiklander if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) { 1396817466cbSJens Wiklander *olen = ilen; 1397*32b31808SJens Wiklander return mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen, 1398817466cbSJens Wiklander iv, iv_len, ad, ad_len, input, output, 1399*32b31808SJens Wiklander tag, tag_len); 1400817466cbSJens Wiklander } 1401817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */ 14023d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 1403*32b31808SJens Wiklander if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { 14043d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */ 14053d3b0591SJens Wiklander if ((iv_len != ctx->cipher_info->iv_size) || 1406*32b31808SJens Wiklander (tag_len != 16U)) { 1407*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 14083d3b0591SJens Wiklander } 14093d3b0591SJens Wiklander 14103d3b0591SJens Wiklander *olen = ilen; 1411*32b31808SJens Wiklander return mbedtls_chachapoly_encrypt_and_tag(ctx->cipher_ctx, 1412*32b31808SJens Wiklander ilen, iv, ad, ad_len, input, output, tag); 14133d3b0591SJens Wiklander } 14143d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 1415817466cbSJens Wiklander 1416*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1417817466cbSJens Wiklander } 1418817466cbSJens Wiklander 1419817466cbSJens Wiklander /* 1420*32b31808SJens Wiklander * Packet-oriented encryption for AEAD modes: internal function used by 1421*32b31808SJens Wiklander * mbedtls_cipher_auth_encrypt_ext(). 1422817466cbSJens Wiklander */ 14237901324dSJerome Forissier static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, 1424817466cbSJens Wiklander const unsigned char *iv, size_t iv_len, 1425817466cbSJens Wiklander const unsigned char *ad, size_t ad_len, 1426817466cbSJens Wiklander const unsigned char *input, size_t ilen, 1427817466cbSJens Wiklander unsigned char *output, size_t *olen, 1428817466cbSJens Wiklander const unsigned char *tag, size_t tag_len) 1429817466cbSJens Wiklander { 143011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 1431*32b31808SJens Wiklander if (ctx->psa_enabled == 1) { 143211fa71b9SJerome Forissier /* As in the non-PSA case, we don't check that 143311fa71b9SJerome Forissier * a key has been set. If not, the key slot will 143411fa71b9SJerome Forissier * still be in its default state of 0, which is 143511fa71b9SJerome Forissier * guaranteed to be invalid, hence the PSA-call 143611fa71b9SJerome Forissier * below will gracefully fail. */ 143711fa71b9SJerome Forissier mbedtls_cipher_context_psa * const cipher_psa = 143811fa71b9SJerome Forissier (mbedtls_cipher_context_psa *) ctx->cipher_ctx; 143911fa71b9SJerome Forissier 144011fa71b9SJerome Forissier psa_status_t status; 144111fa71b9SJerome Forissier 144211fa71b9SJerome Forissier /* PSA Crypto API always writes the authentication tag 144311fa71b9SJerome Forissier * at the end of the encrypted message. */ 1444*32b31808SJens Wiklander if (input == NULL || tag != input + ilen) { 1445*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1446*32b31808SJens Wiklander } 144711fa71b9SJerome Forissier 144811fa71b9SJerome Forissier status = psa_aead_decrypt(cipher_psa->slot, 144911fa71b9SJerome Forissier cipher_psa->alg, 145011fa71b9SJerome Forissier iv, iv_len, 145111fa71b9SJerome Forissier ad, ad_len, 145211fa71b9SJerome Forissier input, ilen + tag_len, 145311fa71b9SJerome Forissier output, ilen, olen); 1454*32b31808SJens Wiklander if (status == PSA_ERROR_INVALID_SIGNATURE) { 1455*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1456*32b31808SJens Wiklander } else if (status != PSA_SUCCESS) { 1457*32b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 1458*32b31808SJens Wiklander } 145911fa71b9SJerome Forissier 1460*32b31808SJens Wiklander return 0; 146111fa71b9SJerome Forissier } 146211fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 146311fa71b9SJerome Forissier 1464817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 1465*32b31808SJens Wiklander if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { 146611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1467817466cbSJens Wiklander 1468817466cbSJens Wiklander *olen = ilen; 1469817466cbSJens Wiklander ret = mbedtls_gcm_auth_decrypt(ctx->cipher_ctx, ilen, 1470817466cbSJens Wiklander iv, iv_len, ad, ad_len, 1471817466cbSJens Wiklander tag, tag_len, input, output); 1472817466cbSJens Wiklander 1473*32b31808SJens Wiklander if (ret == MBEDTLS_ERR_GCM_AUTH_FAILED) { 1474817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1475*32b31808SJens Wiklander } 1476817466cbSJens Wiklander 1477*32b31808SJens Wiklander return ret; 1478817466cbSJens Wiklander } 1479817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 1480817466cbSJens Wiklander #if defined(MBEDTLS_CCM_C) 1481*32b31808SJens Wiklander if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) { 148211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1483817466cbSJens Wiklander 1484817466cbSJens Wiklander *olen = ilen; 1485817466cbSJens Wiklander ret = mbedtls_ccm_auth_decrypt(ctx->cipher_ctx, ilen, 1486817466cbSJens Wiklander iv, iv_len, ad, ad_len, 1487817466cbSJens Wiklander input, output, tag, tag_len); 1488817466cbSJens Wiklander 1489*32b31808SJens Wiklander if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED) { 1490817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1491*32b31808SJens Wiklander } 1492817466cbSJens Wiklander 1493*32b31808SJens Wiklander return ret; 1494817466cbSJens Wiklander } 1495817466cbSJens Wiklander #endif /* MBEDTLS_CCM_C */ 14963d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C) 1497*32b31808SJens Wiklander if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { 149811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 14993d3b0591SJens Wiklander 15003d3b0591SJens Wiklander /* ChachaPoly has fixed length nonce and MAC (tag) */ 15013d3b0591SJens Wiklander if ((iv_len != ctx->cipher_info->iv_size) || 1502*32b31808SJens Wiklander (tag_len != 16U)) { 1503*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 15043d3b0591SJens Wiklander } 15053d3b0591SJens Wiklander 15063d3b0591SJens Wiklander *olen = ilen; 15073d3b0591SJens Wiklander ret = mbedtls_chachapoly_auth_decrypt(ctx->cipher_ctx, ilen, 15083d3b0591SJens Wiklander iv, ad, ad_len, tag, input, output); 15093d3b0591SJens Wiklander 1510*32b31808SJens Wiklander if (ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) { 15113d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 1512*32b31808SJens Wiklander } 15133d3b0591SJens Wiklander 1514*32b31808SJens Wiklander return ret; 15153d3b0591SJens Wiklander } 15163d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */ 15177901324dSJerome Forissier 1518*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 15197901324dSJerome Forissier } 15207901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 15217901324dSJerome Forissier 15227901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) 15237901324dSJerome Forissier /* 15247901324dSJerome Forissier * Packet-oriented encryption for AEAD/NIST_KW: public function. 15257901324dSJerome Forissier */ 15267901324dSJerome Forissier int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx, 15277901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 15287901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 15297901324dSJerome Forissier const unsigned char *input, size_t ilen, 15307901324dSJerome Forissier unsigned char *output, size_t output_len, 15317901324dSJerome Forissier size_t *olen, size_t tag_len) 15327901324dSJerome Forissier { 153311fa71b9SJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 15347901324dSJerome Forissier if ( 15357901324dSJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 15367901324dSJerome Forissier ctx->psa_enabled == 0 && 15377901324dSJerome Forissier #endif 15387901324dSJerome Forissier (MBEDTLS_MODE_KW == ctx->cipher_info->mode || 1539*32b31808SJens Wiklander MBEDTLS_MODE_KWP == ctx->cipher_info->mode)) { 154011fa71b9SJerome Forissier mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ctx->cipher_info->mode) ? 154111fa71b9SJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; 154211fa71b9SJerome Forissier 15437901324dSJerome Forissier /* There is no iv, tag or ad associated with KW and KWP, 15447901324dSJerome Forissier * so these length should be 0 as documented. */ 1545*32b31808SJens Wiklander if (iv_len != 0 || tag_len != 0 || ad_len != 0) { 1546*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1547*32b31808SJens Wiklander } 154811fa71b9SJerome Forissier 15497901324dSJerome Forissier (void) iv; 15507901324dSJerome Forissier (void) ad; 15517901324dSJerome Forissier 1552*32b31808SJens Wiklander return mbedtls_nist_kw_wrap(ctx->cipher_ctx, mode, input, ilen, 1553*32b31808SJens Wiklander output, olen, output_len); 155411fa71b9SJerome Forissier } 155511fa71b9SJerome Forissier #endif /* MBEDTLS_NIST_KW_C */ 1556817466cbSJens Wiklander 15577901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) 15587901324dSJerome Forissier /* AEAD case: check length before passing on to shared function */ 1559*32b31808SJens Wiklander if (output_len < ilen + tag_len) { 1560*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1561*32b31808SJens Wiklander } 15627901324dSJerome Forissier 15637901324dSJerome Forissier int ret = mbedtls_cipher_aead_encrypt(ctx, iv, iv_len, ad, ad_len, 15647901324dSJerome Forissier input, ilen, output, olen, 15657901324dSJerome Forissier output + ilen, tag_len); 15667901324dSJerome Forissier *olen += tag_len; 1567*32b31808SJens Wiklander return ret; 15687901324dSJerome Forissier #else 1569*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 1570817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 15717901324dSJerome Forissier } 15727901324dSJerome Forissier 15737901324dSJerome Forissier /* 15747901324dSJerome Forissier * Packet-oriented decryption for AEAD/NIST_KW: public function. 15757901324dSJerome Forissier */ 15767901324dSJerome Forissier int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx, 15777901324dSJerome Forissier const unsigned char *iv, size_t iv_len, 15787901324dSJerome Forissier const unsigned char *ad, size_t ad_len, 15797901324dSJerome Forissier const unsigned char *input, size_t ilen, 15807901324dSJerome Forissier unsigned char *output, size_t output_len, 15817901324dSJerome Forissier size_t *olen, size_t tag_len) 15827901324dSJerome Forissier { 15837901324dSJerome Forissier #if defined(MBEDTLS_NIST_KW_C) 15847901324dSJerome Forissier if ( 15857901324dSJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 15867901324dSJerome Forissier ctx->psa_enabled == 0 && 15877901324dSJerome Forissier #endif 15887901324dSJerome Forissier (MBEDTLS_MODE_KW == ctx->cipher_info->mode || 1589*32b31808SJens Wiklander MBEDTLS_MODE_KWP == ctx->cipher_info->mode)) { 15907901324dSJerome Forissier mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ctx->cipher_info->mode) ? 15917901324dSJerome Forissier MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; 15927901324dSJerome 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. */ 1595*32b31808SJens Wiklander if (iv_len != 0 || tag_len != 0 || ad_len != 0) { 1596*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1597*32b31808SJens Wiklander } 15987901324dSJerome Forissier 15997901324dSJerome Forissier (void) iv; 16007901324dSJerome Forissier (void) ad; 16017901324dSJerome Forissier 1602*32b31808SJens Wiklander return mbedtls_nist_kw_unwrap(ctx->cipher_ctx, mode, input, ilen, 1603*32b31808SJens Wiklander output, olen, output_len); 16047901324dSJerome Forissier } 16057901324dSJerome Forissier #endif /* MBEDTLS_NIST_KW_C */ 16067901324dSJerome Forissier 16077901324dSJerome Forissier #if defined(MBEDTLS_CIPHER_MODE_AEAD) 16087901324dSJerome Forissier /* AEAD case: check length before passing on to shared function */ 1609*32b31808SJens Wiklander if (ilen < tag_len || output_len < ilen - tag_len) { 1610*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 1611*32b31808SJens Wiklander } 16127901324dSJerome Forissier 1613*32b31808SJens Wiklander return mbedtls_cipher_aead_decrypt(ctx, iv, iv_len, ad, ad_len, 16147901324dSJerome Forissier input, ilen - tag_len, output, olen, 1615*32b31808SJens Wiklander input + ilen - tag_len, tag_len); 16167901324dSJerome Forissier #else 1617*32b31808SJens Wiklander return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 16187901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD */ 16197901324dSJerome Forissier } 16207901324dSJerome Forissier #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ 1621817466cbSJens Wiklander 1622817466cbSJens Wiklander #endif /* MBEDTLS_CIPHER_C */ 1623