Skip to content

Commit 0bf5861

Browse files
committed
port/st/stm32: add CubeMX AES crypto-callback device and STM32U3 HAL PKA include
1 parent 4a7695e commit 0bf5861

3 files changed

Lines changed: 242 additions & 32 deletions

File tree

wolfcrypt/src/port/st/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,21 @@ The TinyAES IP exposes a single key-size bit (128/256 only), so wolfSSL auto-def
8383

8484
Some newer families (H5/H7S/U3/U5/WBA/C5/N6, plus the L562 sub-variant) expose a Secure AES (SAES) instance in addition to (or instead of) a regular AES block. Define `WOLFSSL_STM32_USE_SAES` to route all wolfcrypt AES traffic through SAES via the `WC_STM32_AES_INST` indirection macro. This is required when the regular AES block is TrustZone-gated (H7S3) and is also a prerequisite for DHUK key-wrap on the families in the `WC_STM32_HAS_DHUK` gate (U3/U5/H5/WBA/C5).
8585

86+
### AES via crypto callback (`WOLF_CRYPTO_CB_ONLY_AES`)
87+
88+
`WOLF_CRYPTO_CB_ONLY_AES` strips the software AES core (to shrink code) and routes every AES operation through the `WOLF_CRYPTO_CB` framework. On the CubeMX/HAL build, register the STM32 CubeMX AES device so those callbacks reach the HAL AES hardware:
89+
90+
```
91+
#define WOLFSSL_STM32_CUBEMX
92+
#define WOLF_CRYPTO_CB
93+
#define WOLF_CRYPTO_CB_ONLY_AES
94+
...
95+
wc_Stm32_CubeAesRegister(devId); /* once */
96+
wc_AesInit(&aes, NULL, devId); /* per Aes; then use wc_AesGcm* as normal */
97+
```
98+
99+
The device services AES-ECB on the HAL, which is what `wc_AesGcmSetKey` needs to derive the GHASH subkey; AES-GCM then runs on the native HAL GCM engine, all with the normal plaintext key. When `WOLFSSL_STM32_CCB` is enabled, `wc_Stm32_DhukRegister` dispatches these ciphers too, so a single devId serves both CCB ECDSA and AES. Worked example: [`STM32_Bare_Test/src/main_cubeaes.c`](https://github.com/wolfSSL/wolfssl-examples-stm32) (validated on NUCLEO-U385RG-Q).
100+
86101
### Coding
87102

88103
Include `<wolfssl/wolfcrypt/settings.h>` before any other wolfSSL headers. If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own `user_settings.h`. A reference is in `IDE/GCC-ARM/Header/user_settings.h`.

wolfcrypt/src/port/st/stm32.c

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
#endif
4040
#endif
4141

42+
/* The CubeMX AES crypto-callback device needs cryptocb.h on any WOLF_CRYPTO_CB
43+
* build, not only WOLFSSL_DHUK. */
44+
#if defined(WOLF_CRYPTO_CB) && !defined(WOLFSSL_DHUK)
45+
#include <wolfssl/wolfcrypt/cryptocb.h>
46+
#endif
47+
4248
#ifdef NO_INLINE
4349
#include <wolfssl/wolfcrypt/misc.h>
4450
#else
@@ -75,6 +81,9 @@
7581
#elif defined(WOLFSSL_STM32U5)
7682
#include <stm32u5xx_hal_conf.h>
7783
#include <stm32u5xx_hal_pka.h>
84+
#elif defined(WOLFSSL_STM32U3)
85+
#include <stm32u3xx_hal_conf.h>
86+
#include <stm32u3xx_hal_pka.h>
7887
#elif defined(WOLFSSL_STM32WB)
7988
#include <stm32wbxx_hal_conf.h>
8089
#include <stm32wbxx_hal_pka.h>
@@ -5046,6 +5055,142 @@ void wc_Stm32_Aes_Cleanup(void)
50465055

50475056
#endif /* WOLFSSL_STM32_BARE / WOLFSSL_STM32_CUBEMX / StdPeriph */
50485057

5058+
/* CubeMX/HAL AES crypto-callback device -- makes WOLF_CRYPTO_CB_ONLY_AES work on
5059+
* the HAL build. That mode strips the software AES core and routes AES through
5060+
* the crypto callback; wc_AesGcmSetKey derives the GHASH subkey H via
5061+
* wc_CryptoCb_AesEcbEncrypt, so an AES-ECB handler is required just to key GCM.
5062+
* Providing it here lets AES-GCM be keyed, after which wc_AesGcmEncrypt runs on
5063+
* the native HAL GCM engine (wc_AesGcmEncrypt_STM32) via its CRYPTOCB_UNAVAILABLE
5064+
* fall-through. Uses the plaintext key on the Aes (aes->key) and the plain CRYP
5065+
* (AES/TinyAES) instance -- no DHUK/SAES. */
5066+
#if defined(WOLFSSL_STM32_CUBEMX) && defined(WOLF_CRYPTO_CB)
5067+
5068+
#if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) || \
5069+
defined(WOLF_CRYPTO_CB_ONLY_AES)
5070+
/* One or more whole AES blocks through the HAL in ECB mode. enc != 0 selects
5071+
* encrypt. Mirrors the HAL ECB sequence in wc_AesEncrypt/wc_AesDecrypt (aes.c)
5072+
* that WOLF_CRYPTO_CB_ONLY_AES compiles out. */
5073+
static int Stm32Cube_AesEcb(struct Aes* aes, byte* out, const byte* in,
5074+
word32 sz, int enc)
5075+
{
5076+
CRYP_HandleTypeDef hcryp;
5077+
int ret;
5078+
5079+
if (aes == NULL || out == NULL || in == NULL) {
5080+
return BAD_FUNC_ARG;
5081+
}
5082+
if (sz == 0 || (sz % WC_AES_BLOCK_SIZE) != 0) {
5083+
return BAD_FUNC_ARG;
5084+
}
5085+
5086+
ret = wc_Stm32_Aes_Init(aes, &hcryp, 0);
5087+
if (ret != 0) {
5088+
return ret;
5089+
}
5090+
5091+
ret = wolfSSL_CryptHwMutexLock();
5092+
if (ret != 0) {
5093+
return ret;
5094+
}
5095+
5096+
#if defined(STM32_HAL_V2)
5097+
hcryp.Init.Algorithm = CRYP_AES_ECB;
5098+
#elif defined(STM32_CRYPTO_AES_ONLY)
5099+
hcryp.Init.OperatingMode = enc ?
5100+
CRYP_ALGOMODE_ENCRYPT : CRYP_ALGOMODE_KEYDERIVATION_DECRYPT;
5101+
hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_ECB;
5102+
hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE;
5103+
#endif
5104+
if (HAL_CRYP_Init(&hcryp) != HAL_OK) {
5105+
wolfSSL_CryptHwMutexUnLock();
5106+
wc_Stm32_Aes_Cleanup();
5107+
return WC_HW_E;
5108+
}
5109+
5110+
#if defined(STM32_HAL_V2)
5111+
if (enc) {
5112+
ret = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in, sz, (uint32_t*)out,
5113+
STM32_HAL_TIMEOUT);
5114+
}
5115+
else {
5116+
ret = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)in, sz, (uint32_t*)out,
5117+
STM32_HAL_TIMEOUT);
5118+
}
5119+
#elif defined(STM32_CRYPTO_AES_ONLY)
5120+
ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)in, sz, out, STM32_HAL_TIMEOUT);
5121+
#else
5122+
if (enc) {
5123+
ret = HAL_CRYP_AESECB_Encrypt(&hcryp, (uint8_t*)in, sz, out,
5124+
STM32_HAL_TIMEOUT);
5125+
}
5126+
else {
5127+
ret = HAL_CRYP_AESECB_Decrypt(&hcryp, (uint8_t*)in, sz, out,
5128+
STM32_HAL_TIMEOUT);
5129+
}
5130+
#endif
5131+
if (ret != HAL_OK) {
5132+
ret = WC_TIMEOUT_E;
5133+
}
5134+
5135+
HAL_CRYP_DeInit(&hcryp);
5136+
wolfSSL_CryptHwMutexUnLock();
5137+
wc_Stm32_Aes_Cleanup();
5138+
return ret;
5139+
}
5140+
#endif /* HAVE_AES_ECB || WOLFSSL_AES_DIRECT || WOLF_CRYPTO_CB_ONLY_AES */
5141+
5142+
/* Cipher dispatch (shared with the CCB device below). Services AES-ECB; other
5143+
* modes return CRYPTOCB_UNAVAILABLE so the caller falls through to the native
5144+
* HAL path (e.g. wc_AesGcmEncrypt_STM32) or another provider. */
5145+
static int Stm32Cube_Cipher(struct wc_CryptoInfo* info)
5146+
{
5147+
if (info == NULL) {
5148+
return CRYPTOCB_UNAVAILABLE;
5149+
}
5150+
5151+
switch (info->cipher.type) {
5152+
#if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) || \
5153+
defined(WOLF_CRYPTO_CB_ONLY_AES)
5154+
case WC_CIPHER_AES_ECB:
5155+
return Stm32Cube_AesEcb(info->cipher.aesecb.aes,
5156+
info->cipher.aesecb.out, info->cipher.aesecb.in,
5157+
info->cipher.aesecb.sz, info->cipher.enc);
5158+
#endif
5159+
default:
5160+
return CRYPTOCB_UNAVAILABLE;
5161+
}
5162+
}
5163+
5164+
/* Standalone AES-only device for CubeMX builds without the CCB/DHUK ECDSA
5165+
* device. Register at a devId, then wc_AesInit(aes, heap, devId). (With
5166+
* WOLFSSL_STM32_CCB the CCB device dispatches ciphers here too.) */
5167+
static int Stm32Cube_AesCryptoDevCb(int devId, struct wc_CryptoInfo* info,
5168+
void* ctx)
5169+
{
5170+
(void)devId;
5171+
(void)ctx;
5172+
5173+
if (info == NULL) {
5174+
return CRYPTOCB_UNAVAILABLE;
5175+
}
5176+
if (info->algo_type == WC_ALGO_TYPE_CIPHER) {
5177+
return Stm32Cube_Cipher(info);
5178+
}
5179+
return CRYPTOCB_UNAVAILABLE;
5180+
}
5181+
5182+
int wc_Stm32_CubeAesRegister(int devId)
5183+
{
5184+
return wc_CryptoCb_RegisterDevice(devId, Stm32Cube_AesCryptoDevCb, NULL);
5185+
}
5186+
5187+
void wc_Stm32_CubeAesUnRegister(int devId)
5188+
{
5189+
wc_CryptoCb_UnRegisterDevice(devId);
5190+
}
5191+
5192+
#endif /* WOLFSSL_STM32_CUBEMX && WOLF_CRYPTO_CB */
5193+
50495194
/* CubeMX/HAL CCB ECDSA port -- placed after the build-branch structure and
50505195
* guarded on WOLFSSL_STM32_CUBEMX so it compiles only for the HAL build (the
50515196
* BARE build provides its own wc_Stm32_Ccb_* above). */
@@ -5234,7 +5379,17 @@ static int Stm32Ccb_CryptoDevCb(int devId, struct wc_CryptoInfo* info,
52345379

52355380
(void)devId;
52365381
(void)ctx;
5237-
if (info == NULL || info->algo_type != WC_ALGO_TYPE_PK) {
5382+
if (info == NULL) {
5383+
return CRYPTOCB_UNAVAILABLE;
5384+
}
5385+
/* Route ciphers to the shared CubeMX AES handler so one devId serves both
5386+
* CCB ECDSA and HAL AES (lets WOLF_CRYPTO_CB_ONLY_AES work here). */
5387+
#ifndef NO_AES
5388+
if (info->algo_type == WC_ALGO_TYPE_CIPHER) {
5389+
return Stm32Cube_Cipher(info);
5390+
}
5391+
#endif
5392+
if (info->algo_type != WC_ALGO_TYPE_PK) {
52385393
return CRYPTOCB_UNAVAILABLE;
52395394
}
52405395
/* Transparent provisioning: wc_ecc_make_key() on a WC_DHUK_DEVID key binds

wolfssl/wolfcrypt/port/st/stm32.h

Lines changed: 71 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,11 @@
471471
#endif
472472
#endif
473473

474-
/* HAL-legacy macros that the existing direct-register HASH path depends on.
475-
* Without HAL these aren't otherwise visible. */
474+
/* HAL-legacy macros the direct-register HASH path depends on. ST's
475+
* stm32XXxx_hal_hash.h also defines these HASH_ALGOSELECTION_* / HASH_ALGOMODE_*
476+
* / HASH_DATATYPE_8B names, so each is wrapped in #ifndef: when the Cube HAL
477+
* headers reach this TU (e.g. a Zephyr build) the HAL's copy wins (same register
478+
* bits) instead of causing a redefinition; otherwise we define our own. */
476479
#if defined(WOLFSSL_STM32H5) || defined(WOLFSSL_STM32MP13) || \
477480
defined(WOLFSSL_STM32N6) || defined(WOLFSSL_STM32H7S) || \
478481
defined(WOLFSSL_STM32U3) || defined(WOLFSSL_STM32C5)
@@ -486,66 +489,94 @@
486489
#define WC_STM32_HASH_INSTANCE_HRA
487490
#endif
488491
/* 4-bit ALGO field at bits 20:17 */
489-
#define HASH_ALGOSELECTION_SHA1 0u
490-
#define HASH_ALGOSELECTION_SHA224 HASH_CR_ALGO_1
491-
#define HASH_ALGOSELECTION_SHA256 (HASH_CR_ALGO_0 | HASH_CR_ALGO_1)
492-
#define HASH_ALGOSELECTION_SHA384 (HASH_CR_ALGO_2 | HASH_CR_ALGO_3)
493-
#define HASH_ALGOSELECTION_SHA512 (HASH_CR_ALGO_0 | HASH_CR_ALGO_1 | \
494-
HASH_CR_ALGO_2 | HASH_CR_ALGO_3)
495-
#define HASH_ALGOSELECTION_SHA512_224 (HASH_CR_ALGO_0 | HASH_CR_ALGO_2 | \
496-
HASH_CR_ALGO_3)
497-
#define HASH_ALGOSELECTION_SHA512_256 (HASH_CR_ALGO_1 | HASH_CR_ALGO_2 | \
498-
HASH_CR_ALGO_3)
492+
#ifndef HASH_ALGOSELECTION_SHA1
493+
#define HASH_ALGOSELECTION_SHA1 0u
494+
#endif
495+
#ifndef HASH_ALGOSELECTION_SHA224
496+
#define HASH_ALGOSELECTION_SHA224 HASH_CR_ALGO_1
497+
#endif
498+
#ifndef HASH_ALGOSELECTION_SHA256
499+
#define HASH_ALGOSELECTION_SHA256 (HASH_CR_ALGO_0 | HASH_CR_ALGO_1)
500+
#endif
501+
#ifndef HASH_ALGOSELECTION_SHA384
502+
#define HASH_ALGOSELECTION_SHA384 (HASH_CR_ALGO_2 | HASH_CR_ALGO_3)
503+
#endif
504+
#ifndef HASH_ALGOSELECTION_SHA512
505+
#define HASH_ALGOSELECTION_SHA512 (HASH_CR_ALGO_0 | HASH_CR_ALGO_1 | \
506+
HASH_CR_ALGO_2 | HASH_CR_ALGO_3)
507+
#endif
508+
#ifndef HASH_ALGOSELECTION_SHA512_224
509+
#define HASH_ALGOSELECTION_SHA512_224 (HASH_CR_ALGO_0 | HASH_CR_ALGO_2 | \
510+
HASH_CR_ALGO_3)
511+
#endif
512+
#ifndef HASH_ALGOSELECTION_SHA512_256
513+
#define HASH_ALGOSELECTION_SHA512_256 (HASH_CR_ALGO_1 | HASH_CR_ALGO_2 | \
514+
HASH_CR_ALGO_3)
515+
#endif
499516
#else
500517
/* Older HASH IP (F4/F7/L4 family) ALGO bit mapping (per HAL):
501518
* SHA1 = 0
502519
* MD5 = ALGO_0
503520
* SHA224 = ALGO_1
504521
* SHA256 = ALGO_0 | ALGO_1
505522
*/
506-
#define HASH_ALGOSELECTION_SHA1 0u
507-
#define HASH_ALGOSELECTION_MD5 HASH_CR_ALGO_0
523+
#ifndef HASH_ALGOSELECTION_SHA1
524+
#define HASH_ALGOSELECTION_SHA1 0u
525+
#endif
526+
#ifndef HASH_ALGOSELECTION_MD5
527+
#define HASH_ALGOSELECTION_MD5 HASH_CR_ALGO_0
528+
#endif
508529
#ifdef HASH_CR_ALGO_1
509-
#define HASH_ALGOSELECTION_SHA224 HASH_CR_ALGO_1
510-
#define HASH_ALGOSELECTION_SHA256 (HASH_CR_ALGO_0 | HASH_CR_ALGO_1)
530+
#ifndef HASH_ALGOSELECTION_SHA224
531+
#define HASH_ALGOSELECTION_SHA224 HASH_CR_ALGO_1
532+
#endif
533+
#ifndef HASH_ALGOSELECTION_SHA256
534+
#define HASH_ALGOSELECTION_SHA256 (HASH_CR_ALGO_0 | HASH_CR_ALGO_1)
535+
#endif
511536
#endif
512537
#endif
513538

514539
/* Legacy CamelCase aliases */
515-
#ifdef HASH_ALGOSELECTION_SHA1
540+
#if defined(HASH_ALGOSELECTION_SHA1) && !defined(HASH_AlgoSelection_SHA1)
516541
#define HASH_AlgoSelection_SHA1 HASH_ALGOSELECTION_SHA1
517542
#endif
518-
#ifdef HASH_ALGOSELECTION_SHA224
543+
#if defined(HASH_ALGOSELECTION_SHA224) && !defined(HASH_AlgoSelection_SHA224)
519544
#define HASH_AlgoSelection_SHA224 HASH_ALGOSELECTION_SHA224
520545
#endif
521-
#ifdef HASH_ALGOSELECTION_SHA256
546+
#if defined(HASH_ALGOSELECTION_SHA256) && !defined(HASH_AlgoSelection_SHA256)
522547
#define HASH_AlgoSelection_SHA256 HASH_ALGOSELECTION_SHA256
523548
#endif
524-
#ifdef HASH_ALGOSELECTION_SHA384
549+
#if defined(HASH_ALGOSELECTION_SHA384) && !defined(HASH_AlgoSelection_SHA384)
525550
#define HASH_AlgoSelection_SHA384 HASH_ALGOSELECTION_SHA384
526551
#endif
527-
#ifdef HASH_ALGOSELECTION_SHA512
552+
#if defined(HASH_ALGOSELECTION_SHA512) && !defined(HASH_AlgoSelection_SHA512)
528553
#define HASH_AlgoSelection_SHA512 HASH_ALGOSELECTION_SHA512
529554
#endif
530-
#ifdef HASH_ALGOSELECTION_SHA512_224
555+
#if defined(HASH_ALGOSELECTION_SHA512_224) && \
556+
!defined(HASH_AlgoSelection_SHA512_224)
531557
#define HASH_AlgoSelection_SHA512_224 HASH_ALGOSELECTION_SHA512_224
532558
#endif
533-
#ifdef HASH_ALGOSELECTION_SHA512_256
559+
#if defined(HASH_ALGOSELECTION_SHA512_256) && \
560+
!defined(HASH_AlgoSelection_SHA512_256)
534561
#define HASH_AlgoSelection_SHA512_256 HASH_ALGOSELECTION_SHA512_256
535562
#endif
536-
#ifdef HASH_ALGOSELECTION_MD5
563+
#if defined(HASH_ALGOSELECTION_MD5) && !defined(HASH_AlgoSelection_MD5)
537564
#define HASH_AlgoSelection_MD5 HASH_ALGOSELECTION_MD5
538565
#endif
539566

540-
#define HASH_ALGOMODE_HASH 0u
541-
#ifdef HASH_CR_MODE
542-
#define HASH_ALGOMODE_HMAC HASH_CR_MODE
567+
#ifndef HASH_ALGOMODE_HASH
568+
#define HASH_ALGOMODE_HASH 0u
569+
#endif
570+
#if defined(HASH_CR_MODE) && !defined(HASH_ALGOMODE_HMAC)
571+
#define HASH_ALGOMODE_HMAC HASH_CR_MODE
543572
#endif
544573
/* Byte-stream input (auto byte-swap) */
545-
#ifdef HASH_CR_DATATYPE_1
546-
#define HASH_DATATYPE_8B HASH_CR_DATATYPE_1
547-
#elif defined(HASH_CR_DATATYPE_0)
548-
#define HASH_DATATYPE_8B HASH_CR_DATATYPE_0
574+
#ifndef HASH_DATATYPE_8B
575+
#ifdef HASH_CR_DATATYPE_1
576+
#define HASH_DATATYPE_8B HASH_CR_DATATYPE_1
577+
#elif defined(HASH_CR_DATATYPE_0)
578+
#define HASH_DATATYPE_8B HASH_CR_DATATYPE_0
579+
#endif
549580
#endif
550581

551582
#endif /* WOLFSSL_STM32_BARE */
@@ -969,6 +1000,15 @@ int stm32_ecc_sign_hash_ex(const byte* hash, word32 hashlen, struct WC_RNG* rng,
9691000
void wc_Stm32_DhukUnRegister(int devId);
9701001
#endif
9711002

1003+
/* CubeMX/HAL AES crypto-callback device. Register at a devId, then init an Aes
1004+
* with it (wc_AesInit) to run AES on the HAL through the crypto callback -- this
1005+
* makes WOLF_CRYPTO_CB_ONLY_AES work on the HAL build. With WOLFSSL_STM32_CCB
1006+
* enabled, wc_Stm32_DhukRegister already covers AES too (same devId). */
1007+
#if defined(WOLFSSL_STM32_CUBEMX) && defined(WOLF_CRYPTO_CB)
1008+
int wc_Stm32_CubeAesRegister(int devId);
1009+
void wc_Stm32_CubeAesUnRegister(int devId);
1010+
#endif
1011+
9721012
/* CCB (Coupling and Chaining Bridge) HW-protected DHUK->PKA ECDSA -- STM32U3
9731013
* (e.g. U385). Available on both build paths: WOLFSSL_STM32_BARE (direct
9741014
* register driver) and WOLFSSL_STM32_CUBEMX (ST HAL_CCB_* driver). The blob is

0 commit comments

Comments
 (0)