From ad168fdf2dbfa249e49fdb06a075e31eb24bed01 Mon Sep 17 00:00:00 2001 From: Vlad Pruteanu Date: Wed, 8 Apr 2026 11:21:45 +0300 Subject: [PATCH] arch/xtensa/esp32: Add support for hardware accelerated PBKDF2 This adds support for the PBKDF2 algorithm in the ESP32 crypto driver. Here, it will take advantage of the hardware-accelerated implementation of SHA. Signed-off-by: Vlad Pruteanu --- .../platforms/xtensa/esp32/index.rst | 2 +- arch/xtensa/src/esp32/esp32_crypto.c | 103 +++++++++++++++++- .../esp32-devkitc/configs/crypto/defconfig | 1 + 3 files changed, 101 insertions(+), 5 deletions(-) diff --git a/Documentation/platforms/xtensa/esp32/index.rst b/Documentation/platforms/xtensa/esp32/index.rst index 0c055fbaae0..314c1974dfd 100644 --- a/Documentation/platforms/xtensa/esp32/index.rst +++ b/Documentation/platforms/xtensa/esp32/index.rst @@ -410,7 +410,7 @@ RSA No RTC Yes SD/MMC Yes SPI based SD card driver SDIO No -SHA Yes Also supports HMAC-SHA(1/256) +SHA Yes Also supports HMAC-SHA(1/256) and PBKDF2 SPI Yes SPIFLASH Yes SPIRAM Yes diff --git a/arch/xtensa/src/esp32/esp32_crypto.c b/arch/xtensa/src/esp32/esp32_crypto.c index 3b831c751c1..da14dc56f9a 100644 --- a/arch/xtensa/src/esp32/esp32_crypto.c +++ b/arch/xtensa/src/esp32/esp32_crypto.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -59,7 +61,7 @@ const struct auth_hash g_auth_hash_sha1_esp32 = { CRYPTO_SHA1, "SHA1", 0, 20, 12, sizeof(struct esp32_sha_context_s), - 0, + HMAC_SHA1_BLOCK_LEN, sha1_init, NULL, NULL, sha_update, sha_final @@ -69,7 +71,7 @@ const struct auth_hash g_auth_hash_sha2_256_esp32 = { CRYPTO_SHA2_256, "SHA256", 0, 32, 12, sizeof(struct esp32_sha_context_s), - 0, + HMAC_SHA2_256_BLOCK_LEN, sha256_init, NULL, NULL, sha_update, sha_final @@ -79,7 +81,7 @@ const struct auth_hash g_auth_hash_sha2_384_esp32 = { CRYPTO_SHA2_384, "SHA384", 0, 48, 12, sizeof(struct esp32_sha_context_s), - 0, + HMAC_SHA2_384_BLOCK_LEN, sha384_init, NULL, NULL, sha_update, sha_final @@ -89,7 +91,7 @@ const struct auth_hash g_auth_hash_sha2_512_esp32 = { CRYPTO_SHA2_512, "SHA512", 0, 64, 12, sizeof(struct esp32_sha_context_s), - 0, + HMAC_SHA2_512_BLOCK_LEN, sha512_init, NULL, NULL, sha_update, sha_final @@ -334,6 +336,8 @@ static int authcompute(struct cryptop *crp, struct cryptodesc *crd, { case CRYPTO_SHA1_HMAC: case CRYPTO_SHA2_256_HMAC: + case CRYPTO_PBKDF2_HMAC_SHA1: + case CRYPTO_PBKDF2_HMAC_SHA256: if (data->hw_octx == NULL) { return -EINVAL; @@ -364,6 +368,88 @@ static int authcompute(struct cryptop *crp, struct cryptodesc *crd, return 0; } +static void esp32_pbkdf2_rekey(struct esp32_crypto_data *data, + const struct auth_hash *axf, + const caddr_t key, size_t klen) +{ + uint8_t keybuf[128]; + size_t k; + + memcpy(keybuf, key, klen); + for (k = 0; k < klen; k++) + keybuf[k] ^= HMAC_IPAD_VAL; + + axf->init(data->hw_ictx); + axf->update(data->hw_ictx, keybuf, klen); + axf->update(data->hw_ictx, hmac_ipad_buffer, axf->blocksize - klen); + axf->init(data->hw_octx); +} + +int esp32_pbkdf2(struct cryptop *crp, + struct cryptodesc *crd, + struct esp32_crypto_data *data, + caddr_t buf) +{ + const struct auth_hash *axf = data->hw_axf; + uint8_t U[64]; + uint8_t T[64]; + uint8_t macbuf[64]; + uint8_t key_backup[128]; + char key_work[128]; + struct cryptop crp_dummy; + struct cryptodesc crd_dummy; + + size_t generated = 0; + uint32_t blocknum; + uint32_t i; + uint32_t j; + + crp_dummy.crp_mac = (caddr_t)macbuf; + crd_dummy.crd_key = key_work; + crd_dummy.crd_klen = crd->crd_klen; + + for (blocknum = 1; generated < crp->crp_olen; blocknum++) + { + uint8_t saltblk[crp->crp_ilen + 4]; + uint32_t block_be = htobe32(blocknum); + + memcpy(saltblk, crp->crp_buf, crp->crp_ilen); + memcpy(saltblk + crp->crp_ilen, &block_be, 4); + + /* U1 */ + + esp32_pbkdf2_rekey(data, axf, crd->crd_key, crd->crd_klen / 8); + memcpy(key_work, crd->crd_key, crd->crd_klen / 8); + crd_dummy.crd_len = crp->crp_ilen + 4; + authcompute(&crp_dummy, &crd_dummy, data, (caddr_t)saltblk); + memcpy(U, macbuf, axf->hashsize); + memcpy(T, U, axf->hashsize); + + /* U2..Uc */ + + for (i = 1; i < crp->crp_iter; i++) + { + uint8_t u_prev[64]; + + memcpy(u_prev, U, axf->hashsize); + esp32_pbkdf2_rekey(data, axf, crd->crd_key, crd->crd_klen / 8); + memcpy(key_work, crd->crd_key, crd->crd_klen / 8); + crd_dummy.crd_len = axf->hashsize; + authcompute(&crp_dummy, &crd_dummy, data, (caddr_t)u_prev); + memcpy(U, macbuf, axf->hashsize); + + for (j = 0; j < axf->hashsize; j++) + T[j] ^= U[j]; + } + + size_t tocopy = MIN(crp->crp_olen - generated, axf->hashsize); + memcpy(crp->crp_mac + generated, T, tocopy); + generated += tocopy; + } + + return 0; +} + /**************************************************************************** * Name: esp32_newsession * @@ -474,9 +560,11 @@ static int esp32_newsession(uint32_t *sid, struct cryptoini *cri) data->hw_axf = axf; break; case CRYPTO_SHA1_HMAC: + case CRYPTO_PBKDF2_HMAC_SHA1: axf = &g_auth_hash_hmac_sha1_esp32; goto common__hmac; case CRYPTO_SHA2_256_HMAC: + case CRYPTO_PBKDF2_HMAC_SHA256: axf = &g_auth_hash_hmac_sha256_esp32; goto common__hmac; common__hmac: @@ -699,6 +787,11 @@ static int esp32_process(struct cryptop *crp) return crp->crp_etype; } break; + case CRYPTO_PBKDF2_HMAC_SHA1: + case CRYPTO_PBKDF2_HMAC_SHA256: + esp32_pbkdf2(crp, crd, data, crp->crp_buf); + + break; default: return -EINVAL; } @@ -733,6 +826,8 @@ void hwcr_init(void) algs[CRYPTO_SHA2_512] = CRYPTO_ALG_FLAG_SUPPORTED; algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED; algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED; + algs[CRYPTO_PBKDF2_HMAC_SHA1] = CRYPTO_ALG_FLAG_SUPPORTED; + algs[CRYPTO_PBKDF2_HMAC_SHA256] = CRYPTO_ALG_FLAG_SUPPORTED; esp32_sha_init(); crypto_register(hwcr_id, algs, esp32_newsession, diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/crypto/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/crypto/defconfig index f6500fcea3e..31e8fd864a6 100644 --- a/boards/xtensa/esp32/esp32-devkitc/configs/crypto/defconfig +++ b/boards/xtensa/esp32/esp32-devkitc/configs/crypto/defconfig @@ -60,4 +60,5 @@ CONFIG_SYSTEM_NSH=y CONFIG_TESTING_CRYPTO=y CONFIG_TESTING_CRYPTO_HASH=y CONFIG_TESTING_CRYPTO_HASH_DISABLE_MD5=y +CONFIG_TESTING_CRYPTO_PBKDF2=y CONFIG_UART0_SERIAL_CONSOLE=y