|  | /** | 
|  | * \file block_cipher.c | 
|  | * | 
|  | * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks, | 
|  | * for use by the GCM and CCM modules. | 
|  | */ | 
|  | /* | 
|  | *  Copyright The Mbed TLS Contributors | 
|  | *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later | 
|  | */ | 
|  |  | 
|  | #include "common.h" | 
|  |  | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) | 
|  | #include "psa/crypto.h" | 
|  | #include "psa_crypto_core.h" | 
|  | #include "psa_util_internal.h" | 
|  | #endif | 
|  |  | 
|  | #include "block_cipher_internal.h" | 
|  |  | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_C) | 
|  |  | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) | 
|  | static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id) | 
|  | { | 
|  | switch (cipher_id) { | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_AES: | 
|  | return PSA_KEY_TYPE_AES; | 
|  | #endif | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_ARIA: | 
|  | return PSA_KEY_TYPE_ARIA; | 
|  | #endif | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: | 
|  | return PSA_KEY_TYPE_CAMELLIA; | 
|  | #endif | 
|  | default: | 
|  | return PSA_KEY_TYPE_NONE; | 
|  | } | 
|  | } | 
|  |  | 
|  | static int mbedtls_cipher_error_from_psa(psa_status_t status) | 
|  | { | 
|  | return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors, | 
|  | psa_generic_status_to_mbedtls); | 
|  | } | 
|  | #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ | 
|  |  | 
|  | void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx) | 
|  | { | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) | 
|  | if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { | 
|  | psa_destroy_key(ctx->psa_key_id); | 
|  | return; | 
|  | } | 
|  | #endif | 
|  | switch (ctx->id) { | 
|  | #if defined(MBEDTLS_AES_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_AES: | 
|  | mbedtls_aes_free(&ctx->ctx.aes); | 
|  | break; | 
|  | #endif | 
|  | #if defined(MBEDTLS_ARIA_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_ARIA: | 
|  | mbedtls_aria_free(&ctx->ctx.aria); | 
|  | break; | 
|  | #endif | 
|  | #if defined(MBEDTLS_CAMELLIA_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: | 
|  | mbedtls_camellia_free(&ctx->ctx.camellia); | 
|  | break; | 
|  | #endif | 
|  | default: | 
|  | break; | 
|  | } | 
|  | ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; | 
|  | } | 
|  |  | 
|  | int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx, | 
|  | mbedtls_cipher_id_t cipher_id) | 
|  | { | 
|  | ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES : | 
|  | (cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA : | 
|  | (cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA : | 
|  | MBEDTLS_BLOCK_CIPHER_ID_NONE; | 
|  |  | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) | 
|  | psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id); | 
|  | if (psa_key_type != PSA_KEY_TYPE_NONE && | 
|  | psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) { | 
|  | ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA; | 
|  | return 0; | 
|  | } | 
|  | ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY; | 
|  | #endif | 
|  |  | 
|  | switch (ctx->id) { | 
|  | #if defined(MBEDTLS_AES_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_AES: | 
|  | mbedtls_aes_init(&ctx->ctx.aes); | 
|  | return 0; | 
|  | #endif | 
|  | #if defined(MBEDTLS_ARIA_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_ARIA: | 
|  | mbedtls_aria_init(&ctx->ctx.aria); | 
|  | return 0; | 
|  | #endif | 
|  | #if defined(MBEDTLS_CAMELLIA_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: | 
|  | mbedtls_camellia_init(&ctx->ctx.camellia); | 
|  | return 0; | 
|  | #endif | 
|  | default: | 
|  | ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; | 
|  | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; | 
|  | } | 
|  | } | 
|  |  | 
|  | int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx, | 
|  | const unsigned char *key, | 
|  | unsigned key_bitlen) | 
|  | { | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) | 
|  | if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { | 
|  | psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; | 
|  | psa_status_t status; | 
|  |  | 
|  | psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id)); | 
|  | psa_set_key_bits(&key_attr, key_bitlen); | 
|  | psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); | 
|  | psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); | 
|  |  | 
|  | status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id); | 
|  | if (status != PSA_SUCCESS) { | 
|  | return mbedtls_cipher_error_from_psa(status); | 
|  | } | 
|  | psa_reset_key_attributes(&key_attr); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ | 
|  |  | 
|  | switch (ctx->id) { | 
|  | #if defined(MBEDTLS_AES_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_AES: | 
|  | return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen); | 
|  | #endif | 
|  | #if defined(MBEDTLS_ARIA_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_ARIA: | 
|  | return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen); | 
|  | #endif | 
|  | #if defined(MBEDTLS_CAMELLIA_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: | 
|  | return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen); | 
|  | #endif | 
|  | default: | 
|  | return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; | 
|  | } | 
|  | } | 
|  |  | 
|  | int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx, | 
|  | const unsigned char input[16], | 
|  | unsigned char output[16]) | 
|  | { | 
|  | #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) | 
|  | if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { | 
|  | psa_status_t status; | 
|  | size_t olen; | 
|  |  | 
|  | status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING, | 
|  | input, 16, output, 16, &olen); | 
|  | if (status != PSA_SUCCESS) { | 
|  | return mbedtls_cipher_error_from_psa(status); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  | #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ | 
|  |  | 
|  | switch (ctx->id) { | 
|  | #if defined(MBEDTLS_AES_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_AES: | 
|  | return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT, | 
|  | input, output); | 
|  | #endif | 
|  | #if defined(MBEDTLS_ARIA_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_ARIA: | 
|  | return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output); | 
|  | #endif | 
|  | #if defined(MBEDTLS_CAMELLIA_C) | 
|  | case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: | 
|  | return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia, | 
|  | MBEDTLS_CAMELLIA_ENCRYPT, | 
|  | input, output); | 
|  | #endif | 
|  | default: | 
|  | return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; | 
|  | } | 
|  | } | 
|  |  | 
|  | #endif /* MBEDTLS_BLOCK_CIPHER_C */ |