From f9f2badbe330cb3e61838fc736065518c8b0548e Mon Sep 17 00:00:00 2001 From: Zhiyuan Tang Date: Tue, 18 Aug 2026 16:43:56 +0800 Subject: [PATCH 1/2] drivers: crypto: bee: add PSA hardware accelerator driver Add a PSA crypto driver for the Realtek Bee hardware crypto engine. The driver is built when CONFIG_CRYPTO_BEE_PSA_ACCELERATOR is set and provides PSA-compatible implementations for: - SHA-256 (compute, streaming) - AES-ECB/CBC/CFB/OFB/CTR (one-shot and multipart) - AES-CCM AEAD (one-shot and multipart) - P-256 ECDSA sign/verify (RTL87X2G only) - P-256 ECDH key agreement (RTL87X2G only) The driver is structured as a portable core (crypto_bee_psa.c) plus a thin platform adapter (crypto_bee_psa_adapter.c) that calls the hardware engine APIs from the HAL. Expose the AES block-cipher and PKE/ECC ROM function declarations in the rtl8752h and rtl87x2g HAL headers, and add the corresponding ROM entry-point addresses to the RTL87X2G linker script. Co-Authored-By: Claude Signed-off-by: Zhiyuan Tang --- bee/drivers/crypto/CMakeLists.txt | 2 + bee/drivers/crypto/inc/rtl8752h/hw_aes.h | 68 + .../crypto/inc/rtl87x2g/crypto_engine_nsc.h | 90 +- bee/drivers/crypto/psa/CMakeLists.txt | 11 + .../psa/adapter/inc/crypto_bee_psa_adapter.h | 83 + .../psa/adapter/src/crypto_bee_psa_adapter.c | 516 +++++ bee/drivers/crypto/psa/inc/crypto_bee_psa.h | 143 ++ .../crypto/psa/inc/crypto_bee_psa_types.h | 69 + bee/drivers/crypto/psa/src/crypto_bee_psa.c | 1759 +++++++++++++++++ bee/ld/rtl8752h/ROM.ld | 4 + bee/ld/rtl87x2g/ROM_S.ld | 10 + 11 files changed, 2754 insertions(+), 1 deletion(-) create mode 100644 bee/drivers/crypto/psa/CMakeLists.txt create mode 100644 bee/drivers/crypto/psa/adapter/inc/crypto_bee_psa_adapter.h create mode 100644 bee/drivers/crypto/psa/adapter/src/crypto_bee_psa_adapter.c create mode 100644 bee/drivers/crypto/psa/inc/crypto_bee_psa.h create mode 100644 bee/drivers/crypto/psa/inc/crypto_bee_psa_types.h create mode 100644 bee/drivers/crypto/psa/src/crypto_bee_psa.c diff --git a/bee/drivers/crypto/CMakeLists.txt b/bee/drivers/crypto/CMakeLists.txt index a6ec4b73..7864ae5d 100644 --- a/bee/drivers/crypto/CMakeLists.txt +++ b/bee/drivers/crypto/CMakeLists.txt @@ -3,3 +3,5 @@ zephyr_include_directories_ifdef(CONFIG_SOC_SERIES_RTL87X2G inc/rtl87x2g) zephyr_include_directories_ifdef(CONFIG_SOC_SERIES_RTL8752H inc/rtl8752h) + +add_subdirectory_ifdef(CONFIG_CRYPTO_BEE_PSA_ACCELERATOR psa) diff --git a/bee/drivers/crypto/inc/rtl8752h/hw_aes.h b/bee/drivers/crypto/inc/rtl8752h/hw_aes.h index e11c25c8..cca367d5 100644 --- a/bee/drivers/crypto/inc/rtl8752h/hw_aes.h +++ b/bee/drivers/crypto/inc/rtl8752h/hw_aes.h @@ -77,6 +77,74 @@ typedef enum */ extern bool hw_aes_decrypt_16byte(uint8_t *input, uint8_t *output); +/** + * @brief 128 bit AES encryption on specified plain data and keys + * + * @param[in] p_in specified plain data to be encrypted + * @param[out] p_out output buffer to store encrypted data + * @param[in] data_word_len input buffer length in 32-bit words + * @param[in] p_key key buffer + * @param[in] p_iv initialization vector + * @param[in] mode AES mode specified by @ref T_HW_AES_MODE + * + * @return encryption results + * @retval true successful + * @retval false fail + */ +extern bool hw_aes_encrypt128(uint32_t *p_in, uint32_t *p_out, uint16_t data_word_len, + uint32_t *p_key, uint32_t *p_iv, T_HW_AES_MODE mode); + +/** + * @brief 128 bit AES decryption on specified data and keys + * + * @param[in] p_in specified encrypted data to be decrypted + * @param[out] p_out output buffer to store plain data + * @param[in] data_word_len input buffer length in 32-bit words + * @param[in] p_key key buffer + * @param[in] p_iv initialization vector + * @param[in] mode AES mode specified by @ref T_HW_AES_MODE + * + * @return decryption results + * @retval true successful + * @retval false fail + */ +extern bool hw_aes_decrypt128(uint32_t *p_in, uint32_t *p_out, uint16_t data_word_len, + uint32_t *p_key, uint32_t *p_iv, T_HW_AES_MODE mode); + +/** + * @brief 256 bit AES encryption on specified plain data and keys + * + * @param[in] p_in specified plain data to be encrypted + * @param[out] p_out output buffer to store encrypted data + * @param[in] data_word_len input buffer length in 32-bit words + * @param[in] p_key key buffer + * @param[in] p_iv initialization vector + * @param[in] mode AES mode specified by @ref T_HW_AES_MODE + * + * @return encryption results + * @retval true successful + * @retval false fail + */ +extern bool hw_aes_encrypt256(uint32_t *p_in, uint32_t *p_out, uint16_t data_word_len, + uint32_t *p_key, uint32_t *p_iv, T_HW_AES_MODE mode); + +/** + * @brief 256 bit AES decryption on specified data and keys + * + * @param[in] p_in specified encrypted data to be decrypted + * @param[out] p_out output buffer to store plain data + * @param[in] data_word_len input buffer length in 32-bit words + * @param[in] p_key key buffer + * @param[in] p_iv initialization vector + * @param[in] mode AES mode specified by @ref T_HW_AES_MODE + * + * @return decryption results + * @retval true successful + * @retval false fail + */ +extern bool hw_aes_decrypt256(uint32_t *p_in, uint32_t *p_out, uint16_t data_word_len, + uint32_t *p_key, uint32_t *p_iv, T_HW_AES_MODE mode); + /** * @brief 128 bit AES encryption via DMA on specified plain data and keys * diff --git a/bee/drivers/crypto/inc/rtl87x2g/crypto_engine_nsc.h b/bee/drivers/crypto/inc/rtl87x2g/crypto_engine_nsc.h index 1c60e07c..c52cc083 100644 --- a/bee/drivers/crypto/inc/rtl87x2g/crypto_engine_nsc.h +++ b/bee/drivers/crypto/inc/rtl87x2g/crypto_engine_nsc.h @@ -83,6 +83,17 @@ typedef struct uint8_t buffer[64]; /*!< The data block being processed. */ int is224; /*!< unused, just align mbedtls structure */ } HW_SHA256_CTX; + +/** @brief AES mode definition for HW AES. */ +typedef enum +{ + AES_MODE_NONE, + AES_MODE_CBC, + AES_MODE_ECB, + AES_MODE_CFB, + AES_MODE_OFB, + AES_MODE_CTR +} T_HW_AES_MODE; /** End of CRYPTO_ENGINE_Exported_Types * @} */ @@ -142,6 +153,83 @@ bool hw_sha256_cpu_update(HW_SHA256_CTX *ctx, uint8_t *input, uint32_t byte_len) */ bool hw_sha256_finish(HW_SHA256_CTX *ctx, uint32_t *result); +/** + * @brief 128 bit AES encryption on specified plain data and keys + * + * @param[in] p_in specified plain data to be encrypted + * @param[out] p_out output buffer to store encrypted data + * @param[in] data_word_len input buffer length in 32-bit words + * @param[in] p_key key buffer + * @param[in] p_iv initialization vector + * @param[in] mode AES mode specified by @ref T_HW_AES_MODE + * + * @return encryption results + * @retval true successful + * @retval false fail + */ +bool hw_aes_encrypt128(uint32_t *p_in, uint32_t *p_out, uint16_t data_word_len, + uint32_t *p_key, uint32_t *p_iv, T_HW_AES_MODE mode); + +/** + * @brief 128 bit AES decryption on specified data and keys + * + * @param[in] p_in specified encrypted data to be decrypted + * @param[out] p_out output buffer to store plain data + * @param[in] data_word_len input buffer length in 32-bit words + * @param[in] p_key key buffer + * @param[in] p_iv initialization vector + * @param[in] mode AES mode specified by @ref T_HW_AES_MODE + * + * @return decryption results + * @retval true successful + * @retval false fail + */ +bool hw_aes_decrypt128(uint32_t *p_in, uint32_t *p_out, uint16_t data_word_len, + uint32_t *p_key, uint32_t *p_iv, T_HW_AES_MODE mode); + +/** + * @brief 256 bit AES encryption on specified plain data and keys + * + * @param[in] p_in specified plain data to be encrypted + * @param[out] p_out output buffer to store encrypted data + * @param[in] data_word_len input buffer length in 32-bit words + * @param[in] p_key key buffer + * @param[in] p_iv initialization vector + * @param[in] mode AES mode specified by @ref T_HW_AES_MODE + * + * @return encryption results + * @retval true successful + * @retval false fail + */ +bool hw_aes_encrypt256(uint32_t *p_in, uint32_t *p_out, uint16_t data_word_len, + uint32_t *p_key, uint32_t *p_iv, T_HW_AES_MODE mode); + +/** + * @brief 256 bit AES decryption on specified data and keys + * + * @param[in] p_in specified encrypted data to be decrypted + * @param[out] p_out output buffer to store plain data + * @param[in] data_word_len input buffer length in 32-bit words + * @param[in] p_key key buffer + * @param[in] p_iv initialization vector + * @param[in] mode AES mode specified by @ref T_HW_AES_MODE + * + * @return decryption results + * @retval true successful + * @retval false fail + */ +bool hw_aes_decrypt256(uint32_t *p_in, uint32_t *p_out, uint16_t data_word_len, + uint32_t *p_key, uint32_t *p_iv, T_HW_AES_MODE mode); + +void hw_pke_clock(bool enable); +void hw_pke_init(bool byte_swap_en, bool word_swap_en, uint32_t word_swap_base); +void hw_ecc_init(uint32_t key_bits, PKE_MODE mode, bool go_to_end_loop, + bool RR_mod_n_ready); +void hw_ecc_set_sub_operand(uint32_t operand_addr, uint32_t *operands, + uint32_t byte_len); +bool hw_ecc_set_all_operands(ECC_GROUP *grp, uint32_t *e, uint32_t e_byte_size); +ERR_CODE hw_ecc_compute(void *result, uint32_t output_addr, uint16_t func_id); + /** End of CRYPTO_ENGINE_Exported_Functions * @} */ @@ -150,4 +238,4 @@ bool hw_sha256_finish(HW_SHA256_CTX *ctx, uint32_t *result); * @} */ -#endif \ No newline at end of file +#endif diff --git a/bee/drivers/crypto/psa/CMakeLists.txt b/bee/drivers/crypto/psa/CMakeLists.txt new file mode 100644 index 00000000..13ebf9f2 --- /dev/null +++ b/bee/drivers/crypto/psa/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2026, Realtek Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(inc adapter/inc) +zephyr_library_sources(src/crypto_bee_psa.c adapter/src/crypto_bee_psa_adapter.c) + +if(CONFIG_SOC_SERIES_RTL87X2G) + zephyr_compile_definitions(BEE_CRYPTO_RTL87X2G) +elseif(CONFIG_SOC_SERIES_RTL8752H) + zephyr_compile_definitions(BEE_CRYPTO_RTL8752H) +endif() diff --git a/bee/drivers/crypto/psa/adapter/inc/crypto_bee_psa_adapter.h b/bee/drivers/crypto/psa/adapter/inc/crypto_bee_psa_adapter.h new file mode 100644 index 00000000..55602f7a --- /dev/null +++ b/bee/drivers/crypto/psa/adapter/inc/crypto_bee_psa_adapter.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2026, Realtek Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef REALTEK_BEE_PSA_ADAPTER_H_ +#define REALTEK_BEE_PSA_ADAPTER_H_ + +#include +#include +#include + +#if defined(BEE_CRYPTO_RTL87X2G) +#include +#elif defined(BEE_CRYPTO_RTL8752H) +#include +#include +#else +#error "Unsupported Realtek Bee SoC" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define BEE_AES_BLOCK_SIZE 16U +#define BEE_ECC_P256_WORDS 8U + +struct bee_ecc_point { + uint32_t x[BEE_ECC_P256_WORDS]; + uint32_t y[BEE_ECC_P256_WORDS]; + uint32_t z[BEE_ECC_P256_WORDS]; +}; + +enum bee_crypto_status { + BEE_CRYPTO_SUCCESS = 0, + BEE_CRYPTO_ERROR_INVALID_ARGUMENT = -1, + BEE_CRYPTO_ERROR_HARDWARE = -2, + BEE_CRYPTO_ERROR_SYNC = -3, + BEE_CRYPTO_ERROR_NOT_SUPPORTED = -4, +}; + +int bee_crypto_init(void); +int bee_crypto_lock(void); +void bee_crypto_unlock(void); + +int bee_aes_hw_crypt_block(const uint8_t *key, size_t key_len, + T_HW_AES_MODE mode, const uint8_t *in, uint8_t *out, + const uint8_t *iv, bool decrypt); + +int bee_sha256_hw_compute(const uint8_t *input, size_t input_length, + uint8_t *hash); +int bee_sha256_hw_start(HW_SHA256_CTX *ctx); +int bee_sha256_hw_update(HW_SHA256_CTX *ctx, const uint8_t *input, + size_t input_length); +int bee_sha256_hw_finish(HW_SHA256_CTX *ctx, uint8_t *hash); + +int bee_ecc_p256_enable(void); +void bee_ecc_p256_disable(void); +int bee_ecc_p256_mod_prepare(const uint32_t modulus[BEE_ECC_P256_WORDS]); +int bee_ecc_p256_mod_reduce(uint32_t value[BEE_ECC_P256_WORDS]); +int bee_ecc_p256_mod_mul(const uint32_t left[BEE_ECC_P256_WORDS], + const uint32_t right[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]); +int bee_ecc_p256_mod_add(const uint32_t left[BEE_ECC_P256_WORDS], + const uint32_t right[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]); +int bee_ecc_p256_mod_inv(const uint32_t value[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]); +int bee_ecc_p256_mul(const uint32_t scalar[BEE_ECC_P256_WORDS], + const struct bee_ecc_point *point, + struct bee_ecc_point *result); +int bee_ecc_p256_validate_public(const struct bee_ecc_point *point); +int bee_ecc_p256_add(const struct bee_ecc_point *left, + const struct bee_ecc_point *right, + struct bee_ecc_point *result); + +#ifdef __cplusplus +} +#endif + +#endif /* REALTEK_BEE_PSA_ADAPTER_H_ */ diff --git a/bee/drivers/crypto/psa/adapter/src/crypto_bee_psa_adapter.c b/bee/drivers/crypto/psa/adapter/src/crypto_bee_psa_adapter.c new file mode 100644 index 00000000..8fff35b9 --- /dev/null +++ b/bee/drivers/crypto/psa/adapter/src/crypto_bee_psa_adapter.c @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2026, Realtek Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "crypto_bee_psa_adapter.h" +#include +#include + +#define BEE_CRYPTO_WAIT_FOREVER UINT32_MAX + +static void *bee_crypto_mutex; + +int bee_crypto_init(void) { + if (bee_crypto_mutex != NULL) { + return BEE_CRYPTO_SUCCESS; + } + + return os_mutex_create(&bee_crypto_mutex) ? BEE_CRYPTO_SUCCESS + : BEE_CRYPTO_ERROR_SYNC; +} + +int bee_crypto_lock(void) { + if (bee_crypto_mutex == NULL && bee_crypto_init() != BEE_CRYPTO_SUCCESS) { + return BEE_CRYPTO_ERROR_SYNC; + } + + return os_mutex_take(bee_crypto_mutex, BEE_CRYPTO_WAIT_FOREVER) + ? BEE_CRYPTO_SUCCESS + : BEE_CRYPTO_ERROR_SYNC; +} + +void bee_crypto_unlock(void) { + if (bee_crypto_mutex != NULL) { + (void)os_mutex_give(bee_crypto_mutex); + } +} + +static void bee_aes_copy_to_hw(const uint8_t *src, uint32_t *dst, size_t len) { +#if defined(BEE_CRYPTO_RTL8752H) + swap_buf(src, (uint8_t *)dst, (uint16_t)len); +#else + memcpy(dst, src, len); +#endif +} + +static void bee_aes_copy_from_hw(const uint32_t *src, uint8_t *dst, + size_t len) { +#if defined(BEE_CRYPTO_RTL8752H) + swap_buf((const uint8_t *)src, dst, (uint16_t)len); +#else + memcpy(dst, src, len); +#endif +} + +int bee_aes_hw_crypt_block(const uint8_t *key, size_t key_len, + T_HW_AES_MODE mode, const uint8_t *in, uint8_t *out, + const uint8_t *iv, bool decrypt) { + uint32_t in_hw[BEE_AES_BLOCK_SIZE / sizeof(uint32_t)]; + uint32_t out_hw[BEE_AES_BLOCK_SIZE / sizeof(uint32_t)]; + uint32_t key_hw[32U / sizeof(uint32_t)]; + uint32_t iv_hw[BEE_AES_BLOCK_SIZE / sizeof(uint32_t)]; + uint32_t *iv_arg = NULL; + bool ret; + + if (key == NULL || in == NULL || out == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + bee_aes_copy_to_hw(in, in_hw, BEE_AES_BLOCK_SIZE); + bee_aes_copy_to_hw(key, key_hw, key_len); + + if (iv != NULL) { + bee_aes_copy_to_hw(iv, iv_hw, BEE_AES_BLOCK_SIZE); + iv_arg = iv_hw; + } + + if (key_len == 16U) { + if (decrypt) { + ret = hw_aes_decrypt128(in_hw, out_hw, 4, key_hw, iv_arg, mode); + } else { + ret = hw_aes_encrypt128(in_hw, out_hw, 4, key_hw, iv_arg, mode); + } + } else if (key_len == 32U) { + if (decrypt) { + ret = hw_aes_decrypt256(in_hw, out_hw, 4, key_hw, iv_arg, mode); + } else { + ret = hw_aes_encrypt256(in_hw, out_hw, 4, key_hw, iv_arg, mode); + } + } else { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + if (!ret) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + + bee_aes_copy_from_hw(out_hw, out, BEE_AES_BLOCK_SIZE); + return BEE_CRYPTO_SUCCESS; +} + +int bee_sha256_hw_compute(const uint8_t *input, size_t input_length, + uint8_t *hash) { + uint32_t result[8]; + uint8_t empty = 0U; + int status; + bool ret; + + if ((input == NULL && input_length != 0U) || hash == NULL || + input_length > UINT32_MAX) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + status = bee_crypto_lock(); + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + ret = hw_sha256(input_length == 0U ? &empty : (uint8_t *)input, + (uint32_t)input_length, result, HW_SHA256_CPU_MODE); + bee_crypto_unlock(); + + if (!ret) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + memcpy(hash, result, sizeof(result)); + return BEE_CRYPTO_SUCCESS; +} + +int bee_sha256_hw_start(HW_SHA256_CTX *ctx) { + int status; + + if (ctx == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + status = bee_crypto_lock(); + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + hw_sha256_start(ctx, NULL); + bee_crypto_unlock(); + return BEE_CRYPTO_SUCCESS; +} + +int bee_sha256_hw_update(HW_SHA256_CTX *ctx, const uint8_t *input, + size_t input_length) { + int status; + bool ret; + + if (ctx == NULL || (input == NULL && input_length != 0U) || + input_length > UINT32_MAX) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + if (input_length == 0U) { + return BEE_CRYPTO_SUCCESS; + } + + status = bee_crypto_lock(); + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + ret = hw_sha256_cpu_update(ctx, (uint8_t *)input, (uint32_t)input_length); + bee_crypto_unlock(); + + return ret ? BEE_CRYPTO_SUCCESS : BEE_CRYPTO_ERROR_HARDWARE; +} + +int bee_sha256_hw_finish(HW_SHA256_CTX *ctx, uint8_t *hash) { + uint32_t result[8]; + int status; + bool ret; + + if (ctx == NULL || hash == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + status = bee_crypto_lock(); + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + ret = hw_sha256_finish(ctx, result); + bee_crypto_unlock(); + + if (!ret) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + memcpy(hash, result, sizeof(result)); + return BEE_CRYPTO_SUCCESS; +} + +#if defined(BEE_CRYPTO_RTL87X2G) +#define BEE_PKE_MMEM_ADDR 0x50090000U +#define BEE_ECC_N_ADDR (BEE_PKE_MMEM_ADDR + 0x000U) +#define BEE_ECC_A_ADDR (BEE_PKE_MMEM_ADDR + 0x080U) +#define BEE_ECC_B_ADDR (BEE_PKE_MMEM_ADDR + 0x100U) +#define BEE_ECC_X_ADDR (BEE_PKE_MMEM_ADDR + 0x140U) +#define BEE_ECC_Y_ADDR (BEE_PKE_MMEM_ADDR + 0x180U) +#define BEE_ECC_Z_ADDR (BEE_PKE_MMEM_ADDR + 0x1c0U) +#define BEE_ECC_RX_ADDR (BEE_PKE_MMEM_ADDR + 0x200U) +#define BEE_ECC_RY_ADDR (BEE_PKE_MMEM_ADDR + 0x240U) +#define BEE_ECC_RZ_ADDR (BEE_PKE_MMEM_ADDR + 0x280U) + +#define BEE_ECC_MUL_ENTRY 0x1U +#define BEE_MOD_MUL_ENTRY 0x2U +#define BEE_MOD_ADD_ENTRY 0x3U +#define BEE_R_SQUARE_ENTRY 0x5U +#define BEE_N_INVERSE_ENTRY 0x6U +#define BEE_MOD_INVERSE_ENTRY 0x7U +#define BEE_ECC_ADD_ENTRY 0x8U +#define BEE_MOD_REDUCE_ENTRY 0xeU + +#define BEE_ECC_GO_TO_END true +#define BEE_ECC_RR_READY true + +static const uint32_t bee_p256_prime[BEE_ECC_P256_WORDS] = { + 0xffffffffU, 0xffffffffU, 0xffffffffU, 0x00000000U, + 0x00000000U, 0x00000000U, 0x00000001U, 0xffffffffU, +}; +static const uint32_t bee_p256_order[BEE_ECC_P256_WORDS] = { + 0xfc632551U, 0xf3b9cac2U, 0xa7179e84U, 0xbce6faadU, + 0xffffffffU, 0xffffffffU, 0x00000000U, 0xffffffffU, +}; +static const uint32_t bee_p256_a[BEE_ECC_P256_WORDS] = { + 0xfffffffcU, 0xffffffffU, 0xffffffffU, 0x00000000U, + 0x00000000U, 0x00000000U, 0x00000001U, 0xffffffffU, +}; +static const uint32_t bee_p256_b[BEE_ECC_P256_WORDS] = { + 0x27d2604bU, 0x3bce3c3eU, 0xcc53b0f6U, 0x651d06b0U, + 0x769886bcU, 0xb3ebbd55U, 0xaa3a93e7U, 0x5ac635d8U, +}; + +static int bee_ecc_result(ERR_CODE status) { + return status == ERR_NONE ? BEE_CRYPTO_SUCCESS : BEE_CRYPTO_ERROR_HARDWARE; +} + +int bee_ecc_p256_enable(void) { + hw_pke_clock(true); + hw_pke_init(false, false, 0U); + return BEE_CRYPTO_SUCCESS; +} + +void bee_ecc_p256_disable(void) { hw_pke_clock(false); } + +int bee_ecc_p256_mod_prepare(const uint32_t modulus[BEE_ECC_P256_WORDS]) { + uint32_t temporary[16]; + + if (modulus == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + hw_ecc_init(256U, ECC_PRIME_MODE, BEE_ECC_GO_TO_END, !BEE_ECC_RR_READY); + hw_ecc_set_sub_operand(BEE_ECC_N_ADDR, (uint32_t *)modulus, + BEE_ECC_P256_WORDS * sizeof(uint32_t)); + if (hw_ecc_compute(temporary, BEE_ECC_RX_ADDR, BEE_N_INVERSE_ENTRY) != + ERR_NONE) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + + hw_ecc_init(256U, ECC_PRIME_MODE, BEE_ECC_GO_TO_END, !BEE_ECC_RR_READY); + return bee_ecc_result( + hw_ecc_compute(temporary, BEE_ECC_RX_ADDR, BEE_R_SQUARE_ENTRY)); +} + +int bee_ecc_p256_mod_reduce(uint32_t value[BEE_ECC_P256_WORDS]) { + if (value == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + hw_ecc_init(256U, ECC_PRIME_MODE, BEE_ECC_GO_TO_END, !BEE_ECC_RR_READY); + hw_ecc_set_sub_operand(BEE_ECC_N_ADDR, (uint32_t *)bee_p256_order, + sizeof(bee_p256_order)); + hw_ecc_set_sub_operand(BEE_ECC_RX_ADDR, value, + BEE_ECC_P256_WORDS * sizeof(uint32_t)); + return bee_ecc_result( + hw_ecc_compute(value, BEE_ECC_RX_ADDR, BEE_MOD_REDUCE_ENTRY)); +} + +int bee_ecc_p256_mod_mul(const uint32_t left[BEE_ECC_P256_WORDS], + const uint32_t right[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]) { + if (left == NULL || right == NULL || result == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + hw_ecc_init(256U, ECC_PRIME_MODE, BEE_ECC_GO_TO_END, BEE_ECC_RR_READY); + hw_ecc_set_sub_operand(BEE_ECC_A_ADDR, (uint32_t *)left, + BEE_ECC_P256_WORDS * sizeof(uint32_t)); + hw_ecc_set_sub_operand(BEE_ECC_B_ADDR, (uint32_t *)right, + BEE_ECC_P256_WORDS * sizeof(uint32_t)); + return bee_ecc_result( + hw_ecc_compute(result, BEE_ECC_A_ADDR, BEE_MOD_MUL_ENTRY)); +} + +int bee_ecc_p256_mod_add(const uint32_t left[BEE_ECC_P256_WORDS], + const uint32_t right[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]) { + if (left == NULL || right == NULL || result == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + hw_ecc_init(256U, ECC_PRIME_MODE, BEE_ECC_GO_TO_END, BEE_ECC_RR_READY); + hw_ecc_set_sub_operand(BEE_ECC_A_ADDR, (uint32_t *)left, + BEE_ECC_P256_WORDS * sizeof(uint32_t)); + hw_ecc_set_sub_operand(BEE_ECC_B_ADDR, (uint32_t *)right, + BEE_ECC_P256_WORDS * sizeof(uint32_t)); + return bee_ecc_result( + hw_ecc_compute(result, BEE_ECC_A_ADDR, BEE_MOD_ADD_ENTRY)); +} + +int bee_ecc_p256_mod_inv(const uint32_t value[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]) { + if (value == NULL || result == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + hw_ecc_init(256U, ECC_PRIME_MODE, BEE_ECC_GO_TO_END, BEE_ECC_RR_READY); + hw_ecc_set_sub_operand(BEE_ECC_B_ADDR, (uint32_t *)value, + BEE_ECC_P256_WORDS * sizeof(uint32_t)); + return bee_ecc_result( + hw_ecc_compute(result, BEE_ECC_B_ADDR, BEE_MOD_INVERSE_ENTRY)); +} + +static int bee_ecc_p256_compare(const uint32_t left[BEE_ECC_P256_WORDS], + const uint32_t right[BEE_ECC_P256_WORDS]) { + for (size_t i = BEE_ECC_P256_WORDS; i > 0U; i--) { + if (left[i - 1U] < right[i - 1U]) { + return -1; + } + if (left[i - 1U] > right[i - 1U]) { + return 1; + } + } + return 0; +} + +int bee_ecc_p256_validate_public(const struct bee_ecc_point *point) { + uint32_t left[BEE_ECC_P256_WORDS]; + uint32_t right[BEE_ECC_P256_WORDS]; + uint32_t temporary[BEE_ECC_P256_WORDS]; + int status; + + if (point == NULL || bee_ecc_p256_compare(point->x, bee_p256_prime) >= 0 || + bee_ecc_p256_compare(point->y, bee_p256_prime) >= 0) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + status = bee_ecc_p256_mod_prepare(bee_p256_prime); + if (status == BEE_CRYPTO_SUCCESS) { + status = bee_ecc_p256_mod_mul(point->y, point->y, left); + } + if (status == BEE_CRYPTO_SUCCESS) { + status = bee_ecc_p256_mod_mul(point->x, point->x, temporary); + } + if (status == BEE_CRYPTO_SUCCESS) { + status = bee_ecc_p256_mod_add(temporary, bee_p256_a, temporary); + } + if (status == BEE_CRYPTO_SUCCESS) { + status = bee_ecc_p256_mod_mul(temporary, point->x, right); + } + if (status == BEE_CRYPTO_SUCCESS) { + status = bee_ecc_p256_mod_add(right, bee_p256_b, right); + } + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + return memcmp(left, right, sizeof(left)) == 0 + ? BEE_CRYPTO_SUCCESS + : BEE_CRYPTO_ERROR_INVALID_ARGUMENT; +} + +int bee_ecc_p256_mul(const uint32_t scalar[BEE_ECC_P256_WORDS], + const struct bee_ecc_point *point, + struct bee_ecc_point *result) { + ECC_GROUP group = {0}; + ECC_POINT base = {0}; + ECC_POINT hardware_result = {0}; + uint32_t a[BEE_ECC_P256_WORDS]; + uint32_t b[BEE_ECC_P256_WORDS]; + uint32_t n[BEE_ECC_P256_WORDS]; + + if (scalar == NULL || point == NULL || result == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + memcpy(a, bee_p256_a, sizeof(a)); + memcpy(b, bee_p256_b, sizeof(b)); + memcpy(n, bee_p256_order, sizeof(n)); + memcpy(base.x, point->x, sizeof(point->x)); + memcpy(base.y, point->y, sizeof(point->y)); + memcpy(base.z, point->z, sizeof(point->z)); + group.N = (uint32_t *)bee_p256_prime; + group.A = a; + group.B = b; + group.n = n; + group.G = base; + group.key_bits = 256U; + group.mode = ECC_PRIME_MODE; + + hw_ecc_init(256U, ECC_PRIME_MODE, !BEE_ECC_GO_TO_END, !BEE_ECC_RR_READY); + if (!hw_ecc_set_all_operands(&group, (uint32_t *)scalar, + BEE_ECC_P256_WORDS * sizeof(uint32_t))) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + if (hw_ecc_compute(&hardware_result, BEE_ECC_RX_ADDR, BEE_ECC_MUL_ENTRY) != + ERR_NONE) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + + memcpy(result->x, hardware_result.x, sizeof(result->x)); + memcpy(result->y, hardware_result.y, sizeof(result->y)); + memset(result->z, 0, sizeof(result->z)); + result->z[0] = 1U; + return BEE_CRYPTO_SUCCESS; +} + +int bee_ecc_p256_add(const struct bee_ecc_point *left, + const struct bee_ecc_point *right, + struct bee_ecc_point *result) { + ECC_POINT hardware_result = {0}; + + if (left == NULL || right == NULL || result == NULL) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + if (bee_ecc_p256_mod_prepare(bee_p256_prime) != BEE_CRYPTO_SUCCESS) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + hw_ecc_init(256U, ECC_PRIME_MODE, BEE_ECC_GO_TO_END, BEE_ECC_RR_READY); + hw_ecc_set_sub_operand(BEE_ECC_A_ADDR, (uint32_t *)bee_p256_a, + sizeof(bee_p256_a)); + hw_ecc_set_sub_operand(BEE_ECC_B_ADDR, (uint32_t *)bee_p256_b, + sizeof(bee_p256_b)); + hw_ecc_set_sub_operand(BEE_ECC_X_ADDR, (uint32_t *)left->x, sizeof(left->x)); + hw_ecc_set_sub_operand(BEE_ECC_Y_ADDR, (uint32_t *)left->y, sizeof(left->y)); + hw_ecc_set_sub_operand(BEE_ECC_Z_ADDR, (uint32_t *)left->z, sizeof(left->z)); + hw_ecc_set_sub_operand(BEE_ECC_RX_ADDR, (uint32_t *)right->x, + sizeof(right->x)); + hw_ecc_set_sub_operand(BEE_ECC_RY_ADDR, (uint32_t *)right->y, + sizeof(right->y)); + hw_ecc_set_sub_operand(BEE_ECC_RZ_ADDR, (uint32_t *)right->z, + sizeof(right->z)); + if (hw_ecc_compute(&hardware_result, BEE_ECC_RX_ADDR, BEE_ECC_ADD_ENTRY) != + ERR_NONE) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + + memcpy(result->x, hardware_result.x, sizeof(result->x)); + memcpy(result->y, hardware_result.y, sizeof(result->y)); + memset(result->z, 0, sizeof(result->z)); + result->z[0] = 1U; + return BEE_CRYPTO_SUCCESS; +} +#else +int bee_ecc_p256_enable(void) { return BEE_CRYPTO_ERROR_NOT_SUPPORTED; } + +void bee_ecc_p256_disable(void) {} + +int bee_ecc_p256_mod_prepare(const uint32_t modulus[BEE_ECC_P256_WORDS]) { + (void)modulus; + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; +} + +int bee_ecc_p256_mod_reduce(uint32_t value[BEE_ECC_P256_WORDS]) { + (void)value; + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; +} + +int bee_ecc_p256_mod_mul(const uint32_t left[BEE_ECC_P256_WORDS], + const uint32_t right[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]) { + (void)left; + (void)right; + (void)result; + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; +} + +int bee_ecc_p256_mod_add(const uint32_t left[BEE_ECC_P256_WORDS], + const uint32_t right[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]) { + (void)left; + (void)right; + (void)result; + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; +} + +int bee_ecc_p256_mod_inv(const uint32_t value[BEE_ECC_P256_WORDS], + uint32_t result[BEE_ECC_P256_WORDS]) { + (void)value; + (void)result; + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; +} + +int bee_ecc_p256_mul(const uint32_t scalar[BEE_ECC_P256_WORDS], + const struct bee_ecc_point *point, + struct bee_ecc_point *result) { + (void)scalar; + (void)point; + (void)result; + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; +} + +int bee_ecc_p256_validate_public(const struct bee_ecc_point *point) { + (void)point; + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; +} + +int bee_ecc_p256_add(const struct bee_ecc_point *left, + const struct bee_ecc_point *right, + struct bee_ecc_point *result) { + (void)left; + (void)right; + (void)result; + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; +} +#endif diff --git a/bee/drivers/crypto/psa/inc/crypto_bee_psa.h b/bee/drivers/crypto/psa/inc/crypto_bee_psa.h new file mode 100644 index 00000000..ceca8759 --- /dev/null +++ b/bee/drivers/crypto/psa/inc/crypto_bee_psa.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2026, Realtek Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef REALTEK_BEE_CRYPTO_PSA_H_ +#define REALTEK_BEE_CRYPTO_PSA_H_ + +#include "crypto_bee_psa_types.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +psa_status_t bee_psa_init(void); + +psa_status_t bee_psa_hash_compute(psa_algorithm_t alg, const uint8_t *input, + size_t input_length, uint8_t *hash, + size_t hash_size, size_t *hash_length); +psa_status_t bee_psa_hash_setup(bee_psa_hash_operation_t *operation, + psa_algorithm_t alg); +psa_status_t bee_psa_hash_clone(const bee_psa_hash_operation_t *source_operation, + bee_psa_hash_operation_t *target_operation); +psa_status_t bee_psa_hash_update(bee_psa_hash_operation_t *operation, + const uint8_t *input, size_t input_length); +psa_status_t bee_psa_hash_finish(bee_psa_hash_operation_t *operation, + uint8_t *hash, size_t hash_size, + size_t *hash_length); +psa_status_t bee_psa_hash_abort(bee_psa_hash_operation_t *operation); + +psa_status_t bee_psa_sign_hash(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, + size_t *signature_length); +psa_status_t bee_psa_verify_hash(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, + size_t signature_length); +psa_status_t bee_psa_key_agreement(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length); + +psa_status_t bee_psa_cipher_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *iv, size_t iv_length, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length); + +psa_status_t bee_psa_cipher_decrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length); + +psa_status_t +bee_psa_cipher_encrypt_setup(bee_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg); +psa_status_t +bee_psa_cipher_decrypt_setup(bee_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg); +psa_status_t bee_psa_cipher_set_iv(bee_psa_cipher_operation_t *operation, + const uint8_t *iv, size_t iv_length); +psa_status_t bee_psa_cipher_update(bee_psa_cipher_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length); +psa_status_t bee_psa_cipher_finish(bee_psa_cipher_operation_t *operation, + uint8_t *output, size_t output_size, + size_t *output_length); +psa_status_t bee_psa_cipher_abort(bee_psa_cipher_operation_t *operation); + +psa_status_t bee_psa_aead_encrypt_setup(bee_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg); +psa_status_t bee_psa_aead_decrypt_setup(bee_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg); +psa_status_t bee_psa_aead_set_nonce(bee_psa_aead_operation_t *operation, + const uint8_t *nonce, size_t nonce_length); +psa_status_t bee_psa_aead_set_lengths(bee_psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); +psa_status_t bee_psa_aead_update_ad(bee_psa_aead_operation_t *operation, + const uint8_t *input, size_t input_length); +psa_status_t bee_psa_aead_update(bee_psa_aead_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length); +psa_status_t bee_psa_aead_finish(bee_psa_aead_operation_t *operation, + uint8_t *ciphertext, size_t ciphertext_size, + size_t *ciphertext_length, uint8_t *tag, + size_t tag_size, size_t *tag_length); +psa_status_t bee_psa_aead_verify(bee_psa_aead_operation_t *operation, + uint8_t *plaintext, size_t plaintext_size, + size_t *plaintext_length, const uint8_t *tag, + size_t tag_length); +psa_status_t bee_psa_aead_abort(bee_psa_aead_operation_t *operation); + +psa_status_t +bee_psa_aead_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *plaintext, + size_t plaintext_length, uint8_t *ciphertext, + size_t ciphertext_size, size_t *ciphertext_length); + +psa_status_t +bee_psa_aead_decrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *ciphertext, + size_t ciphertext_length, uint8_t *plaintext, + size_t plaintext_size, size_t *plaintext_length); + +#ifdef __cplusplus +} +#endif + +#endif /* REALTEK_BEE_CRYPTO_PSA_H_ */ diff --git a/bee/drivers/crypto/psa/inc/crypto_bee_psa_types.h b/bee/drivers/crypto/psa/inc/crypto_bee_psa_types.h new file mode 100644 index 00000000..7bfdfafe --- /dev/null +++ b/bee/drivers/crypto/psa/inc/crypto_bee_psa_types.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026, Realtek Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef REALTEK_BEE_CRYPTO_PSA_TYPES_H_ +#define REALTEK_BEE_CRYPTO_PSA_TYPES_H_ + +#include +#include +#include + +#if defined(BEE_CRYPTO_RTL87X2G) +#include +#elif defined(BEE_CRYPTO_RTL8752H) +#include +#else +#error "Unsupported Realtek Bee SoC" +#endif + +typedef struct { + HW_SHA256_CTX context; + psa_algorithm_t algorithm; +} bee_psa_hash_operation_t; + +typedef struct { + uint8_t key[32]; + uint8_t iv[16]; + uint8_t buffer[16]; + uint8_t stream[16]; + size_t key_length; + size_t buffer_length; + size_t stream_used; + psa_algorithm_t algorithm; + uint8_t decrypt; + uint8_t iv_set; +} bee_psa_cipher_operation_t; + +typedef struct { + uint8_t key[32]; + uint8_t nonce[13]; + uint8_t mac[16]; + uint8_t b0[16]; + uint8_t aad_block[16]; + uint8_t payload_block[16]; + uint8_t counter[16]; + uint8_t stream[16]; + uint8_t tag[16]; + size_t key_length; + size_t nonce_length; + size_t tag_length; + size_t aad_length; + size_t aad_processed; + size_t payload_length; + size_t payload_processed; + size_t aad_block_used; + size_t payload_block_used; + size_t stream_used; + uint8_t length_size; + uint8_t decrypt; + uint8_t nonce_set; + uint8_t lengths_set; + uint8_t b0_processed; + uint8_t aad_finished; + uint8_t tag_ready; +} bee_psa_aead_operation_t; + +#endif /* REALTEK_BEE_CRYPTO_PSA_TYPES_H_ */ diff --git a/bee/drivers/crypto/psa/src/crypto_bee_psa.c b/bee/drivers/crypto/psa/src/crypto_bee_psa.c new file mode 100644 index 00000000..6d7b2686 --- /dev/null +++ b/bee/drivers/crypto/psa/src/crypto_bee_psa.c @@ -0,0 +1,1759 @@ +/* + * Copyright (c) 2026, Realtek Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "crypto_bee_psa.h" +#include "crypto_bee_psa_adapter.h" +#include + +#define BEE_PSA_CCM_BLOCK_SIZE 16U +#define BEE_PSA_P256_BYTES 32U +#define BEE_PSA_P256_SIGNATURE_BYTES (2U * BEE_PSA_P256_BYTES) + +static const uint32_t bee_psa_p256_order[BEE_ECC_P256_WORDS] = { + 0xfc632551U, 0xf3b9cac2U, 0xa7179e84U, 0xbce6faadU, + 0xffffffffU, 0xffffffffU, 0x00000000U, 0xffffffffU, +}; +static const struct bee_ecc_point bee_psa_p256_generator = { + .x = {0xd898c296U, 0xf4a13945U, 0x2deb33a0U, 0x77037d81U, 0x63a440f2U, + 0xf8bce6e5U, 0xe12c4247U, 0x6b17d1f2U}, + .y = {0x37bf51f5U, 0xcbb64068U, 0x6b315eceU, 0x2bce3357U, 0x7c0f9e16U, + 0x8ee7eb4aU, 0xfe1a7f9bU, 0x4fe342e2U}, + .z = {1U}, +}; + +struct bee_psa_ccm_context { + const uint8_t *key; + size_t key_length; + const uint8_t *nonce; + size_t nonce_length; + uint8_t length_size; + uint8_t mac[BEE_PSA_CCM_BLOCK_SIZE]; +}; + +psa_status_t bee_psa_init(void) { + int status = bee_crypto_init(); + + if (status != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + + hw_sha256_init(); + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_status(int status) { + if (status == BEE_CRYPTO_SUCCESS) { + return PSA_SUCCESS; + } + if (status == BEE_CRYPTO_ERROR_NOT_SUPPORTED) { + return PSA_ERROR_NOT_SUPPORTED; + } + + return status == BEE_CRYPTO_ERROR_INVALID_ARGUMENT + ? PSA_ERROR_INVALID_ARGUMENT + : PSA_ERROR_HARDWARE_FAILURE; +} + +psa_status_t bee_psa_hash_compute(psa_algorithm_t alg, const uint8_t *input, + size_t input_length, uint8_t *hash, + size_t hash_size, size_t *hash_length) { + size_t required_size = PSA_HASH_LENGTH(PSA_ALG_SHA_256); + psa_status_t status; + + if (alg != PSA_ALG_SHA_256) { + return PSA_ERROR_NOT_SUPPORTED; + } + if ((input == NULL && input_length != 0U) || hash_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (hash_size < required_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + if (hash == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = bee_psa_status(bee_sha256_hw_compute(input, input_length, hash)); + if (status == PSA_SUCCESS) { + *hash_length = required_size; + } + return status; +} + +psa_status_t bee_psa_hash_setup(bee_psa_hash_operation_t *operation, + psa_algorithm_t alg) { + psa_status_t status; + + if (operation == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (alg != PSA_ALG_SHA_256) { + return PSA_ERROR_NOT_SUPPORTED; + } + + memset(operation, 0, sizeof(*operation)); + status = bee_psa_status(bee_sha256_hw_start(&operation->context)); + if (status == PSA_SUCCESS) { + operation->algorithm = alg; + } + return status; +} + +psa_status_t bee_psa_hash_clone(const bee_psa_hash_operation_t *source_operation, + bee_psa_hash_operation_t *target_operation) { + if (source_operation == NULL || target_operation == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (source_operation->algorithm != PSA_ALG_SHA_256) { + return PSA_ERROR_BAD_STATE; + } + + memcpy(target_operation, source_operation, sizeof(*target_operation)); + return PSA_SUCCESS; +} + +psa_status_t bee_psa_hash_update(bee_psa_hash_operation_t *operation, + const uint8_t *input, size_t input_length) { + if (operation == NULL || (input == NULL && input_length != 0U)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (operation->algorithm != PSA_ALG_SHA_256) { + return PSA_ERROR_BAD_STATE; + } + + return bee_psa_status( + bee_sha256_hw_update(&operation->context, input, input_length)); +} + +psa_status_t bee_psa_hash_finish(bee_psa_hash_operation_t *operation, + uint8_t *hash, size_t hash_size, + size_t *hash_length) { + size_t required_size = PSA_HASH_LENGTH(PSA_ALG_SHA_256); + psa_status_t status; + + if (operation == NULL || hash_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (operation->algorithm != PSA_ALG_SHA_256) { + return PSA_ERROR_BAD_STATE; + } + if (hash_size < required_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + if (hash == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = bee_psa_status(bee_sha256_hw_finish(&operation->context, hash)); + if (status == PSA_SUCCESS) { + *hash_length = required_size; + } + return status; +} + +psa_status_t bee_psa_hash_abort(bee_psa_hash_operation_t *operation) { + if (operation == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memset(operation, 0, sizeof(*operation)); + return PSA_SUCCESS; +} + +static void bee_psa_p256_read(const uint8_t *input, size_t input_length, + uint32_t output[BEE_ECC_P256_WORDS]) { + size_t used = + input_length > BEE_PSA_P256_BYTES ? BEE_PSA_P256_BYTES : input_length; + + memset(output, 0, BEE_PSA_P256_BYTES); + for (size_t i = 0; i < used; i++) { + output[(used - 1U - i) / sizeof(uint32_t)] |= + (uint32_t)input[i] << (8U * ((used - 1U - i) % sizeof(uint32_t))); + } +} + +static void bee_psa_p256_write(const uint32_t input[BEE_ECC_P256_WORDS], + uint8_t output[BEE_PSA_P256_BYTES]) { + for (size_t i = 0; i < BEE_PSA_P256_BYTES; i++) { + output[BEE_PSA_P256_BYTES - 1U - i] = + (uint8_t)(input[i / sizeof(uint32_t)] >> (8U * (i % sizeof(uint32_t)))); + } +} + +static int bee_psa_p256_is_zero(const uint32_t value[BEE_ECC_P256_WORDS]) { + uint32_t result = 0U; + + for (size_t i = 0; i < BEE_ECC_P256_WORDS; i++) { + result |= value[i]; + } + return result == 0U; +} + +static int bee_psa_p256_compare(const uint32_t left[BEE_ECC_P256_WORDS], + const uint32_t right[BEE_ECC_P256_WORDS]) { + for (size_t i = BEE_ECC_P256_WORDS; i > 0U; i--) { + if (left[i - 1U] < right[i - 1U]) { + return -1; + } + if (left[i - 1U] > right[i - 1U]) { + return 1; + } + } + return 0; +} + +static void bee_psa_p256_reduce_order(uint32_t value[BEE_ECC_P256_WORDS]) { + uint64_t borrow = 0U; + + if (bee_psa_p256_compare(value, bee_psa_p256_order) < 0) { + return; + } + for (size_t i = 0; i < BEE_ECC_P256_WORDS; i++) { + uint64_t subtrahend = (uint64_t)bee_psa_p256_order[i] + borrow; + uint64_t current = value[i]; + + value[i] = (uint32_t)(current - subtrahend); + borrow = current < subtrahend; + } +} + +static int bee_psa_p256_point_is_zero(const struct bee_ecc_point *point) { + return bee_psa_p256_is_zero(point->x) && bee_psa_p256_is_zero(point->y); +} + +static psa_status_t +bee_psa_validate_ecdsa(const psa_key_attributes_t *attributes, + psa_algorithm_t alg, bool signing) { + psa_key_type_t type = psa_get_key_type(attributes); + +#if !defined(BEE_CRYPTO_RTL87X2G) + (void)type; + (void)alg; + (void)signing; + return PSA_ERROR_NOT_SUPPORTED; +#else + if (!PSA_ALG_IS_RANDOMIZED_ECDSA(alg) || + PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_SECP_R1 || + psa_get_key_bits(attributes) != 256U) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (signing) { + return type == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) + ? PSA_SUCCESS + : PSA_ERROR_NOT_SUPPORTED; + } + return (type == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) || + type == PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) + ? PSA_SUCCESS + : PSA_ERROR_NOT_SUPPORTED; +#endif +} + +static psa_status_t bee_psa_validate_ecdh( + const psa_key_attributes_t *attributes, psa_algorithm_t alg) { +#if !defined(BEE_CRYPTO_RTL87X2G) + (void)attributes; + (void)alg; + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_key_type_t type = psa_get_key_type(attributes); + + if (!PSA_ALG_IS_ECDH(alg) || + type != PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) || + psa_get_key_bits(attributes) != 256U) { + return PSA_ERROR_NOT_SUPPORTED; + } + return PSA_SUCCESS; +#endif +} + +psa_status_t bee_psa_key_agreement(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length) { + uint32_t private_key[BEE_ECC_P256_WORDS]; + struct bee_ecc_point peer_point = {0}; + struct bee_ecc_point result = {0}; + psa_status_t status = bee_psa_validate_ecdh(attributes, alg); + + if (status != PSA_SUCCESS) { + return status; + } + if (key_buffer == NULL || peer_key == NULL || shared_secret == NULL || + shared_secret_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (key_buffer_size != BEE_PSA_P256_BYTES || + peer_key_length != 1U + 2U * BEE_PSA_P256_BYTES || + peer_key[0] != 0x04U) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (shared_secret_size < BEE_PSA_P256_BYTES) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + bee_psa_p256_read(key_buffer, key_buffer_size, private_key); + if (bee_psa_p256_is_zero(private_key) || + bee_psa_p256_compare(private_key, bee_psa_p256_order) >= 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + bee_psa_p256_read(&peer_key[1], BEE_PSA_P256_BYTES, peer_point.x); + bee_psa_p256_read(&peer_key[1U + BEE_PSA_P256_BYTES], BEE_PSA_P256_BYTES, + peer_point.y); + if (bee_psa_p256_is_zero(peer_point.x) && + bee_psa_p256_is_zero(peer_point.y)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + peer_point.z[0] = 1U; + + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + status = PSA_ERROR_HARDWARE_FAILURE; + goto exit; + } + status = bee_psa_status(bee_ecc_p256_enable()); + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_validate_public(&peer_point)); + } + if (status == PSA_SUCCESS) { + status = + bee_psa_status(bee_ecc_p256_mul(private_key, &peer_point, &result)); + } + bee_ecc_p256_disable(); + bee_crypto_unlock(); + + if (status == PSA_SUCCESS && bee_psa_p256_point_is_zero(&result)) { + status = PSA_ERROR_INVALID_ARGUMENT; + } + if (status == PSA_SUCCESS) { + bee_psa_p256_write(result.x, shared_secret); + *shared_secret_length = BEE_PSA_P256_BYTES; + } + +exit: + memset(private_key, 0, sizeof(private_key)); + memset(&result, 0, sizeof(result)); + return status; +} + +static psa_status_t +bee_psa_p256_public_from_key(psa_key_type_t type, const uint8_t *key_buffer, + size_t key_buffer_size, + struct bee_ecc_point *public_key) { + if (type == PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) { + if (key_buffer_size != 1U + 2U * BEE_PSA_P256_BYTES || + key_buffer[0] != 0x04U) { + return PSA_ERROR_INVALID_ARGUMENT; + } + bee_psa_p256_read(&key_buffer[1], BEE_PSA_P256_BYTES, public_key->x); + bee_psa_p256_read(&key_buffer[1U + BEE_PSA_P256_BYTES], BEE_PSA_P256_BYTES, + public_key->y); + public_key->z[0] = 1U; + return PSA_SUCCESS; + } + + if (key_buffer_size != BEE_PSA_P256_BYTES) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + uint32_t private_key[BEE_ECC_P256_WORDS]; + bee_psa_p256_read(key_buffer, key_buffer_size, private_key); + if (bee_psa_p256_is_zero(private_key) || + bee_psa_p256_compare(private_key, bee_psa_p256_order) >= 0) { + memset(private_key, 0, sizeof(private_key)); + return PSA_ERROR_INVALID_ARGUMENT; + } + int ret = bee_ecc_p256_mul(private_key, &bee_psa_p256_generator, public_key); + memset(private_key, 0, sizeof(private_key)); + return bee_psa_status(ret); +} + +psa_status_t bee_psa_sign_hash(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, + size_t *signature_length) { + uint32_t private_key[BEE_ECC_P256_WORDS]; + uint32_t e[BEE_ECC_P256_WORDS]; + uint32_t k[BEE_ECC_P256_WORDS]; + uint32_t r[BEE_ECC_P256_WORDS]; + uint32_t s[BEE_ECC_P256_WORDS]; + uint32_t temporary[BEE_ECC_P256_WORDS]; + struct bee_ecc_point point; + psa_status_t status = bee_psa_validate_ecdsa(attributes, alg, true); + + if (status != PSA_SUCCESS) { + return status; + } + if (key_buffer == NULL || hash == NULL || signature == NULL || + signature_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (key_buffer_size != BEE_PSA_P256_BYTES) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (signature_size < BEE_PSA_P256_SIGNATURE_BYTES) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + bee_psa_p256_read(key_buffer, key_buffer_size, private_key); + bee_psa_p256_read(hash, hash_length, e); + bee_psa_p256_reduce_order(e); + if (bee_psa_p256_is_zero(private_key) || + bee_psa_p256_compare(private_key, bee_psa_p256_order) >= 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + for (unsigned int attempt = 0; attempt < 10U; attempt++) { + uint8_t random[BEE_PSA_P256_BYTES]; + + status = psa_generate_random(random, sizeof(random)); + if (status != PSA_SUCCESS) { + break; + } + bee_psa_p256_read(random, sizeof(random), k); + memset(random, 0, sizeof(random)); + if (bee_psa_p256_is_zero(k) || + bee_psa_p256_compare(k, bee_psa_p256_order) >= 0) { + continue; + } + + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + status = PSA_ERROR_HARDWARE_FAILURE; + break; + } + status = bee_psa_status(bee_ecc_p256_enable()); + if (status == PSA_SUCCESS) { + status = + bee_psa_status(bee_ecc_p256_mul(k, &bee_psa_p256_generator, &point)); + } + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_mod_prepare(bee_psa_p256_order)); + } + if (status == PSA_SUCCESS) { + memcpy(r, point.x, sizeof(r)); + status = bee_psa_status(bee_ecc_p256_mod_reduce(r)); + } + if (status == PSA_SUCCESS && !bee_psa_p256_is_zero(r)) { + status = bee_psa_status(bee_ecc_p256_mod_mul(r, private_key, temporary)); + } + if (status == PSA_SUCCESS && !bee_psa_p256_is_zero(r)) { + status = bee_psa_status(bee_ecc_p256_mod_add(e, temporary, temporary)); + } + if (status == PSA_SUCCESS && !bee_psa_p256_is_zero(r)) { + status = bee_psa_status(bee_ecc_p256_mod_inv(k, s)); + } + if (status == PSA_SUCCESS && !bee_psa_p256_is_zero(r)) { + status = bee_psa_status(bee_ecc_p256_mod_mul(s, temporary, s)); + } + bee_ecc_p256_disable(); + bee_crypto_unlock(); + + if (status != PSA_SUCCESS) { + break; + } + if (bee_psa_p256_is_zero(r) || bee_psa_p256_is_zero(s)) { + continue; + } + + bee_psa_p256_write(r, signature); + bee_psa_p256_write(s, signature + BEE_PSA_P256_BYTES); + *signature_length = BEE_PSA_P256_SIGNATURE_BYTES; + status = PSA_SUCCESS; + goto exit; + } + + if (status == PSA_SUCCESS) { + status = PSA_ERROR_INSUFFICIENT_ENTROPY; + } + +exit: + memset(private_key, 0, sizeof(private_key)); + memset(k, 0, sizeof(k)); + memset(temporary, 0, sizeof(temporary)); + return status; +} + +psa_status_t bee_psa_verify_hash(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, + size_t signature_length) { + struct bee_ecc_point public_key = {0}; + struct bee_ecc_point point1; + struct bee_ecc_point point2; + struct bee_ecc_point result; + uint32_t e[BEE_ECC_P256_WORDS]; + uint32_t r[BEE_ECC_P256_WORDS]; + uint32_t s[BEE_ECC_P256_WORDS]; + uint32_t inverse[BEE_ECC_P256_WORDS]; + uint32_t u1[BEE_ECC_P256_WORDS]; + uint32_t u2[BEE_ECC_P256_WORDS]; + psa_key_type_t type = psa_get_key_type(attributes); + psa_status_t status = bee_psa_validate_ecdsa(attributes, alg, false); + + if (status != PSA_SUCCESS) { + return status; + } + if (key_buffer == NULL || hash == NULL || signature == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (signature_length != BEE_PSA_P256_SIGNATURE_BYTES) { + return PSA_ERROR_INVALID_SIGNATURE; + } + + bee_psa_p256_read(hash, hash_length, e); + bee_psa_p256_reduce_order(e); + bee_psa_p256_read(signature, BEE_PSA_P256_BYTES, r); + bee_psa_p256_read(signature + BEE_PSA_P256_BYTES, BEE_PSA_P256_BYTES, s); + if (bee_psa_p256_is_zero(r) || bee_psa_p256_is_zero(s) || + bee_psa_p256_compare(r, bee_psa_p256_order) >= 0 || + bee_psa_p256_compare(s, bee_psa_p256_order) >= 0) { + return PSA_ERROR_INVALID_SIGNATURE; + } + + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + status = bee_psa_status(bee_ecc_p256_enable()); + if (status == PSA_SUCCESS) { + status = bee_psa_p256_public_from_key(type, key_buffer, key_buffer_size, + &public_key); + } + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_mod_prepare(bee_psa_p256_order)); + } + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_mod_inv(s, inverse)); + } + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_mod_mul(inverse, e, u1)); + } + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_mod_mul(inverse, r, u2)); + } + if (status == PSA_SUCCESS) { + status = + bee_psa_status(bee_ecc_p256_mul(u1, &bee_psa_p256_generator, &point1)); + } + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_mul(u2, &public_key, &point2)); + } + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_add(&point1, &point2, &result)); + } + if (status == PSA_SUCCESS && bee_psa_p256_point_is_zero(&result)) { + status = PSA_ERROR_INVALID_SIGNATURE; + } + if (status == PSA_SUCCESS) { + status = bee_psa_status(bee_ecc_p256_mod_reduce(result.x)); + } + if (status == PSA_SUCCESS && memcmp(result.x, r, BEE_PSA_P256_BYTES) != 0) { + status = PSA_ERROR_INVALID_SIGNATURE; + } + bee_ecc_p256_disable(); + bee_crypto_unlock(); + return status; +} + +static psa_status_t bee_psa_validate_key(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size) { + if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES || + (key_buffer_size != 16U && key_buffer_size != 32U)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (key_buffer == NULL || + psa_get_key_bits(attributes) != PSA_BYTES_TO_BITS(key_buffer_size)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_ecb_crypt(const uint8_t *key, size_t key_length, + const uint8_t *input, uint8_t *output, + bool decrypt) { + return bee_psa_status(bee_aes_hw_crypt_block(key, key_length, AES_MODE_ECB, + input, output, NULL, decrypt)); +} + +static psa_status_t +bee_psa_ccm_mac_block(struct bee_psa_ccm_context *ctx, + const uint8_t block[BEE_PSA_CCM_BLOCK_SIZE]) { + uint8_t input[BEE_PSA_CCM_BLOCK_SIZE]; + + for (size_t i = 0; i < BEE_PSA_CCM_BLOCK_SIZE; i++) { + input[i] = ctx->mac[i] ^ block[i]; + } + + return bee_psa_ecb_crypt(ctx->key, ctx->key_length, input, ctx->mac, false); +} + +static psa_status_t bee_psa_ccm_mac_data(struct bee_psa_ccm_context *ctx, + const uint8_t *data, + size_t data_length) { + while (data_length > 0U) { + uint8_t block[BEE_PSA_CCM_BLOCK_SIZE] = {0}; + size_t chunk = data_length > sizeof(block) ? sizeof(block) : data_length; + psa_status_t status; + + memcpy(block, data, chunk); + status = bee_psa_ccm_mac_block(ctx, block); + if (status != PSA_SUCCESS) { + return status; + } + data += chunk; + data_length -= chunk; + } + + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_ccm_mac_aad(struct bee_psa_ccm_context *ctx, + const uint8_t *aad, size_t aad_length) { + uint8_t block[BEE_PSA_CCM_BLOCK_SIZE] = {0}; + size_t block_used = 2U; + psa_status_t status; + + if (aad_length == 0U) { + return PSA_SUCCESS; + } + + block[0] = (uint8_t)(aad_length >> 8); + block[1] = (uint8_t)aad_length; + while (aad_length > 0U) { + size_t chunk = aad_length; + + if (chunk > sizeof(block) - block_used) { + chunk = sizeof(block) - block_used; + } + memcpy(&block[block_used], aad, chunk); + block_used += chunk; + aad += chunk; + aad_length -= chunk; + + if (block_used == sizeof(block)) { + status = bee_psa_ccm_mac_block(ctx, block); + if (status != PSA_SUCCESS) { + return status; + } + memset(block, 0, sizeof(block)); + block_used = 0U; + } + } + + return block_used == 0U ? PSA_SUCCESS : bee_psa_ccm_mac_block(ctx, block); +} + +static void bee_psa_ccm_counter(const struct bee_psa_ccm_context *ctx, + uint8_t counter[BEE_PSA_CCM_BLOCK_SIZE], + uint64_t value) { + memset(counter, 0, BEE_PSA_CCM_BLOCK_SIZE); + counter[0] = ctx->length_size - 1U; + memcpy(&counter[1], ctx->nonce, ctx->nonce_length); + for (size_t i = 0; i < ctx->length_size; i++) { + counter[BEE_PSA_CCM_BLOCK_SIZE - 1U - i] = (uint8_t)value; + value >>= 8; + } +} + +static void bee_psa_ccm_increment(uint8_t counter[BEE_PSA_CCM_BLOCK_SIZE], + size_t offset) { + for (int i = BEE_PSA_CCM_BLOCK_SIZE - 1; i >= (int)offset; i--) { + if (++counter[i] != 0U) { + break; + } + } +} + +static psa_status_t bee_psa_ccm_crypt(const struct bee_psa_ccm_context *ctx, + const uint8_t *input, size_t input_length, + uint8_t *output) { + uint8_t counter[BEE_PSA_CCM_BLOCK_SIZE]; + + bee_psa_ccm_counter(ctx, counter, 1U); + while (input_length > 0U) { + uint8_t stream[BEE_PSA_CCM_BLOCK_SIZE]; + size_t chunk = + input_length > sizeof(stream) ? sizeof(stream) : input_length; + psa_status_t status = + bee_psa_ecb_crypt(ctx->key, ctx->key_length, counter, stream, false); + + if (status != PSA_SUCCESS) { + return status; + } + for (size_t i = 0; i < chunk; i++) { + output[i] = input[i] ^ stream[i]; + } + bee_psa_ccm_increment(counter, 1U + ctx->nonce_length); + input += chunk; + output += chunk; + input_length -= chunk; + } + + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_ccm_tag(struct bee_psa_ccm_context *ctx, + const uint8_t *aad, size_t aad_length, + const uint8_t *plaintext, + size_t plaintext_length, size_t tag_length, + uint8_t *tag) { + uint8_t b0[BEE_PSA_CCM_BLOCK_SIZE] = {0}; + uint8_t counter[BEE_PSA_CCM_BLOCK_SIZE]; + uint8_t s0[BEE_PSA_CCM_BLOCK_SIZE]; + uint64_t length = plaintext_length; + psa_status_t status; + + b0[0] = (aad_length > 0U ? 0x40U : 0U) | (((tag_length - 2U) / 2U) << 3) | + (ctx->length_size - 1U); + memcpy(&b0[1], ctx->nonce, ctx->nonce_length); + for (size_t i = 0; i < ctx->length_size; i++) { + b0[BEE_PSA_CCM_BLOCK_SIZE - 1U - i] = (uint8_t)length; + length >>= 8; + } + + status = bee_psa_ccm_mac_block(ctx, b0); + if (status == PSA_SUCCESS) { + status = bee_psa_ccm_mac_aad(ctx, aad, aad_length); + } + if (status == PSA_SUCCESS) { + status = bee_psa_ccm_mac_data(ctx, plaintext, plaintext_length); + } + if (status == PSA_SUCCESS) { + bee_psa_ccm_counter(ctx, counter, 0U); + status = bee_psa_ecb_crypt(ctx->key, ctx->key_length, counter, s0, false); + } + if (status == PSA_SUCCESS) { + for (size_t i = 0; i < tag_length; i++) { + tag[i] = ctx->mac[i] ^ s0[i]; + } + } + return status; +} + +static psa_status_t bee_psa_ccm_prepare( + struct bee_psa_ccm_context *ctx, const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, size_t aad_length, + size_t message_length, size_t *tag_length) { + uint64_t length = message_length; + psa_status_t status = + bee_psa_validate_key(attributes, key_buffer, key_buffer_size); + + if (status != PSA_SUCCESS) { + return status; + } + if (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0) != + PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0)) { + return PSA_ERROR_NOT_SUPPORTED; + } + *tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); + if (*tag_length < 4U || *tag_length > BEE_PSA_CCM_BLOCK_SIZE || + (*tag_length & 1U) != 0U || nonce == NULL || nonce_length < 7U || + nonce_length > 13U) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (aad_length >= 0xff00U) { + return PSA_ERROR_NOT_SUPPORTED; + } + + memset(ctx, 0, sizeof(*ctx)); + ctx->key = key_buffer; + ctx->key_length = key_buffer_size; + ctx->nonce = nonce; + ctx->nonce_length = nonce_length; + ctx->length_size = BEE_PSA_CCM_BLOCK_SIZE - 1U - nonce_length; + if (ctx->length_size < sizeof(length) && + length >= (UINT64_C(1) << (8U * ctx->length_size))) { + return PSA_ERROR_INVALID_ARGUMENT; + } + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_cipher_setup(bee_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, bool decrypt) { + psa_status_t status = + bee_psa_validate_key(attributes, key_buffer, key_buffer_size); + + if (status != PSA_SUCCESS) { + return status; + } + if (alg != PSA_ALG_CBC_NO_PADDING && alg != PSA_ALG_CBC_PKCS7 && + alg != PSA_ALG_CFB && alg != PSA_ALG_OFB && alg != PSA_ALG_CTR) { + return PSA_ERROR_NOT_SUPPORTED; + } + + memset(operation, 0, sizeof(*operation)); + memcpy(operation->key, key_buffer, key_buffer_size); + operation->key_length = key_buffer_size; + operation->algorithm = alg; + operation->decrypt = decrypt; + return PSA_SUCCESS; +} + +psa_status_t +bee_psa_cipher_encrypt_setup(bee_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg) { + return bee_psa_cipher_setup(operation, attributes, key_buffer, + key_buffer_size, alg, false); +} + +psa_status_t +bee_psa_cipher_decrypt_setup(bee_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg) { + return bee_psa_cipher_setup(operation, attributes, key_buffer, + key_buffer_size, alg, true); +} + +psa_status_t bee_psa_cipher_set_iv(bee_psa_cipher_operation_t *operation, + const uint8_t *iv, size_t iv_length) { + psa_status_t status = PSA_SUCCESS; + + if (operation == NULL || iv == NULL || iv_length != BEE_AES_BLOCK_SIZE || + operation->iv_set) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memcpy(operation->iv, iv, BEE_AES_BLOCK_SIZE); + if (operation->algorithm == PSA_ALG_CFB || + operation->algorithm == PSA_ALG_OFB || + operation->algorithm == PSA_ALG_CTR) { + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + status = bee_psa_ecb_crypt(operation->key, operation->key_length, + operation->iv, operation->stream, false); + bee_crypto_unlock(); + } + if (status == PSA_SUCCESS) { + operation->iv_set = 1U; + } + return status; +} + +static int bee_psa_cipher_cbc_block(bee_psa_cipher_operation_t *operation, + const uint8_t input[BEE_AES_BLOCK_SIZE], + uint8_t output[BEE_AES_BLOCK_SIZE]) { + uint8_t next_iv[BEE_AES_BLOCK_SIZE]; + int ret; + + if (operation->decrypt) { + memcpy(next_iv, input, sizeof(next_iv)); + } + ret = bee_aes_hw_crypt_block(operation->key, operation->key_length, + AES_MODE_CBC, input, output, operation->iv, + operation->decrypt); + if (ret != BEE_CRYPTO_SUCCESS) { + return ret; + } + memcpy(operation->iv, operation->decrypt ? next_iv : output, + BEE_AES_BLOCK_SIZE); + return BEE_CRYPTO_SUCCESS; +} + +static psa_status_t bee_psa_cipher_update_cbc_no_padding( + bee_psa_cipher_operation_t *operation, const uint8_t *input, + size_t input_length, uint8_t *output, size_t *output_length) { + size_t produced = 0U; + + while (input_length > 0U) { + size_t chunk = BEE_AES_BLOCK_SIZE - operation->buffer_length; + + if (chunk > input_length) { + chunk = input_length; + } + memcpy(&operation->buffer[operation->buffer_length], input, chunk); + operation->buffer_length += chunk; + input += chunk; + input_length -= chunk; + + if (operation->buffer_length == BEE_AES_BLOCK_SIZE) { + int ret = bee_psa_cipher_cbc_block(operation, operation->buffer, output); + + if (ret != BEE_CRYPTO_SUCCESS) { + return bee_psa_status(ret); + } + operation->buffer_length = 0U; + output += BEE_AES_BLOCK_SIZE; + produced += BEE_AES_BLOCK_SIZE; + } + } + *output_length = produced; + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_cipher_update_cbc_pkcs7( + bee_psa_cipher_operation_t *operation, const uint8_t *input, + size_t input_length, uint8_t *output, size_t *output_length) { + size_t produced = 0U; + + while (input_length > 0U) { + size_t chunk; + + if (operation->decrypt && + operation->buffer_length == BEE_AES_BLOCK_SIZE) { + int ret = bee_psa_cipher_cbc_block(operation, operation->buffer, output); + + if (ret != BEE_CRYPTO_SUCCESS) { + return bee_psa_status(ret); + } + operation->buffer_length = 0U; + output += BEE_AES_BLOCK_SIZE; + produced += BEE_AES_BLOCK_SIZE; + } + + chunk = BEE_AES_BLOCK_SIZE - operation->buffer_length; + if (chunk > input_length) { + chunk = input_length; + } + memcpy(&operation->buffer[operation->buffer_length], input, chunk); + operation->buffer_length += chunk; + input += chunk; + input_length -= chunk; + + if (!operation->decrypt && + operation->buffer_length == BEE_AES_BLOCK_SIZE) { + int ret = bee_psa_cipher_cbc_block(operation, operation->buffer, output); + + if (ret != BEE_CRYPTO_SUCCESS) { + return bee_psa_status(ret); + } + operation->buffer_length = 0U; + output += BEE_AES_BLOCK_SIZE; + produced += BEE_AES_BLOCK_SIZE; + } + } + *output_length = produced; + return PSA_SUCCESS; +} + +static void bee_psa_cipher_increment_counter(uint8_t counter[16]) { + for (int i = BEE_AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++counter[i] != 0U) { + break; + } + } +} + +static int bee_psa_cipher_next_stream(bee_psa_cipher_operation_t *operation) { + if (operation->algorithm == PSA_ALG_CFB) { + memcpy(operation->iv, operation->buffer, BEE_AES_BLOCK_SIZE); + } else if (operation->algorithm == PSA_ALG_OFB) { + memcpy(operation->iv, operation->stream, BEE_AES_BLOCK_SIZE); + } else { + bee_psa_cipher_increment_counter(operation->iv); + } + + operation->stream_used = 0U; + return bee_psa_ecb_crypt(operation->key, operation->key_length, + operation->iv, operation->stream, false) == PSA_SUCCESS + ? BEE_CRYPTO_SUCCESS + : BEE_CRYPTO_ERROR_HARDWARE; +} + +static psa_status_t bee_psa_cipher_update_stream( + bee_psa_cipher_operation_t *operation, const uint8_t *input, + size_t input_length, uint8_t *output, size_t *output_length) { + size_t produced = input_length; + + while (input_length > 0U) { + if (operation->stream_used == BEE_AES_BLOCK_SIZE) { + int ret = bee_psa_cipher_next_stream(operation); + + if (ret != BEE_CRYPTO_SUCCESS) { + return bee_psa_status(ret); + } + } + + if (operation->algorithm == PSA_ALG_CFB) { + uint8_t ciphertext; + + ciphertext = *input ^ operation->stream[operation->stream_used]; + operation->buffer[operation->stream_used] = + operation->decrypt ? *input : ciphertext; + *output = ciphertext; + } else { + *output = *input ^ operation->stream[operation->stream_used]; + } + operation->stream_used++; + input++; + output++; + input_length--; + } + *output_length = produced; + return PSA_SUCCESS; +} + +psa_status_t bee_psa_cipher_update(bee_psa_cipher_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length) { + psa_status_t status; + size_t required_size; + + if (operation == NULL || output_length == NULL || + (input_length > 0U && (input == NULL || output == NULL))) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (!operation->iv_set) { + return PSA_ERROR_BAD_STATE; + } + if (operation->algorithm == PSA_ALG_CBC_NO_PADDING) { + size_t available = operation->buffer_length + input_length; + + required_size = (available / BEE_AES_BLOCK_SIZE) * BEE_AES_BLOCK_SIZE; + } else if (operation->algorithm == PSA_ALG_CBC_PKCS7) { + size_t available = operation->buffer_length + input_length; + + if (operation->decrypt) { + required_size = available > BEE_AES_BLOCK_SIZE + ? ((available - 1U) / BEE_AES_BLOCK_SIZE) * + BEE_AES_BLOCK_SIZE + : 0U; + } else { + required_size = (available / BEE_AES_BLOCK_SIZE) * BEE_AES_BLOCK_SIZE; + } + } else if (operation->algorithm == PSA_ALG_CFB || + operation->algorithm == PSA_ALG_OFB || + operation->algorithm == PSA_ALG_CTR) { + required_size = input_length; + } else { + return PSA_ERROR_BAD_STATE; + } + if (output_size < required_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + if (input_length == 0U) { + *output_length = 0U; + return PSA_SUCCESS; + } + + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + if (operation->algorithm == PSA_ALG_CBC_NO_PADDING) { + status = bee_psa_cipher_update_cbc_no_padding( + operation, input, input_length, output, output_length); + } else if (operation->algorithm == PSA_ALG_CBC_PKCS7) { + status = bee_psa_cipher_update_cbc_pkcs7( + operation, input, input_length, output, output_length); + } else { + status = bee_psa_cipher_update_stream( + operation, input, input_length, output, output_length); + } + bee_crypto_unlock(); + return status; +} + +psa_status_t bee_psa_cipher_finish(bee_psa_cipher_operation_t *operation, + uint8_t *output, size_t output_size, + size_t *output_length) { + psa_status_t status = PSA_SUCCESS; + + if (operation == NULL || output_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + *output_length = 0U; + if (operation->algorithm == PSA_ALG_CBC_NO_PADDING) { + return operation->buffer_length == 0U ? PSA_SUCCESS + : PSA_ERROR_INVALID_ARGUMENT; + } + if (operation->algorithm != PSA_ALG_CBC_PKCS7) { + return operation->algorithm == PSA_ALG_CFB || + operation->algorithm == PSA_ALG_OFB || + operation->algorithm == PSA_ALG_CTR + ? PSA_SUCCESS + : PSA_ERROR_BAD_STATE; + } + if (operation->decrypt && operation->buffer_length != BEE_AES_BLOCK_SIZE) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (output_size < BEE_AES_BLOCK_SIZE) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + if (output == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + if (!operation->decrypt) { + uint8_t padding = BEE_AES_BLOCK_SIZE - operation->buffer_length; + + memset(&operation->buffer[operation->buffer_length], padding, padding); + status = bee_psa_status( + bee_psa_cipher_cbc_block(operation, operation->buffer, output)); + if (status == PSA_SUCCESS) { + *output_length = BEE_AES_BLOCK_SIZE; + } + } else { + uint8_t plaintext[BEE_AES_BLOCK_SIZE] = {0}; + uint8_t padding = 0U; + uint8_t diff = 0U; + + status = bee_psa_status( + bee_psa_cipher_cbc_block(operation, operation->buffer, plaintext)); + if (status == PSA_SUCCESS) { + padding = plaintext[BEE_AES_BLOCK_SIZE - 1U]; + for (size_t i = 0; i < BEE_AES_BLOCK_SIZE; i++) { + uint8_t mask = (uint8_t)-(i < padding); + + diff |= (plaintext[BEE_AES_BLOCK_SIZE - 1U - i] ^ padding) & mask; + } + if (padding == 0U || padding > BEE_AES_BLOCK_SIZE || diff != 0U) { + status = PSA_ERROR_INVALID_PADDING; + } + } + if (status == PSA_SUCCESS) { + *output_length = BEE_AES_BLOCK_SIZE - padding; + memcpy(output, plaintext, *output_length); + } + memset(plaintext, 0, sizeof(plaintext)); + } + bee_crypto_unlock(); + return status; +} + +psa_status_t bee_psa_cipher_abort(bee_psa_cipher_operation_t *operation) { + memset(operation, 0, sizeof(*operation)); + return PSA_SUCCESS; +} + +psa_status_t bee_psa_cipher_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *iv, size_t iv_length, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length) { + bee_psa_cipher_operation_t operation; + size_t update_length; + size_t finish_length; + psa_status_t status; + + if (output_length == NULL || (input_length > 0U && input == NULL) || + output == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (alg == PSA_ALG_ECB_NO_PADDING) { + status = bee_psa_validate_key(attributes, key_buffer, key_buffer_size); + if (status != PSA_SUCCESS) { + return status; + } + if (iv_length != 0U || input_length != BEE_AES_BLOCK_SIZE) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (output_size < BEE_AES_BLOCK_SIZE) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + status = bee_psa_ecb_crypt(key_buffer, key_buffer_size, input, output, false); + bee_crypto_unlock(); + if (status == PSA_SUCCESS) { + *output_length = BEE_AES_BLOCK_SIZE; + } + return status; + } + + status = bee_psa_cipher_encrypt_setup(&operation, attributes, key_buffer, + key_buffer_size, alg); + if (status != PSA_SUCCESS) { + return status; + } + status = bee_psa_cipher_set_iv(&operation, iv, iv_length); + if (status == PSA_SUCCESS) { + status = bee_psa_cipher_update(&operation, input, input_length, output, + output_size, &update_length); + } + if (status == PSA_SUCCESS) { + status = bee_psa_cipher_finish(&operation, output + update_length, + output_size - update_length, &finish_length); + } + if (status == PSA_SUCCESS) { + *output_length = update_length + finish_length; + } + bee_psa_cipher_abort(&operation); + return status; +} + +psa_status_t bee_psa_cipher_decrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length) { + bee_psa_cipher_operation_t operation; + size_t update_length; + size_t finish_length; + psa_status_t status; + + if (output_length == NULL || input == NULL || output == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (alg == PSA_ALG_ECB_NO_PADDING) { + status = bee_psa_validate_key(attributes, key_buffer, key_buffer_size); + if (status != PSA_SUCCESS) { + return status; + } + if (input_length != BEE_AES_BLOCK_SIZE) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (output_size < BEE_AES_BLOCK_SIZE) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + status = bee_psa_ecb_crypt(key_buffer, key_buffer_size, input, output, true); + bee_crypto_unlock(); + if (status == PSA_SUCCESS) { + *output_length = BEE_AES_BLOCK_SIZE; + } + return status; + } + if (input_length < BEE_AES_BLOCK_SIZE) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = bee_psa_cipher_decrypt_setup(&operation, attributes, key_buffer, + key_buffer_size, alg); + if (status != PSA_SUCCESS) { + return status; + } + status = bee_psa_cipher_set_iv(&operation, input, BEE_AES_BLOCK_SIZE); + if (status == PSA_SUCCESS) { + status = bee_psa_cipher_update( + &operation, input + BEE_AES_BLOCK_SIZE, input_length - BEE_AES_BLOCK_SIZE, + output, output_size, &update_length); + } + if (status == PSA_SUCCESS) { + status = bee_psa_cipher_finish(&operation, output + update_length, + output_size - update_length, &finish_length); + } + if (status == PSA_SUCCESS) { + *output_length = update_length + finish_length; + } + bee_psa_cipher_abort(&operation); + return status; +} + +psa_status_t +bee_psa_aead_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *plaintext, + size_t plaintext_length, uint8_t *ciphertext, + size_t ciphertext_size, size_t *ciphertext_length) { + struct bee_psa_ccm_context ctx; + size_t tag_length; + psa_status_t status = bee_psa_ccm_prepare( + &ctx, attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, + additional_data_length, plaintext_length, &tag_length); + + if (status != PSA_SUCCESS) { + return status; + } + if ((additional_data_length > 0U && additional_data == NULL) || + (plaintext_length > 0U && plaintext == NULL) || ciphertext == NULL || + ciphertext_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (ciphertext_size < plaintext_length + tag_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + status = bee_psa_ccm_tag(&ctx, additional_data, additional_data_length, + plaintext, plaintext_length, tag_length, + &ciphertext[plaintext_length]); + if (status == PSA_SUCCESS) { + status = bee_psa_ccm_crypt(&ctx, plaintext, plaintext_length, ciphertext); + } + bee_crypto_unlock(); + if (status == PSA_SUCCESS) { + *ciphertext_length = plaintext_length + tag_length; + } + return status; +} + +psa_status_t +bee_psa_aead_decrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *ciphertext, + size_t ciphertext_length, uint8_t *plaintext, + size_t plaintext_size, size_t *plaintext_length) { + struct bee_psa_ccm_context ctx; + uint8_t tag[BEE_PSA_CCM_BLOCK_SIZE]; + uint8_t diff = 0U; + size_t tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); + size_t payload_length; + psa_status_t status; + + if (tag_length > ciphertext_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + payload_length = ciphertext_length - tag_length; + status = bee_psa_ccm_prepare(&ctx, attributes, key_buffer, key_buffer_size, + alg, nonce, nonce_length, additional_data_length, + payload_length, &tag_length); + if (status != PSA_SUCCESS) { + return status; + } + if ((additional_data_length > 0U && additional_data == NULL) || + ciphertext == NULL || (payload_length > 0U && plaintext == NULL) || + plaintext_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (plaintext_size < payload_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + status = bee_psa_ccm_crypt(&ctx, ciphertext, payload_length, plaintext); + if (status == PSA_SUCCESS) { + status = bee_psa_ccm_tag(&ctx, additional_data, additional_data_length, + plaintext, payload_length, tag_length, tag); + } + bee_crypto_unlock(); + if (status != PSA_SUCCESS) { + memset(plaintext, 0, payload_length); + return status; + } + + for (size_t i = 0; i < tag_length; i++) { + diff |= tag[i] ^ ciphertext[payload_length + i]; + } + memset(tag, 0, sizeof(tag)); + if (diff != 0U) { + memset(plaintext, 0, payload_length); + return PSA_ERROR_INVALID_SIGNATURE; + } + + *plaintext_length = payload_length; + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_aead_setup(bee_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, bool decrypt) { + size_t tag_length; + psa_status_t status = + bee_psa_validate_key(attributes, key_buffer, key_buffer_size); + + if (status != PSA_SUCCESS) { + return status; + } + if (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0) != + PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0)) { + return PSA_ERROR_NOT_SUPPORTED; + } + tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); + if (tag_length < 4U || tag_length > BEE_PSA_CCM_BLOCK_SIZE || + (tag_length & 1U) != 0U) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memset(operation, 0, sizeof(*operation)); + memcpy(operation->key, key_buffer, key_buffer_size); + operation->key_length = key_buffer_size; + operation->tag_length = tag_length; + operation->decrypt = decrypt; + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_aead_mac_block(bee_psa_aead_operation_t *operation, + const uint8_t block[16]) { + uint8_t input[16]; + + for (size_t i = 0; i < sizeof(input); i++) { + input[i] = operation->mac[i] ^ block[i]; + } + return bee_psa_ecb_crypt(operation->key, operation->key_length, input, + operation->mac, false); +} + +static void bee_psa_aead_counter(bee_psa_aead_operation_t *operation, + uint64_t value) { + memset(operation->counter, 0, sizeof(operation->counter)); + operation->counter[0] = operation->length_size - 1U; + memcpy(&operation->counter[1], operation->nonce, operation->nonce_length); + for (size_t i = 0; i < operation->length_size; i++) { + operation->counter[15U - i] = (uint8_t)value; + value >>= 8; + } + operation->stream_used = sizeof(operation->stream); +} + +static void bee_psa_aead_counter_inc(bee_psa_aead_operation_t *operation) { + for (int i = 15; i >= 1 + (int)operation->nonce_length; i--) { + if (++operation->counter[i] != 0U) { + break; + } + } +} + +static psa_status_t +bee_psa_aead_process_b0(bee_psa_aead_operation_t *operation) { + psa_status_t status; + + if (operation->b0_processed) { + return PSA_SUCCESS; + } + + status = bee_psa_aead_mac_block(operation, operation->b0); + if (status == PSA_SUCCESS) { + operation->b0_processed = 1U; + } + return status; +} + +static psa_status_t +bee_psa_aead_finish_aad(bee_psa_aead_operation_t *operation) { + psa_status_t status; + + if (operation->aad_finished) { + return PSA_SUCCESS; + } + if (operation->aad_processed != operation->aad_length) { + return PSA_ERROR_BAD_STATE; + } + + status = bee_psa_aead_process_b0(operation); + if (status != PSA_SUCCESS) { + return status; + } + if (operation->aad_block_used != 0U) { + status = bee_psa_aead_mac_block(operation, operation->aad_block); + if (status != PSA_SUCCESS) { + return status; + } + } + operation->aad_finished = 1U; + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_aead_mac_update(bee_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length) { + while (input_length > 0U) { + size_t chunk = + sizeof(operation->payload_block) - operation->payload_block_used; + psa_status_t status; + + if (chunk > input_length) { + chunk = input_length; + } + memcpy(&operation->payload_block[operation->payload_block_used], input, + chunk); + operation->payload_block_used += chunk; + input += chunk; + input_length -= chunk; + if (operation->payload_block_used == sizeof(operation->payload_block)) { + status = bee_psa_aead_mac_block(operation, operation->payload_block); + if (status != PSA_SUCCESS) { + return status; + } + memset(operation->payload_block, 0, sizeof(operation->payload_block)); + operation->payload_block_used = 0U; + } + } + return PSA_SUCCESS; +} + +static psa_status_t bee_psa_aead_crypt(bee_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, uint8_t *output) { + while (input_length > 0U) { + if (operation->stream_used == sizeof(operation->stream)) { + psa_status_t status = + bee_psa_ecb_crypt(operation->key, operation->key_length, + operation->counter, operation->stream, false); + + if (status != PSA_SUCCESS) { + return status; + } + bee_psa_aead_counter_inc(operation); + operation->stream_used = 0U; + } + *output++ = *input++ ^ operation->stream[operation->stream_used++]; + input_length--; + } + return PSA_SUCCESS; +} + +psa_status_t bee_psa_aead_encrypt_setup(bee_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) { + return bee_psa_aead_setup(operation, attributes, key_buffer, key_buffer_size, + alg, false); +} + +psa_status_t bee_psa_aead_decrypt_setup(bee_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) { + return bee_psa_aead_setup(operation, attributes, key_buffer, key_buffer_size, + alg, true); +} + +psa_status_t bee_psa_aead_set_nonce(bee_psa_aead_operation_t *operation, + const uint8_t *nonce, size_t nonce_length) { + if (nonce == NULL || nonce_length < 7U || nonce_length > 13U) { + return PSA_ERROR_INVALID_ARGUMENT; + } + memcpy(operation->nonce, nonce, nonce_length); + operation->nonce_length = nonce_length; + operation->length_size = 15U - nonce_length; + operation->nonce_set = 1U; + return PSA_SUCCESS; +} + +psa_status_t bee_psa_aead_set_lengths(bee_psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) { + uint64_t length = plaintext_length; + + if (!operation->nonce_set) { + return PSA_ERROR_BAD_STATE; + } + if (ad_length >= 0xff00U) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (operation->length_size < sizeof(length) && + length >= (UINT64_C(1) << (8U * operation->length_size))) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + operation->aad_length = ad_length; + operation->payload_length = plaintext_length; + operation->b0[0] = (ad_length > 0U ? 0x40U : 0U) | + (((operation->tag_length - 2U) / 2U) << 3) | + (operation->length_size - 1U); + memcpy(&operation->b0[1], operation->nonce, operation->nonce_length); + for (size_t i = 0; i < operation->length_size; i++) { + operation->b0[15U - i] = (uint8_t)length; + length >>= 8; + } + + if (ad_length > 0U) { + operation->aad_block[0] = (uint8_t)(ad_length >> 8); + operation->aad_block[1] = (uint8_t)ad_length; + operation->aad_block_used = 2U; + } + bee_psa_aead_counter(operation, 1U); + operation->lengths_set = 1U; + return PSA_SUCCESS; +} + +psa_status_t bee_psa_aead_update_ad(bee_psa_aead_operation_t *operation, + const uint8_t *input, size_t input_length) { + psa_status_t status = PSA_SUCCESS; + + if (!operation->lengths_set || operation->payload_processed != 0U || + input_length > operation->aad_length - operation->aad_processed || + (input_length > 0U && input == NULL)) { + return PSA_ERROR_BAD_STATE; + } + + while (input_length > 0U) { + size_t chunk = sizeof(operation->aad_block) - operation->aad_block_used; + + if (chunk > input_length) { + chunk = input_length; + } + memcpy(&operation->aad_block[operation->aad_block_used], input, chunk); + operation->aad_block_used += chunk; + operation->aad_processed += chunk; + input += chunk; + input_length -= chunk; + + if (operation->aad_block_used == sizeof(operation->aad_block)) { + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + status = bee_psa_aead_process_b0(operation); + if (status == PSA_SUCCESS) { + status = bee_psa_aead_mac_block(operation, operation->aad_block); + } + bee_crypto_unlock(); + if (status != PSA_SUCCESS) { + return status; + } + memset(operation->aad_block, 0, sizeof(operation->aad_block)); + operation->aad_block_used = 0U; + } + } + return status; +} + +static psa_status_t +bee_psa_aead_finalize_tag(bee_psa_aead_operation_t *operation) { + uint8_t counter[16]; + uint8_t s0[16]; + psa_status_t status; + + if (operation->tag_ready) { + return PSA_SUCCESS; + } + status = bee_psa_aead_finish_aad(operation); + if (status == PSA_SUCCESS && operation->payload_block_used != 0U) { + status = bee_psa_aead_mac_block(operation, operation->payload_block); + } + if (status == PSA_SUCCESS) { + bee_psa_aead_counter(operation, 0U); + memcpy(counter, operation->counter, sizeof(counter)); + status = bee_psa_ecb_crypt(operation->key, operation->key_length, counter, + s0, false); + } + if (status == PSA_SUCCESS) { + for (size_t i = 0; i < operation->tag_length; i++) { + operation->tag[i] = operation->mac[i] ^ s0[i]; + } + operation->tag_ready = 1U; + } + return status; +} + +psa_status_t bee_psa_aead_update(bee_psa_aead_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length) { + psa_status_t status; + + if (!operation->lengths_set || + input_length > operation->payload_length - operation->payload_processed || + (input_length > 0U && (input == NULL || output == NULL)) || + output_length == NULL) { + return PSA_ERROR_BAD_STATE; + } + if (output_size < input_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + + status = bee_psa_aead_finish_aad(operation); + if (status == PSA_SUCCESS && !operation->decrypt) { + status = bee_psa_aead_mac_update(operation, input, input_length); + } + if (status == PSA_SUCCESS) { + status = bee_psa_aead_crypt(operation, input, input_length, output); + } + if (status == PSA_SUCCESS && operation->decrypt) { + status = bee_psa_aead_mac_update(operation, output, input_length); + } + if (status == PSA_SUCCESS && operation->payload_processed + input_length == + operation->payload_length) { + status = bee_psa_aead_finalize_tag(operation); + } + bee_crypto_unlock(); + + if (status == PSA_SUCCESS) { + operation->payload_processed += input_length; + *output_length = input_length; + } + return status; +} + +psa_status_t bee_psa_aead_finish(bee_psa_aead_operation_t *operation, + uint8_t *ciphertext, size_t ciphertext_size, + size_t *ciphertext_length, uint8_t *tag, + size_t tag_size, size_t *tag_length) { + psa_status_t status = PSA_SUCCESS; + + if (operation->payload_processed != operation->payload_length || + tag == NULL || ciphertext_length == NULL || tag_length == NULL || + tag_size < operation->tag_length) { + return PSA_ERROR_BAD_STATE; + } + (void)ciphertext; + (void)ciphertext_size; + + if (!operation->tag_ready) { + if (bee_crypto_lock() != BEE_CRYPTO_SUCCESS) { + return PSA_ERROR_HARDWARE_FAILURE; + } + status = bee_psa_aead_finalize_tag(operation); + bee_crypto_unlock(); + } + if (status == PSA_SUCCESS) { + memcpy(tag, operation->tag, operation->tag_length); + *ciphertext_length = 0U; + *tag_length = operation->tag_length; + } + return status; +} + +psa_status_t bee_psa_aead_verify(bee_psa_aead_operation_t *operation, + uint8_t *plaintext, size_t plaintext_size, + size_t *plaintext_length, const uint8_t *tag, + size_t tag_length) { + uint8_t calculated[16]; + uint8_t diff = 0U; + size_t calculated_length; + size_t finish_length; + psa_status_t status; + + if (tag == NULL || tag_length != operation->tag_length || + plaintext_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + status = + bee_psa_aead_finish(operation, plaintext, plaintext_size, &finish_length, + calculated, sizeof(calculated), &calculated_length); + if (status != PSA_SUCCESS) { + return status; + } + for (size_t i = 0; i < tag_length; i++) { + diff |= calculated[i] ^ tag[i]; + } + memset(calculated, 0, sizeof(calculated)); + if (diff != 0U) { + return PSA_ERROR_INVALID_SIGNATURE; + } + *plaintext_length = finish_length; + return PSA_SUCCESS; +} + +psa_status_t bee_psa_aead_abort(bee_psa_aead_operation_t *operation) { + memset(operation, 0, sizeof(*operation)); + return PSA_SUCCESS; +} diff --git a/bee/ld/rtl8752h/ROM.ld b/bee/ld/rtl8752h/ROM.ld index dc2497ff..e27c1596 100644 --- a/bee/ld/rtl8752h/ROM.ld +++ b/bee/ld/rtl8752h/ROM.ld @@ -38,6 +38,10 @@ SECTIONS PROVIDE(LogUartDMAIdleHook = 0x00004449); PROVIDE(log_pm_check = 0x000044b7); PROVIDE(hw_aes_create_mutex = 0x00004561); + PROVIDE(hw_aes_encrypt128 = 0x00004639); + PROVIDE(hw_aes_decrypt128 = 0x00004671); + PROVIDE(hw_aes_encrypt256 = 0x000046a1); + PROVIDE(hw_aes_decrypt256 = 0x000046d7); PROVIDE(hw_aes_encrypt128_use_dma = 0x0000470d); PROVIDE(hw_aes_decrypt128_use_dma = 0x00004751); PROVIDE(swap_buf = 0x00004795); diff --git a/bee/ld/rtl87x2g/ROM_S.ld b/bee/ld/rtl87x2g/ROM_S.ld index 7aaf65f7..f4fe50d0 100644 --- a/bee/ld/rtl87x2g/ROM_S.ld +++ b/bee/ld/rtl87x2g/ROM_S.ld @@ -3,6 +3,10 @@ SECTIONS PROVIDE(Peripheral_Handler = 0x00003705); PROVIDE(WDG_Enable = 0x000040b1); PROVIDE(flash_nor_set_all_info = 0x0000aa79); + PROVIDE(hw_aes_decrypt128 = 0x0000cd31); + PROVIDE(hw_aes_decrypt256 = 0x0000cd4d); + PROVIDE(hw_aes_encrypt128 = 0x0000d025); + PROVIDE(hw_aes_encrypt256 = 0x0000d041); PROVIDE(swap_buf = 0x0001776f); PROVIDE(get_occd_addr = 0x0001bf89); PROVIDE(get_occd_size = 0x0001bf91); @@ -58,6 +62,12 @@ SECTIONS PROVIDE(hw_sha256_cpu_update = 0x0001c2f9); PROVIDE(hw_sha256_finish = 0x0001c301); PROVIDE(hw_sha256 = 0x0001c309); + PROVIDE(hw_pke_clock = 0x0001c311); + PROVIDE(hw_pke_init = 0x0001c319); + PROVIDE(hw_ecc_init = 0x0001c349); + PROVIDE(hw_ecc_set_sub_operand = 0x0001c351); + PROVIDE(hw_ecc_set_all_operands = 0x0001c359); + PROVIDE(hw_ecc_compute = 0x0001c361); PROVIDE(secure_app_function_call = 0x0001c3b9); PROVIDE(secure_function_call = 0x0001c3c1); PROVIDE(set_secure_func_ptr = 0x0001c3c9); From 23f43c7d601e32af93549e841662623c3c36ef5b Mon Sep 17 00:00:00 2001 From: Zhiyuan Tang Date: Wed, 19 Aug 2026 17:05:45 +0800 Subject: [PATCH 2/2] drivers: crypto: bee: add RTL87x2J AES and SHA-224/256 HW support RTL87x2J exposes AES (ECB/CBC) and SHA (SHA-224, SHA-256) through a different ROM API than other Bee SoC series. Extend the PSA hardware accelerator driver to support RTL87x2J across all layers: bee/drivers/crypto/inc/rtl87x2j/ Add vendor header files for the RTL87x2J AES and SHA2 ROM driver: aes_interface.h, sha2_interface.h, aes_dma_types.h. CMakeLists.txt Include the above directory when building for SOC_SERIES_RTL87X2J. crypto_bee_psa_adapter.h / .c - Introduce bee_aes_mode_t to abstract AES_WORK_MODE (RTL87x2J) vs T_HW_AES_MODE (other series) and matching BEE_AES_MODE_CBC/ECB aliases so call sites are SoC-family-agnostic. - Add a dedicated RTL87x2J path in bee_aes_hw_crypt_block() that drives the aes_encrypt()/aes_decrypt() ROM functions and clears the hardware busy flag via AES_BASE after each operation. - Rename the one-shot hash entry point to bee_sha2_hw_compute() and add a hash_length parameter to support both SHA-224 (28 B) and SHA-256 (32 B). - Add bee_sha2_hw_start/update/finish() multipart API for RTL87x2J, backed by sha2_iv_init(), sha2_cpu_update(), and sha2_finish(); a restore helper re-seeds the hardware IV register from the saved SHA2_CTX on each call so context switching is safe. crypto_bee_psa_types.h Use SHA2_CTX as the internal context type for RTL87x2J (selected via CONFIG_SOC_SERIES_RTL87X2J); retain HW_SHA256_CTX for other series. crypto_bee_psa.c - Extend bee_psa_hash_compute/setup/update/finish/clone to accept PSA_ALG_SHA_224 on RTL87x2J in addition to PSA_ALG_SHA_256. - Derive required_size from PSA_HASH_LENGTH(alg) instead of hard-coding the SHA-256 length, so SHA-224 output is sized correctly. - Use BEE_AES_MODE_ECB/CBC aliases in cipher paths to remain portable across SoC families. bee/ld/rtl87x2j/bootloader.ld Add PROVIDE() entries for all AES ROM symbols (aes_cmac, aes_cpu_operate, aes_decrypt, aes_dma_*, aes_encrypt, aes_init) and SHA2 ROM symbols (sha2, sha2_cpu_finish, sha2_cpu_update, sha2_dma_*, sha2_get_digest*, sha2_init, sha2_iv_init, sha2_start) required by the crypto driver at link time. Co-Authored-By: Claude --- bee/drivers/crypto/CMakeLists.txt | 1 + .../crypto/inc/rtl87x2j/aes_dma_types.h | 23 +++ .../crypto/inc/rtl87x2j/aes_interface.h | 104 +++++++++++ .../crypto/inc/rtl87x2j/sha2_interface.h | 69 ++++++++ .../psa/adapter/inc/crypto_bee_psa_adapter.h | 28 ++- .../psa/adapter/src/crypto_bee_psa_adapter.c | 167 +++++++++++++++++- .../crypto/psa/inc/crypto_bee_psa_types.h | 9 + bee/drivers/crypto/psa/src/crypto_bee_psa.c | 61 ++++++- bee/ld/rtl87x2j/bootloader.ld | 19 ++ 9 files changed, 466 insertions(+), 15 deletions(-) create mode 100644 bee/drivers/crypto/inc/rtl87x2j/aes_dma_types.h create mode 100644 bee/drivers/crypto/inc/rtl87x2j/aes_interface.h create mode 100644 bee/drivers/crypto/inc/rtl87x2j/sha2_interface.h diff --git a/bee/drivers/crypto/CMakeLists.txt b/bee/drivers/crypto/CMakeLists.txt index 7864ae5d..616ccd18 100644 --- a/bee/drivers/crypto/CMakeLists.txt +++ b/bee/drivers/crypto/CMakeLists.txt @@ -3,5 +3,6 @@ zephyr_include_directories_ifdef(CONFIG_SOC_SERIES_RTL87X2G inc/rtl87x2g) zephyr_include_directories_ifdef(CONFIG_SOC_SERIES_RTL8752H inc/rtl8752h) +zephyr_include_directories_ifdef(CONFIG_SOC_SERIES_RTL87X2J inc/rtl87x2j) add_subdirectory_ifdef(CONFIG_CRYPTO_BEE_PSA_ACCELERATOR psa) diff --git a/bee/drivers/crypto/inc/rtl87x2j/aes_dma_types.h b/bee/drivers/crypto/inc/rtl87x2j/aes_dma_types.h new file mode 100644 index 00000000..7247d336 --- /dev/null +++ b/bee/drivers/crypto/inc/rtl87x2j/aes_dma_types.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2026, Realtek Semiconductor Corporation + * + * SPDX-License-Identifier: LicenseRef-Realtek-5-Clause + */ + +#ifndef __AES_DMA_TYPES_H +#define __AES_DMA_TYPES_H + +#include + +typedef void (*AES_DMA_CB)(void *); +typedef void (*AES_DMA_ISR)(void); + +typedef struct AES_DMA_CFG +{ + uint8_t dma_ch_num; + AES_DMA_ISR dma_isr; + AES_DMA_CB cb; + void *cb_param; +} AES_DMA_CFG; + +#endif /* __AES_DMA_TYPES_H */ diff --git a/bee/drivers/crypto/inc/rtl87x2j/aes_interface.h b/bee/drivers/crypto/inc/rtl87x2j/aes_interface.h new file mode 100644 index 00000000..5a9900b1 --- /dev/null +++ b/bee/drivers/crypto/inc/rtl87x2j/aes_interface.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2026, Realtek Semiconductor Corporation + * + * SPDX-License-Identifier: LicenseRef-Realtek-5-Clause + */ + +#ifndef __AES_INTERFACE_H +#define __AES_INTERFACE_H +// *INDENT-OFF* +#ifdef __cplusplus +extern "C" { +#endif +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include "aes_dma_types.h" + +#define AES_SUPPORT_DMA_MODE 1 +#define AES_SUPPORT_CMAC 1 + +typedef enum +{ + AES_NONE, + AES_CBC = 0x1, + AES_ECB = 0x2, + AES_CFB = 0x3, + AES_OFB = 0x4, + AES_CTR_IV_64BITS_MSB = 0x5, + AES_CTR_IV_96BITS_MSB = 0x15, + AES_CTR_IV_64BITS_LSB = 0x25, + AES_CTR_IV_96BITS_LSB = 0x35, + AES_CIPHER_MAC = 0x6, +} AES_WORK_MODE; + +typedef enum +{ + AES_KEY_IRK = 0, + AES_KEY2 = 1, + AES_KEY3 = 2, + AES_KEY4 = 3, + AES_KEY5 = 4, + AES_HIDDEN_KEY, + AES_KEY_MAX, +} AES_KEY_SEL; + +typedef enum +{ + AES_KEY_BITS_128 = 128, + AES_KEY_BITS_256 = 256, +} AES_KEY_BITS_SEL; + +typedef struct +{ + uint32_t *key; + AES_KEY_BITS_SEL key_bits; + AES_KEY_SEL key_sel; +} AES_KEY_CFG; + +typedef enum +{ + AES_CPU_MODE = 0, + AES_DMA_MODE = 1, +} AES_ACCESS_MODE; + +typedef struct +{ + uint32_t *input; + uint32_t *iv; + uint32_t byte_len; + AES_WORK_MODE aes_mode; + AES_ACCESS_MODE access_mode; +#if AES_SUPPORT_DMA_MODE == 1 + AES_DMA_CFG *dma_rx_cfg; + AES_DMA_CFG *dma_tx_cfg; +#endif +} AES_CFG; + +void aes_init(AES_WORK_MODE aes_mode, const uint32_t *iv, AES_KEY_CFG *key_cfg); +bool aes_cpu_operate(const uint32_t *in, uint32_t *out, uint32_t word_len, bool isEncrypt); +bool aes_encrypt(AES_CFG *aes_config, AES_KEY_CFG *key_cfg, uint32_t *ciphertext); +bool aes_decrypt(AES_CFG *aes_config, AES_KEY_CFG *key_cfg, uint32_t *plaintext); + +#if AES_SUPPORT_DMA_MODE == 1 +void aes_dma_channel_init(AES_DMA_CFG *rx_cfg, AES_DMA_CFG *tx_cfg); +bool aes_dma_operate(const uint32_t *in, uint32_t *out, uint32_t word_len, bool isEncrypt); +bool aes_dma_done(void); +#endif + +#if AES_SUPPORT_CMAC == 1 +typedef struct +{ + uint8_t *input; + uint32_t byte_len; + AES_ACCESS_MODE access_mode; + AES_DMA_CFG *dma_rx_cfg; +} AES_CMAC_CFG; + +bool aes_cmac(AES_CMAC_CFG *cmac_config, AES_KEY_CFG *key_cfg, uint32_t *cmac); +#endif + +#ifdef __cplusplus +} +#endif +#endif /*__AES_INTERFACE_H*/ diff --git a/bee/drivers/crypto/inc/rtl87x2j/sha2_interface.h b/bee/drivers/crypto/inc/rtl87x2j/sha2_interface.h new file mode 100644 index 00000000..a2b22ae1 --- /dev/null +++ b/bee/drivers/crypto/inc/rtl87x2j/sha2_interface.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026, Realtek Semiconductor Corporation + * + * SPDX-License-Identifier: LicenseRef-Realtek-5-Clause + */ + +#ifndef __SHA2_INTERFACE_H +#define __SHA2_INTERFACE_H +// *INDENT-OFF* +#ifdef __cplusplus +extern "C" { +#endif +/* Includes ------------------------------------------------------------------*/ +#include +#include + +#define SHA2_SUPPORT_DMA_MODE 1 +#define SHA2_DMA_CH_NUM 2U + +typedef enum +{ + SHA2_DMA_MODE = 0, + SHA2_CPU_MODE = 1, +} SHA2_ACCESS_MODE; + +typedef enum +{ + SHA2_224, + SHA2_256, + SHA2_ALGO_MAX, +} SHA2_ALGO; + +typedef struct +{ + uint32_t total[2]; + uint32_t state[8]; + uint8_t buffer[64]; + SHA2_ALGO algo; +} SHA2_CTX; + +typedef struct +{ + uint8_t *input; + uint32_t byte_len; + SHA2_ALGO algo; + SHA2_ACCESS_MODE access_mode; + uint8_t dma_ch_num; +} SHA2_CFG; + +void sha2_init(void); +void sha2_start(SHA2_CTX *ctx, SHA2_ALGO algo); +bool sha2_cpu_update(SHA2_CTX *ctx, const uint8_t *input, uint32_t byte_len); +bool sha2_cpu_finish(SHA2_CTX *ctx, uint32_t *output); +uint32_t sha2_get_digest_len(SHA2_ALGO algo); +void sha2_iv_init(SHA2_ALGO algo, uint32_t *iv); +void sha2_get_digest(SHA2_ALGO algo, uint32_t *output); + +#if SHA2_SUPPORT_DMA_MODE == 1 +void sha2_dma_channel_init(uint8_t dma_rx_ch_num); +bool sha2_dma_update(SHA2_CTX *ctx, const uint8_t *input, uint32_t byte_len); +bool sha2_dma_finish(SHA2_CTX *ctx, uint32_t *output); +#endif + +bool sha2(SHA2_CFG *sha2_config, uint32_t *result); + +#ifdef __cplusplus +} +#endif +#endif /*__SHA2_INTERFACE_H*/ diff --git a/bee/drivers/crypto/psa/adapter/inc/crypto_bee_psa_adapter.h b/bee/drivers/crypto/psa/adapter/inc/crypto_bee_psa_adapter.h index 55602f7a..d2cffe01 100644 --- a/bee/drivers/crypto/psa/adapter/inc/crypto_bee_psa_adapter.h +++ b/bee/drivers/crypto/psa/adapter/inc/crypto_bee_psa_adapter.h @@ -11,7 +11,10 @@ #include #include -#if defined(BEE_CRYPTO_RTL87X2G) +#if defined(CONFIG_SOC_SERIES_RTL87X2J) +#include +#include +#elif defined(BEE_CRYPTO_RTL87X2G) #include #elif defined(BEE_CRYPTO_RTL8752H) #include @@ -20,6 +23,16 @@ #error "Unsupported Realtek Bee SoC" #endif +#if defined(CONFIG_SOC_SERIES_RTL87X2J) +typedef AES_WORK_MODE bee_aes_mode_t; +#define BEE_AES_MODE_CBC AES_CBC +#define BEE_AES_MODE_ECB AES_ECB +#else +typedef T_HW_AES_MODE bee_aes_mode_t; +#define BEE_AES_MODE_CBC AES_MODE_CBC +#define BEE_AES_MODE_ECB AES_MODE_ECB +#endif + #ifdef __cplusplus extern "C" { #endif @@ -46,15 +59,22 @@ int bee_crypto_lock(void); void bee_crypto_unlock(void); int bee_aes_hw_crypt_block(const uint8_t *key, size_t key_len, - T_HW_AES_MODE mode, const uint8_t *in, uint8_t *out, + bee_aes_mode_t mode, const uint8_t *in, uint8_t *out, const uint8_t *iv, bool decrypt); -int bee_sha256_hw_compute(const uint8_t *input, size_t input_length, - uint8_t *hash); +int bee_sha2_hw_compute(const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_length); +#if defined(CONFIG_SOC_SERIES_RTL87X2J) +int bee_sha2_hw_start(SHA2_CTX *ctx, SHA2_ALGO algorithm); +int bee_sha2_hw_update(SHA2_CTX *ctx, const uint8_t *input, + size_t input_length); +int bee_sha2_hw_finish(SHA2_CTX *ctx, uint8_t *hash, size_t hash_length); +#else int bee_sha256_hw_start(HW_SHA256_CTX *ctx); int bee_sha256_hw_update(HW_SHA256_CTX *ctx, const uint8_t *input, size_t input_length); int bee_sha256_hw_finish(HW_SHA256_CTX *ctx, uint8_t *hash); +#endif int bee_ecc_p256_enable(void); void bee_ecc_p256_disable(void); diff --git a/bee/drivers/crypto/psa/adapter/src/crypto_bee_psa_adapter.c b/bee/drivers/crypto/psa/adapter/src/crypto_bee_psa_adapter.c index 8fff35b9..76ed09a5 100644 --- a/bee/drivers/crypto/psa/adapter/src/crypto_bee_psa_adapter.c +++ b/bee/drivers/crypto/psa/adapter/src/crypto_bee_psa_adapter.c @@ -8,6 +8,10 @@ #include #include +#if defined(CONFIG_SOC_SERIES_RTL87X2J) +#include +#endif + #define BEE_CRYPTO_WAIT_FOREVER UINT32_MAX static void *bee_crypto_mutex; @@ -37,6 +41,50 @@ void bee_crypto_unlock(void) { } } +#if defined(CONFIG_SOC_SERIES_RTL87X2J) +int bee_aes_hw_crypt_block(const uint8_t *key, size_t key_len, + bee_aes_mode_t mode, const uint8_t *in, uint8_t *out, + const uint8_t *iv, bool decrypt) { + uint32_t in_hw[BEE_AES_BLOCK_SIZE / sizeof(uint32_t)]; + uint32_t out_hw[BEE_AES_BLOCK_SIZE / sizeof(uint32_t)]; + uint32_t key_hw[32U / sizeof(uint32_t)]; + uint32_t iv_hw[BEE_AES_BLOCK_SIZE / sizeof(uint32_t)]; + AES_CFG aes_config = {0}; + AES_KEY_CFG key_config = {0}; + bool ret; + + if (key == NULL || in == NULL || out == NULL || + (key_len != 16U && key_len != 32U) || + (mode != BEE_AES_MODE_ECB && (mode != BEE_AES_MODE_CBC || iv == NULL))) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + memcpy(in_hw, in, BEE_AES_BLOCK_SIZE); + memcpy(key_hw, key, key_len); + if (iv != NULL) { + memcpy(iv_hw, iv, BEE_AES_BLOCK_SIZE); + } + + aes_config.input = in_hw; + aes_config.iv = iv == NULL ? NULL : iv_hw; + aes_config.byte_len = BEE_AES_BLOCK_SIZE; + aes_config.aes_mode = mode; + aes_config.access_mode = AES_CPU_MODE; + key_config.key = key_hw; + key_config.key_bits = key_len == 16U ? AES_KEY_BITS_128 : AES_KEY_BITS_256; + key_config.key_sel = AES_KEY_IRK; + + ret = decrypt ? aes_decrypt(&aes_config, &key_config, out_hw) + : aes_encrypt(&aes_config, &key_config, out_hw); + *(volatile uint32_t *)AES_BASE &= decrypt ? ~0x2U : ~0x1U; + if (!ret) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + + memcpy(out, out_hw, BEE_AES_BLOCK_SIZE); + return BEE_CRYPTO_SUCCESS; +} +#else static void bee_aes_copy_to_hw(const uint8_t *src, uint32_t *dst, size_t len) { #if defined(BEE_CRYPTO_RTL8752H) swap_buf(src, (uint8_t *)dst, (uint16_t)len); @@ -55,7 +103,7 @@ static void bee_aes_copy_from_hw(const uint32_t *src, uint8_t *dst, } int bee_aes_hw_crypt_block(const uint8_t *key, size_t key_len, - T_HW_AES_MODE mode, const uint8_t *in, uint8_t *out, + bee_aes_mode_t mode, const uint8_t *in, uint8_t *out, const uint8_t *iv, bool decrypt) { uint32_t in_hw[BEE_AES_BLOCK_SIZE / sizeof(uint32_t)]; uint32_t out_hw[BEE_AES_BLOCK_SIZE / sizeof(uint32_t)]; @@ -99,9 +147,118 @@ int bee_aes_hw_crypt_block(const uint8_t *key, size_t key_len, bee_aes_copy_from_hw(out_hw, out, BEE_AES_BLOCK_SIZE); return BEE_CRYPTO_SUCCESS; } +#endif + +#if defined(CONFIG_SOC_SERIES_RTL87X2J) +int bee_sha2_hw_compute(const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_length) { + uint32_t result[8]; + uint8_t empty = 0U; + SHA2_CFG sha2_config = {0}; + int status; + bool ret; + + if ((input == NULL && input_length != 0U) || hash == NULL || + input_length > UINT32_MAX || (hash_length != 28U && hash_length != 32U)) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + sha2_config.input = input_length == 0U ? &empty : (uint8_t *)input; + sha2_config.byte_len = (uint32_t)input_length; + sha2_config.algo = hash_length == 28U ? SHA2_224 : SHA2_256; + sha2_config.access_mode = SHA2_CPU_MODE; + + status = bee_crypto_lock(); + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + ret = sha2(&sha2_config, result); + bee_crypto_unlock(); + + if (!ret) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + memcpy(hash, result, hash_length); + return BEE_CRYPTO_SUCCESS; +} + +static void bee_sha2_hw_restore(const SHA2_CTX *ctx) { + uint32_t *state = NULL; + + sha2_init(); + if (ctx->total[0] >= sizeof(ctx->buffer) || ctx->total[1] != 0U) { + state = (uint32_t *)ctx->state; + } + sha2_iv_init(ctx->algo, state); +} + +int bee_sha2_hw_start(SHA2_CTX *ctx, SHA2_ALGO algorithm) { + int status; + + if (ctx == NULL || (algorithm != SHA2_224 && algorithm != SHA2_256)) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + status = bee_crypto_lock(); + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + sha2_init(); + sha2_start(ctx, algorithm); + bee_crypto_unlock(); + return BEE_CRYPTO_SUCCESS; +} + +int bee_sha2_hw_update(SHA2_CTX *ctx, const uint8_t *input, + size_t input_length) { + int status; + bool ret; + + if (ctx == NULL || (input == NULL && input_length != 0U) || + input_length > UINT32_MAX) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + if (input_length == 0U) { + return BEE_CRYPTO_SUCCESS; + } + + status = bee_crypto_lock(); + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + bee_sha2_hw_restore(ctx); + ret = sha2_cpu_update(ctx, input, (uint32_t)input_length); + bee_crypto_unlock(); + return ret ? BEE_CRYPTO_SUCCESS : BEE_CRYPTO_ERROR_HARDWARE; +} + +int bee_sha2_hw_finish(SHA2_CTX *ctx, uint8_t *hash, size_t hash_length) { + uint32_t result[8]; + int status; + bool ret; + + if (ctx == NULL || hash == NULL || + (hash_length != 28U && hash_length != 32U)) { + return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; + } + + status = bee_crypto_lock(); + if (status != BEE_CRYPTO_SUCCESS) { + return status; + } + bee_sha2_hw_restore(ctx); + ret = sha2_cpu_finish(ctx, result); + bee_crypto_unlock(); -int bee_sha256_hw_compute(const uint8_t *input, size_t input_length, - uint8_t *hash) { + if (!ret) { + return BEE_CRYPTO_ERROR_HARDWARE; + } + memcpy(hash, result, hash_length); + return BEE_CRYPTO_SUCCESS; +} +#else +int bee_sha2_hw_compute(const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_length) { uint32_t result[8]; uint8_t empty = 0U; int status; @@ -111,6 +268,9 @@ int bee_sha256_hw_compute(const uint8_t *input, size_t input_length, input_length > UINT32_MAX) { return BEE_CRYPTO_ERROR_INVALID_ARGUMENT; } + if (hash_length != sizeof(result)) { + return BEE_CRYPTO_ERROR_NOT_SUPPORTED; + } status = bee_crypto_lock(); if (status != BEE_CRYPTO_SUCCESS) { @@ -188,6 +348,7 @@ int bee_sha256_hw_finish(HW_SHA256_CTX *ctx, uint8_t *hash) { memcpy(hash, result, sizeof(result)); return BEE_CRYPTO_SUCCESS; } +#endif #if defined(BEE_CRYPTO_RTL87X2G) #define BEE_PKE_MMEM_ADDR 0x50090000U diff --git a/bee/drivers/crypto/psa/inc/crypto_bee_psa_types.h b/bee/drivers/crypto/psa/inc/crypto_bee_psa_types.h index 7bfdfafe..9b3dd496 100644 --- a/bee/drivers/crypto/psa/inc/crypto_bee_psa_types.h +++ b/bee/drivers/crypto/psa/inc/crypto_bee_psa_types.h @@ -15,14 +15,23 @@ #include #elif defined(BEE_CRYPTO_RTL8752H) #include +#elif defined(CONFIG_SOC_SERIES_RTL87X2J) +#include #else #error "Unsupported Realtek Bee SoC" #endif +#if defined(CONFIG_SOC_SERIES_RTL87X2J) +typedef struct { + SHA2_CTX context; + psa_algorithm_t algorithm; +} bee_psa_hash_operation_t; +#else typedef struct { HW_SHA256_CTX context; psa_algorithm_t algorithm; } bee_psa_hash_operation_t; +#endif typedef struct { uint8_t key[32]; diff --git a/bee/drivers/crypto/psa/src/crypto_bee_psa.c b/bee/drivers/crypto/psa/src/crypto_bee_psa.c index 6d7b2686..9280cb07 100644 --- a/bee/drivers/crypto/psa/src/crypto_bee_psa.c +++ b/bee/drivers/crypto/psa/src/crypto_bee_psa.c @@ -40,7 +40,11 @@ psa_status_t bee_psa_init(void) { return PSA_ERROR_HARDWARE_FAILURE; } +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + sha2_init(); +#else hw_sha256_init(); +#endif return PSA_SUCCESS; } @@ -60,12 +64,17 @@ static psa_status_t bee_psa_status(int status) { psa_status_t bee_psa_hash_compute(psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length) { - size_t required_size = PSA_HASH_LENGTH(PSA_ALG_SHA_256); + size_t required_size; psa_status_t status; +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + if (alg != PSA_ALG_SHA_224 && alg != PSA_ALG_SHA_256) { +#else if (alg != PSA_ALG_SHA_256) { +#endif return PSA_ERROR_NOT_SUPPORTED; } + required_size = PSA_HASH_LENGTH(alg); if ((input == NULL && input_length != 0U) || hash_length == NULL) { return PSA_ERROR_INVALID_ARGUMENT; } @@ -76,7 +85,8 @@ psa_status_t bee_psa_hash_compute(psa_algorithm_t alg, const uint8_t *input, return PSA_ERROR_INVALID_ARGUMENT; } - status = bee_psa_status(bee_sha256_hw_compute(input, input_length, hash)); + status = bee_psa_status( + bee_sha2_hw_compute(input, input_length, hash, required_size)); if (status == PSA_SUCCESS) { *hash_length = required_size; } @@ -90,12 +100,21 @@ psa_status_t bee_psa_hash_setup(bee_psa_hash_operation_t *operation, if (operation == NULL) { return PSA_ERROR_INVALID_ARGUMENT; } +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + if (alg != PSA_ALG_SHA_224 && alg != PSA_ALG_SHA_256) { +#else if (alg != PSA_ALG_SHA_256) { +#endif return PSA_ERROR_NOT_SUPPORTED; } memset(operation, 0, sizeof(*operation)); +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + status = bee_psa_status(bee_sha2_hw_start( + &operation->context, alg == PSA_ALG_SHA_224 ? SHA2_224 : SHA2_256)); +#else status = bee_psa_status(bee_sha256_hw_start(&operation->context)); +#endif if (status == PSA_SUCCESS) { operation->algorithm = alg; } @@ -107,7 +126,12 @@ psa_status_t bee_psa_hash_clone(const bee_psa_hash_operation_t *source_operation if (source_operation == NULL || target_operation == NULL) { return PSA_ERROR_INVALID_ARGUMENT; } +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + if (source_operation->algorithm != PSA_ALG_SHA_224 && + source_operation->algorithm != PSA_ALG_SHA_256) { +#else if (source_operation->algorithm != PSA_ALG_SHA_256) { +#endif return PSA_ERROR_BAD_STATE; } @@ -120,26 +144,42 @@ psa_status_t bee_psa_hash_update(bee_psa_hash_operation_t *operation, if (operation == NULL || (input == NULL && input_length != 0U)) { return PSA_ERROR_INVALID_ARGUMENT; } +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + if (operation->algorithm != PSA_ALG_SHA_224 && + operation->algorithm != PSA_ALG_SHA_256) { +#else if (operation->algorithm != PSA_ALG_SHA_256) { +#endif return PSA_ERROR_BAD_STATE; } +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + return bee_psa_status( + bee_sha2_hw_update(&operation->context, input, input_length)); +#else return bee_psa_status( bee_sha256_hw_update(&operation->context, input, input_length)); +#endif } psa_status_t bee_psa_hash_finish(bee_psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length) { - size_t required_size = PSA_HASH_LENGTH(PSA_ALG_SHA_256); + size_t required_size; psa_status_t status; if (operation == NULL || hash_length == NULL) { return PSA_ERROR_INVALID_ARGUMENT; } +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + if (operation->algorithm != PSA_ALG_SHA_224 && + operation->algorithm != PSA_ALG_SHA_256) { +#else if (operation->algorithm != PSA_ALG_SHA_256) { +#endif return PSA_ERROR_BAD_STATE; } + required_size = PSA_HASH_LENGTH(operation->algorithm); if (hash_size < required_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } @@ -147,7 +187,12 @@ psa_status_t bee_psa_hash_finish(bee_psa_hash_operation_t *operation, return PSA_ERROR_INVALID_ARGUMENT; } +#if defined(CONFIG_SOC_SERIES_RTL87X2J) + status = bee_psa_status( + bee_sha2_hw_finish(&operation->context, hash, required_size)); +#else status = bee_psa_status(bee_sha256_hw_finish(&operation->context, hash)); +#endif if (status == PSA_SUCCESS) { *hash_length = required_size; } @@ -587,8 +632,8 @@ static psa_status_t bee_psa_validate_key(const psa_key_attributes_t *attributes, static psa_status_t bee_psa_ecb_crypt(const uint8_t *key, size_t key_length, const uint8_t *input, uint8_t *output, bool decrypt) { - return bee_psa_status(bee_aes_hw_crypt_block(key, key_length, AES_MODE_ECB, - input, output, NULL, decrypt)); + return bee_psa_status(bee_aes_hw_crypt_block( + key, key_length, BEE_AES_MODE_ECB, input, output, NULL, decrypt)); } static psa_status_t @@ -862,9 +907,9 @@ static int bee_psa_cipher_cbc_block(bee_psa_cipher_operation_t *operation, if (operation->decrypt) { memcpy(next_iv, input, sizeof(next_iv)); } - ret = bee_aes_hw_crypt_block(operation->key, operation->key_length, - AES_MODE_CBC, input, output, operation->iv, - operation->decrypt); + ret = bee_aes_hw_crypt_block( + operation->key, operation->key_length, BEE_AES_MODE_CBC, input, output, + operation->iv, operation->decrypt); if (ret != BEE_CRYPTO_SUCCESS) { return ret; } diff --git a/bee/ld/rtl87x2j/bootloader.ld b/bee/ld/rtl87x2j/bootloader.ld index f0a046fd..5d1b8718 100644 --- a/bee/ld/rtl87x2j/bootloader.ld +++ b/bee/ld/rtl87x2j/bootloader.ld @@ -3,6 +3,14 @@ SECTIONS PROVIDE(srand_bl = 0x020005ed); PROVIDE(GTC_CounterToUs = 0x020010ed); PROVIDE(GTC_UsToCounter = 0x0200112d); + PROVIDE(aes_cmac = 0x020041e5); + PROVIDE(aes_cpu_operate = 0x02004241); + PROVIDE(aes_decrypt = 0x02004251); + PROVIDE(aes_dma_channel_init = 0x02004281); + PROVIDE(aes_dma_done = 0x02004289); + PROVIDE(aes_dma_operate = 0x0200428d); + PROVIDE(aes_encrypt = 0x0200429d); + PROVIDE(aes_init = 0x020042d9); PROVIDE(eflash_erase = 0x02005fe5); PROVIDE(eflash_read = 0x02006021); PROVIDE(eflash_write = 0x02006063); @@ -103,6 +111,17 @@ SECTIONS PROVIDE(ota_bank_addr_get = 0x020096b1); PROVIDE(ota_dual_bank_enable = 0x020096c5); PROVIDE(phy_hw_control_init = 0x0200a6f9); + PROVIDE(sha2 = 0x0200cee9); + PROVIDE(sha2_cpu_finish = 0x0200cf21); + PROVIDE(sha2_cpu_update = 0x0200cf29); + PROVIDE(sha2_dma_channel_init = 0x0200cf35); + PROVIDE(sha2_dma_finish = 0x0200cf41); + PROVIDE(sha2_dma_update = 0x0200cf4d); + PROVIDE(sha2_get_digest = 0x0200cf5d); + PROVIDE(sha2_get_digest_len = 0x0200cf61); + PROVIDE(sha2_init = 0x0200cf71); + PROVIDE(sha2_iv_init = 0x0200cf75); + PROVIDE(sha2_start = 0x0200cf81); PROVIDE(sys_reset = 0x0200d171); PROVIDE(sys_reset_aon_preserve = 0x0200d1a5); PROVIDE(trace_double = 0x0200d7a9);