Showing results for 
Search instead for 
Did you mean: 

Encryption using AES CCM + MIC - stm32wb

Associate II


i am trying to develop a device which sends out bthome advertisements via ble (some sensor data).

So far so good, this part is working, but now i would also like to use bthome encryption.

So following this guide, i would need AES128 - CCM and MIC.

What i did so far is enabling AES and set it to be CCM and added a key (using CubeMX).

In the generated code i now have the hcrypt handle.

What i did afterwards -> I collected all the described data to create the nonce:

  uint8_t nonce[13];
  // MAC Address
  nonce[0] = mac_address[0];
  nonce[1] = mac_address[1];
  nonce[2] = mac_address[2];
  nonce[3] = mac_address[3];
  nonce[4] = mac_address[4];
  nonce[5] = mac_address[5];

  // add bt_home_device_info
  nonce[6] = bt_home_device_info;

  // add UUID
  nonce[7] = (uuid >> 😎 & 0xff; 
  nonce[8] = uuid & 0xff;        

  // add counter
  nonce[9] = (counter >> 24) & 0xff;
  nonce[10] = (counter >> 16) & 0xff;
  nonce[11] = (counter >> 😎 & 0xff;
  nonce[12] = counter & 0xff;

This is my nonce i would need for AES CCM.

Now sadly the example on bthome is a python one.. but they are using it as follows:

from Cryptodome.Cipher import AES

cipher =, AES.MODE_CCM, nonce=nonce, mac_len=4)
ciphertext, mic = cipher.encrypt_and_digest(data)

So basically a new cipher instance is created with the key and the nonce, telling the mac/mic len is 4 bytes.

Then encrypt the data (bthome service data) with this cipher.

My question is how i would achieve this using HAL_Cryp* library on a stm32wb55?

I looked for different examples and there are some for a wb55 but none for CCM as far as i can see.

-> Then i saw that there also is a third party software pack mbedtls which should make this a bit easier but apparently it is not available on stm32wb.

My current aes init is as cubemx generated it:

CRYP_HandleTypeDef hcryp1;
__ALIGN_BEGIN static const uint32_t pKeyAES1[4] __ALIGN_END = {
__ALIGN_BEGIN static const uint32_t HeaderAES1[4] __ALIGN_END = {
__ALIGN_BEGIN static const uint32_t B0AES1[4] __ALIGN_END = {

/* AES1 init function */
void MX_AES1_Init(void)

  /* USER CODE BEGIN AES1_Init 0 */

  /* USER CODE END AES1_Init 0 */

  /* USER CODE BEGIN AES1_Init 1 */

  /* USER CODE END AES1_Init 1 */
  hcryp1.Instance = AES1;
  hcryp1.Init.DataType = CRYP_DATATYPE_8B;
  hcryp1.Init.KeySize = CRYP_KEYSIZE_128B;
  hcryp1.Init.pKey = (uint32_t *)pKeyAES1;
  hcryp1.Init.Algorithm = CRYP_AES_CCM;
  hcryp1.Init.Header = (uint32_t *)HeaderAES1;
  hcryp1.Init.HeaderSize = 4;
  hcryp1.Init.B0 = (uint32_t *)B0AES1;
  hcryp1.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
  hcryp1.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
  if (HAL_CRYP_Init(&hcryp1) != HAL_OK)
  /* USER CODE BEGIN AES1_Init 2 */

  /* USER CODE END AES1_Init 2 */


My knowledge about crypto is quite limited so i also don't really know what i should use for B0 and HeaderAES1.

Maybe you know some wrapper library or sth. similar which i could use.