arch/arm/src/stm32h7: Add support for CRYP peripheral

Add STM32H7 support for AES-CBC/CTR HW encryption accelerator.
Add nucleo-h753zi:crypt defconfig.

Signed-off-by: Peter Barada <peter.barada@gmail.com>
This commit is contained in:
Peter Barada 2026-05-25 19:11:14 -04:00 committed by Xiang Xiao
parent 304b8706cb
commit 6bba29a2ba
8 changed files with 1212 additions and 4 deletions

View file

@ -233,42 +233,47 @@ config ARCH_CHIP_STM32H750VB
select STM32H7_STM32H7X0XX
select STM32H7_FLASH_CONFIG_B
select STM32H7_IO_CONFIG_V
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7+M4, 128 Kb FLASH, 1024K Kb SRAM,
LQFP100
with cryptographic accelerator, LQFP100
config ARCH_CHIP_STM32H750ZB
bool "STM32H750ZB"
select STM32H7_STM32H7X0XX
select STM32H7_FLASH_CONFIG_B
select STM32H7_IO_CONFIG_Z
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7+M4, 128 Kb FLASH, 1024K Kb SRAM,
LQFP144
with cryptographic accelerator, LQFP144
config ARCH_CHIP_STM32H750IB
bool "STM32H750IB"
select STM32H7_STM32H7X0XX
select STM32H7_FLASH_CONFIG_B
select STM32H7_IO_CONFIG_I
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7+M4, 128 Kb FLASH, 1024K Kb SRAM,
LQFP176 or UFBGA176+25
with cryptographic accelerator, LQFP176 or UFBGA176+25
config ARCH_CHIP_STM32H750XB
bool "STM32H750XB"
select STM32H7_STM32H7X0XX
select STM32H7_FLASH_CONFIG_B
select STM32H7_IO_CONFIG_X
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7+M4, 128 Kb FLASH, 1024K Kb SRAM,
TFBGA240+25
with cryptographic accelerator, TFBGA240+25
config ARCH_CHIP_STM32H753AI
bool "STM32H753AI"
select STM32H7_STM32H7X3XX
select STM32H7_FLASH_CONFIG_I
select STM32H7_IO_CONFIG_A
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, UFBGA169
@ -278,6 +283,7 @@ config ARCH_CHIP_STM32H753BI
select STM32H7_STM32H7X3XX
select STM32H7_FLASH_CONFIG_I
select STM32H7_IO_CONFIG_B
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP208
@ -287,6 +293,7 @@ config ARCH_CHIP_STM32H753II
select STM32H7_STM32H7X3XX
select STM32H7_FLASH_CONFIG_I
select STM32H7_IO_CONFIG_I
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP176/UFBGA176
@ -296,6 +303,7 @@ config ARCH_CHIP_STM32H753VI
select STM32H7_STM32H7X3XX
select STM32H7_FLASH_CONFIG_I
select STM32H7_IO_CONFIG_V
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP100/TFBGA100
@ -305,6 +313,7 @@ config ARCH_CHIP_STM32H753XI
select STM32H7_STM32H7X3XX
select STM32H7_FLASH_CONFIG_I
select STM32H7_IO_CONFIG_X
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, TFBGA240
@ -314,6 +323,7 @@ config ARCH_CHIP_STM32H753ZI
select STM32H7_STM32H7X3XX
select STM32H7_FLASH_CONFIG_I
select STM32H7_IO_CONFIG_Z
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP144
@ -324,6 +334,7 @@ config ARCH_CHIP_STM32H7B3LI
select STM32H7_FLASH_CONFIG_I
select STM32H7_IO_CONFIG_L
select STM32H7_HAVE_SMPS
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1376 Kb SRAM,
with cryptographic accelerator, TFBGA225
@ -335,6 +346,7 @@ config ARCH_CHIP_STM32H755II
select STM32H7_IO_CONFIG_I
select STM32H7_HAVE_FDCAN1
select STM32H7_HAVE_FDCAN2
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP176/UFBGA176
@ -346,6 +358,7 @@ config ARCH_CHIP_STM32H755XI
select STM32H7_IO_CONFIG_X
select STM32H7_HAVE_FDCAN1
select STM32H7_HAVE_FDCAN2
select STM32H7_HAVE_CRYP
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, TFBGA240
@ -759,6 +772,10 @@ config STM32H7_HAVE_RNG
bool
default n
config STM32H7_HAVE_CRYP
bool
default n
# These "hidden" settings are the OR of individual peripheral selections
# indicating that the general capability is required.
@ -865,6 +882,11 @@ config STM32H7_CRC
bool "CRC"
default n
config STM32H7_CRYP
bool "CRYP"
default n
depends on STM32H7_HAVE_CRYP
config STM32H7_BKPSRAM
bool "Enable BKP RAM Domain"
select STM32H7_PWR

View file

@ -213,3 +213,15 @@ endif
ifeq ($(CONFIG_STM32H7_WWDG),y)
CHIP_CSRCS += stm32_wwdg.c
endif
#ifeq ($(CONFIG_STM32H7_HASH),y)
#CHIP_CSRCS += stm32_hash.c
#endif
ifeq ($(CONFIG_STM32H7_CRYP),y)
CHIP_CSRCS += stm32_aes.c
endif
ifeq ($(CONFIG_CRYPTO_CRYPTODEV_HARDWARE),y)
CHIP_CSRCS += stm32_crypto.c
endif

View file

@ -0,0 +1,186 @@
/****************************************************************************
* arch/arm/src/stm32h7/hardware/stm32h7xxxx_cryp.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32H7X3XX_CRYP_H
#define __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32H7X3XX_CRYP_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include "chip.h"
/* The following STM32H7 devices have a cryptographic accelerator that
* support AES, DES/TDES:
*
* STM32H735ZO, STM32H750XX, STM32H753XX, STM32H755XX, STM32H757XX,
* STM32H7B0XX, STM32H7B3XX, STM32H7S3x8, STM32H7S7X8
*/
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* CRYP register offsets ****************************************************/
#define STM32_CRYP_CR_OFFSET 0x0000 /* Control Register */
#define STM32_CRYP_SR_OFFSET 0x0004 /* Status Register */
#define STM32_CRYP_DIN_OFFSET 0x0008 /* Data Input Register */
#define STM32_CRYP_DOUT_OFFSET 0x000C /* Data Output Register */
#define STM32_CRYP_DMACR_OFFSET 0x0010 /* DMA Control Register */
#define STM32_CRYP_IMSCR_OFFSET 0x0014 /* Interrupt Mask Register */
#define STM32_CRYP_RISR_OFFSET 0x0018 /* Raw Interrupt Status Register */
#define STM32_CRYP_MISR_OFFSET 0x001C /* Masked Interrupt Status Register */
#define STM32_CRYP_K0LR_OFFSET 0x0020 /* CRYP key 0L Register */
#define STM32_CRYP_K0RR_OFFSET 0x0024 /* CRYP key 0R Register */
#define STM32_CRYP_K1LR_OFFSET 0x0028 /* CRYP key 1L Register */
#define STM32_CRYP_K1RR_OFFSET 0x002c /* CRYP key 1R Register */
#define STM32_CRYP_K2LR_OFFSET 0x0030 /* CRYP key 2L Register */
#define STM32_CRYP_K2RR_OFFSET 0x0034 /* CRYP key 2R Register */
#define STM32_CRYP_K3LR_OFFSET 0x0038 /* CRYP key 3L Register */
#define STM32_CRYP_K3RR_OFFSET 0x003c /* CRYP key 3R Register */
#define STM32_CRYP_IV0LR_OFFSET 0x0040 /* CRYP Init Vector 0L Register */
#define STM32_CRYP_IV0RR_OFFSET 0x0044 /* CRYP Init Vector 0R Register */
#define STM32_CRYP_IV1LR_OFFSET 0x0048 /* CRYP Init Vector 1L Register */
#define STM32_CRYP_IV1RR_OFFSET 0x004C /* CRYP Init Vector 1R Register */
#define STM32_CRYP_CSGCMCCM0R_OFFSET 0x0050 /* CRYP Context Swap Register 0R */
/* CRYP register addresses **************************************************/
#define STM32_CRYP_CR (STM32_CRYPTO_BASE + STM32_CRYP_CR_OFFSET)
#define STM32_CRYP_SR (STM32_CRYPTO_BASE + STM32_CRYP_SR_OFFSET)
#define STM32_CRYP_DIN (STM32_CRYPTO_BASE + STM32_CRYP_DIN_OFFSET)
#define STM32_CRYP_DOUT (STM32_CRYPTO_BASE + STM32_CRYP_DOUT_OFFSET)
#define STM32_CRYP_DMACR (STM32_CRYPTO_BASE + STM32_CRYP_DMACR_OFFSET)
#define STM32_CRYP_IMSCR (STM32_CRYPTO_BASE + STM32_CRYP_IMSCR_OFFSET)
#define STM32_CRYP_RISR (STM32_CRYPTO_BASE + STM32_CRYP_RISR_OFFSET)
#define STM32_CRYP_MISR (STM32_CRYPTO_BASE + STM32_CRYP_MISR_OFFSET)
#define STM32_CRYP_K0LR (STM32_CRYPTO_BASE + STM32_CRYP_K0LR_OFFSET)
#define STM32_CRYP_K0RR (STM32_CRYPTO_BASE + STM32_CRYP_K0RR_OFFSET)
#define STM32_CRYP_K1LR (STM32_CRYPTO_BASE + STM32_CRYP_K1LR_OFFSET)
#define STM32_CRYP_K1RR (STM32_CRYPTO_BASE + STM32_CRYP_K1RR_OFFSET)
#define STM32_CRYP_K2LR (STM32_CRYPTO_BASE + STM32_CRYP_K2LR_OFFSET)
#define STM32_CRYP_K2RR (STM32_CRYPTO_BASE + STM32_CRYP_K2RR_OFFSET)
#define STM32_CRYP_K3LR (STM32_CRYPTO_BASE + STM32_CRYP_K3LR_OFFSET)
#define STM32_CRYP_K3RR (STM32_CRYPTO_BASE + STM32_CRYP_K3RR_OFFSET)
#define STM32_CRYP_IV0LR (STM32_CRYPTO_BASE + STM32_CRYP_IV0LR_OFFSET)
#define STM32_CRYP_IV0RR (STM32_CRYPTO_BASE + STM32_CRYP_IV0RR_OFFSET)
#define STM32_CRYP_IV1LR (STM32_CRYPTO_BASE + STM32_CRYP_IV1LR_OFFSET)
#define STM32_CRYP_IV1RR (STM32_CRYPTO_BASE + STM32_CRYP_IV1RR_OFFSET)
#define STM32_CRYP_CSGCMCCM0R (STM32_CRYPTO_BASE + STM32_CRYP_CSGCMCCM0R_OFFSET)
/* CRYP register bit definitions ********************************************/
/* CRYP CR register */
#define CRYP_CR_GCMPH_SHIFT 16
#define CRYP_CR_GCMPH_MASK (0x3 << CRYP_CR_GCMPH_SHIFT)
# define CRYP_CR_GCMPH_INIT (0 << CRYP_CR_GCMPH_SHIFT)
# define CRYP_CR_GCMPH_HEADER (1 << CRYP_CR_GCMPH_SHIFT)
# define CRYP_CR_GCMPH_PAYLOAD (2 << CRYP_CR_GCMPH_SHIFT)
# define CRYP_CR_GCMPH_FINAL (3 << CRYP_CR_GCMPH_SHIFT)
#define CRYP_CR_CRYPEN (1 << 15)
#define CRYP_CR_FFLUSH (1 << 14)
#define CRYP_CR_KEYSIZE_SHIFT 8
#define CRYP_CR_KEYSIZE_MASK (0x3 << CRYP_CR_KEYSIZE_SHIFT)
# define CRYP_CR_KEYSIZE_128 (0 << CRYP_CR_KEYSIZE_SHIFT)
# define CRYP_CR_KEYSIZE_192 (1 << CRYP_CR_KEYSIZE_SHIFT)
# define CRYP_CR_KEYSIZE_256 (2 << CRYP_CR_KEYSIZE_SHIFT)
#define CRYP_CR_DATATYPE_SHIFT 6
#define CRYP_CR_DATATYPE_MASK (0x3 << CRYP_CR_DATATYPE_SHIFT)
# define CRYP_CR_DATATYPE_LE (0 << CRYP_CR_DATATYPE_SHIFT)
# define CRYP_CR_DATATYPE_BE (2 << CRYP_CR_DATATYPE_SHIFT)
/* ALGOMODE straddles bits [19, 5:3] of CRYP_CR */
#define CRYP_CR_ALGOMODE3_SHIFT 19
#define CRYP_CR_ALGOMODE3_MASK (0x1 << CRYP_CR_ALGOMODE3_SHIFT)
#define CRYP_CR_ALGOMODE_SHIFT 3
#define CRYP_CR_ALGOMODE_MASK ((0xf << CRYP_CR_ALGOMODE_SHIFT) \
| CRYP_CR_ALGOMODE3_MASK)
# define CRYP_CR_ALGOMODE_TDES_ECB ((0 << CRYP_CR_ALGOMODE3_SHIFT) \
| (0 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_TDES_CBC ((1 << CRYP_CR_ALGOMODE_SHIFT) \
| (0 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_DES_ECB ((2 << CRYP_CR_ALGOMODE_SHIFT) \
| (0 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_DES_CBC ((3 << CRYP_CR_ALGOMODE_SHIFT) \
| (0 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_AES_ECB ((4 << CRYP_CR_ALGOMODE_SHIFT) \
| (0 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_AES_CBC ((5 << CRYP_CR_ALGOMODE_SHIFT) \
| (0 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_AES_CTR ((6 << CRYP_CR_ALGOMODE_SHIFT) \
| (0 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_AES_KEY_PREP ((7 << CRYP_CR_ALGOMODE_SHIFT) \
| (0 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_AES_GCM ((8 << CRYP_CR_ALGOMODE_SHIFT) \
| (1 << CRYP_CR_ALGOMODE_SHIFT))
# define CRYP_CR_ALGOMODE_AES_CCM ((9 << CRYP_CR_ALGOMODE_SHIFT) \
| (1 << CRYP_CR_ALGOMODE_SHIFT))
#define CRYP_CR_ALGODIR_SHIFT 2
#define CRYP_CR_ALGODIR_MASK (1 << CRYP_CR_ALGODIR_SHIFT)
# define CRYP_CR_ALGODIR_ENCRYPT (0 << CRYP_CR_ALGODIR_SHIFT)
# define CRYP_CR_ALGODIR_DECRYPT (1 << CRYP_CR_ALGODIR_SHIFT)
/* All non-defined bits in CRYP_CR have to be set
* to the reset value (0x00000000). Following is mask for such
*/
#define CRYP_CR_RESET_MASK \
(CRYP_CR_ALGOMODE3_MASK | CRYP_CR_GCMPH_MASK | CRYP_CR_CRYPEN \
| CRYP_CR_FFLUSH | CRYP_CR_KEYSIZE_MASK | CRYP_CR_DATATYPE_MASK \
| CRYP_CR_ALGOMODE_MASK | CRYP_CR_ALGODIR_MASK)
/* CRYP SR register */
#define CRYP_SR_BUSY (1 << 4) /* BUSY */
#define CRYP_SR_OFFU (1 << 3) /* Output Fifo Full */
#define CRYP_SR_OFNE (1 << 2) /* Output Fifo Not Empty */
#define CRYP_SR_IFNF (1 << 1) /* Input Fifo Not Full */
#define CRYP_SR_IFEM (1 << 0) /* Input Fifo Empty */
/* CRYP DMACR register */
#define CRYP_DMACR_DOEN (1 << 1) /* DMA Output Enable */
#define CRYP_DMACR_DIEN (1 << 0) /* DMA Input Enable */
/* CRYP IMSCR register */
#define CRYP_IMSCR_OUTIM (1 << 1) /* Output Fifo Service Mask */
#define CRYP_IMSCR_INIM (1 << 0) /* Input Fifo Service Mask */
/* CRYP RISR register */
#define CRYP_RISR_OUTRIS (1 << 1)
#define CRYP_RISR_INRIS (1 << 0)
/* CRYP MISR register */
#define CRYP_MISR_OUTMIS (1 << 1)
#define CRYP_MISR_INMIS (1 << 0)
#endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32H7X3XX_CRYP_H */

View file

@ -0,0 +1,705 @@
/****************************************************************************
* arch/arm/src/stm32h7/stm32_aes.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/param.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
#include <nuttx/debug.h>
#include <nuttx/crypto/crypto.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/semaphore.h>
#include <arch/board/board.h>
#include "arm_internal.h"
#include "chip.h"
#include "stm32_rcc.h"
#include "stm32_aes.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define AES_BLOCK_SIZE 16
/* Any reserved bits in CRYP_CR must be kept at reset value (0x0) */
#define STM32AES_CLEAR_RESERVED_CR_BITS(regval) \
(regval & CRYP_CR_RESET_MASK)
/* #define CONFIG_STM32_CRYP_DEBUG */
#ifdef CONFIG_STM32_CRYP_DEBUG
#define cryp_getreg32(reg) stm32aes_getreg32(__FUNCTION__, __LINE__, reg)
#define cryp_putreg32(val, reg) stm32aes_putreg32(__FUNCTION__, __LINE__, val, reg)
#define crypinfo(func, line, format, ...) \
__arch_syslog(LOG_INFO, "%s:%d" format, func, line, ##__VA_ARGS__)
#else
#define crypinfo(func, line, format, ...)
#define cryp_getreg32(reg) getreg32(reg)
#define cryp_putreg32(val, reg) putreg32(val, reg)
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void stm32aes_enable(bool on);
static int stm32aes_setkey(const void *key, size_t keysize);
static void stm32aes_setiv(const void *iv);
static void stm32aes_encryptblock(void *block_out,
const void *block_in);
static int stm32aes_setup_cr(int mode, int encrypt,
const void *key, size_t keysize);
/****************************************************************************
* Private Data
****************************************************************************/
static mutex_t g_stm32aes_lock = NXMUTEX_INITIALIZER;
static bool g_stm32aes_initdone = false;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
#ifdef STM32_CRYP_DEBUG
struct rn
{
FAR const char *name;
uint32_t regaddr;
};
static struct rn stm32aes_regnames [] =
{
{
"RCC_AHB2RSTR",
STM32_RCC_AHB2RSTR,
},
{
"RCC_AHB2ENR",
STM32_RCC_AHB2ENR,
},
{
"CRYP_CR",
STM32_CRYP_CR,
},
{
"CRYP_SR",
STM32_CRYP_SR,
},
{
"CRYP_DIN",
STM32_CRYP_DIN,
},
{
"CRYP_DOUT",
STM32_CRYP_DOUT,
},
{
"CRYP_DMACR",
STM32_CRYP_DMACR,
},
{
"CRYP_IMSCR",
STM32_CRYP_IMSCR,
},
{
"CRYP_RISR",
STM32_CRYP_RISR,
},
{
"CRYP_MISR",
STM32_CRYP_MISR,
},
{
"CRYP_K0LR",
STM32_CRYP_K0LR,
},
{
"CRYP_K0RR",
STM32_CRYP_K0RR,
},
{
"CRYP_K1LR",
STM32_CRYP_K1LR,
},
{
"CRYP_K1RR",
STM32_CRYP_K1RR,
},
{
"CRYP_K2LR",
STM32_CRYP_K2LR,
},
{
"CRYP_K2RR",
STM32_CRYP_K2RR,
},
{
"CRYP_K3LR",
STM32_CRYP_K3LR,
},
{
"CRYP_K3RR",
STM32_CRYP_K3RR,
},
{
"CRYP_IV0LR",
STM32_CRYP_IV0LR,
},
{
"CRYP_IV0RR",
STM32_CRYP_IV0RR,
},
{
"CRYP_IV1LR",
STM32_CRYP_IV1LR,
},
{
"CRYP_IV1RR",
STM32_CRYP_IV1RR,
},
{
"CRYP_CSGCMCCM0R",
STM32_CRYP_CSGCMCCM0R,
},
};
const char *stm32aes_regname(uint32_t regaddr)
{
int i;
for (i = 0; i < nitems(stm32aes_regnames); ++i)
{
if (stm32aes_regnames[i].regaddr == regaddr)
{
return stm32aes_regnames[i].name;
}
}
return "???";
}
static uint32_t stm32aes_getreg32(const char *func, int line,
uint32_t regaddr)
{
const char *regname = stm32aes_regname(regaddr);
char buf[128];
uint32_t val;
val = getreg32(regaddr);
snprintf(buf, sizeof(buf), "%08" PRIx32 "(%s)<=%08" PRIx32 "",
regaddr, regname, val);
crypinfo(func, line, " %s", buf);
return val;
}
static void stm32aes_putreg32(const char *func, int line,
uint32_t val, uint32_t regaddr)
{
const char *regname = stm32aes_regname(regaddr);
char buf[128];
snprintf(buf, sizeof(buf), "%08" PRIx32 "(%s)=>%08" PRIx32 "",
regaddr, regname, val);
putreg32(val, regaddr);
crypinfo(func, line, " %s", buf);
}
#endif
static void stm32aes_enable(bool on)
{
uint32_t regval;
regval = cryp_getreg32(STM32_CRYP_CR);
if (on)
{
if (regval & CRYP_CR_CRYPEN)
{
return;
}
regval |= CRYP_CR_CRYPEN;
}
else
{
if (!(regval & CRYP_CR_CRYPEN))
{
return;
}
regval &= ~CRYP_CR_CRYPEN;
}
regval = STM32AES_CLEAR_RESERVED_CR_BITS(regval);
cryp_putreg32(regval, STM32_CRYP_CR);
}
static void stm32aes_wait_not_busy(void)
{
uint32_t regval;
do
{
regval = cryp_getreg32(STM32_CRYP_SR);
}
while (regval & CRYP_SR_BUSY);
}
static int stm32aes_setkey(const void *key, size_t keysize)
{
uint32_t *in = (uint32_t *)key;
stm32aes_wait_not_busy();
if (keysize == 32)
{
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_K0LR); /* [255:224] */
in++;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_K0RR); /* [223:192] */
in++;
}
if (keysize >= 24)
{
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_K1LR); /* [191:160] */
in++;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_K1RR); /* [159:128] */
in++;
}
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_K2LR); /* [127:96] */
in++;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_K2RR); /* [95:64] */
in++;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_K3LR); /* [63:32] */
in++;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_K3RR); /* [31:0] */
return 0;
}
static void stm32aes_setiv(const void *iv)
{
uint32_t *in = (uint32_t *)iv;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_IV0LR); /* [127:96] */
in++;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_IV0RR); /* [95:64] */
in++;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_IV1LR); /* [63:32] */
in++;
cryp_putreg32(__builtin_bswap32(*in), STM32_CRYP_IV1RR); /* [31:0] */
}
static void stm32aes_encryptblock(void *block_out,
const void *block_in)
{
uint32_t *in = (uint32_t *)block_in;
uint32_t *out = (uint32_t *)block_out;
cryp_putreg32(*in, STM32_CRYP_DIN);
in++;
cryp_putreg32(*in, STM32_CRYP_DIN);
in++;
cryp_putreg32(*in, STM32_CRYP_DIN);
in++;
cryp_putreg32(*in, STM32_CRYP_DIN);
stm32aes_wait_not_busy();
*out = cryp_getreg32(STM32_CRYP_DOUT);
out++;
*out = cryp_getreg32(STM32_CRYP_DOUT);
out++;
*out = cryp_getreg32(STM32_CRYP_DOUT);
out++;
*out = cryp_getreg32(STM32_CRYP_DOUT);
}
static void stm32aes_set_datatype(void)
{
uint32_t regval;
regval = cryp_getreg32(STM32_CRYP_CR);
regval |= CRYP_CR_DATATYPE_BE;
regval = STM32AES_CLEAR_RESERVED_CR_BITS(regval);
cryp_putreg32(regval, STM32_CRYP_CR);
}
static int stm32aes_setup_cr(int mode, int encrypt,
const void *key, size_t keysize)
{
int ret;
uint32_t regval = 0;
/** 1) Configure algorithm/chaining mode through ALGOMODE/AOGODIR
* bits; also set KEYSIZE
* - when decrypting and mode is AES-ECB or AES-CBC, an initial
* key derivation must be performed (see section 35.4.7)
*/
/* Set KEYSIZE field */
switch (keysize)
{
case 16:
regval |= CRYP_CR_KEYSIZE_128;
break;
case 24:
regval |= CRYP_CR_KEYSIZE_192;
break;
case 32:
regval |= CRYP_CR_KEYSIZE_256;
break;
default:
return -EINVAL;
}
/* Set symmetric key */
ret = stm32aes_setkey(key, keysize);
if (ret)
{
return -EINVAL;
}
/* If decrypting and mode is AES-ECB or AES-CBC need to perform
* key derivation first
*/
if (!encrypt)
{
/* Set DECRYPT field */
regval |= CRYP_CR_ALGODIR_DECRYPT;
if ((mode == AES_MODE_ECB) || (mode == AES_MODE_CBC))
{
regval |= CRYP_CR_ALGOMODE_AES_KEY_PREP;
cryp_putreg32(regval, STM32_CRYP_CR);
/* Start key derivation and wait for not BUSY */
stm32aes_enable(true);
stm32aes_wait_not_busy();
/* CRYPEN is automatically cleared. Clear
* ALGOMODE field to allow following code to set
* to the proper mode
*/
regval &= ~CRYP_CR_ALGOMODE_MASK;
}
}
else
{
/* Encrypting, make sure DECRYPT flag is cleared */
regval &= ~CRYP_CR_ALGODIR_DECRYPT;
}
switch (mode)
{
case AES_MODE_ECB:
regval |= CRYP_CR_ALGOMODE_AES_ECB;
break;
case AES_MODE_CBC:
regval |= CRYP_CR_ALGOMODE_AES_CBC;
break;
case AES_MODE_CTR:
regval |= CRYP_CR_ALGOMODE_AES_CTR;
break;
default:
return -EINVAL;
}
regval = STM32AES_CLEAR_RESERVED_CR_BITS(regval);
cryp_putreg32(regval, STM32_CRYP_CR);
stm32aes_wait_not_busy();
stm32aes_set_datatype();
stm32aes_wait_not_busy();
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int stm32_aesreset(void)
{
irqstate_t flags;
uint32_t regval;
flags = enter_critical_section();
/* Clear/set AHB2RSTR to reset CRYP peripheral */
regval = cryp_getreg32(STM32_RCC_AHB2RSTR);
regval |= RCC_AHB2RSTR_CRYPTRST;
cryp_putreg32(regval, STM32_RCC_AHB2RSTR);
regval &= ~RCC_AHB2RSTR_CRYPTRST;
cryp_putreg32(regval, STM32_RCC_AHB2RSTR);
leave_critical_section(flags);
return OK;
}
int stm32_aesinitialize(void)
{
uint32_t regval;
regval = cryp_getreg32(STM32_RCC_AHB2ENR);
regval |= RCC_AHB2ENR_CRYPTEN;
cryp_putreg32(regval, STM32_RCC_AHB2ENR);
stm32aes_enable(false);
return OK;
}
static void stm32aes_flush_fifos(void)
{
uint32_t regval;
regval = cryp_getreg32(STM32_CRYP_CR);
regval |= CRYP_CR_FFLUSH;
regval = STM32AES_CLEAR_RESERVED_CR_BITS(regval);
cryp_putreg32(regval, STM32_CRYP_CR);
}
/* See section 35.4.5 CRYP procedure to perform a cipher operation:
* 0) Clear CRYPEN bit
* 1) Configure algorithm/chaining mode through ALGOMODE/AOGODIR
* bits; also set KEYSIZE
* - when decrypting and mode is AES-ECB or AES-CBC, an initial
* key derivation must be performed (see section 35.4.7)
* 2) When previous step is complete (and when applicable), write
* key into CRYP_KxL/R registers (see section 35.4.17)
* 3) Configure DATATYPE
* 4) When required(eg for CBC or CTR chaining modes), write the
* initialization vectors into CRYP_IVx(L/R)R.
* 5) Flush the IN/OUT FIFOS by setting FFLUSH.
*
* Warning: If ECB/CBC mode is selected and data is not a multiple
* of 64 bits (for DES) or 128 bits (for AES), the 2nd and last
* block management is more comples; see Section 35.4.8
*
* Appending data using the CPU in Polling mode
* 1) Enable the cryptographic processor by setting to 1 the CRYPEN
* bit in the CRYP_CR register.
* 2) Write data in the IN FIFO (one block or until the FIFO is full).
* 3) Repeat the following sequence until the second last block of
* data has been processed:
* a) Wait until the not-empty-flag OFNE is set to 1, then read
* the OUT FIFO (one block or until the FIFO is empty).
* b) Wait until the not-full-flag IFNF is set to 1, then write
* the IN FIFO (one block or until the FIFO is full) except
* if it is the last block.
* 4) The BUSY bit is set automatically by the cryptographic processor.
* At the end of the processing, the BUSY bit returns to 0 and both
* FIFOs are empty (IN FIFO empty flag IFEM = 1 and OUT FIFO not
* empty flag OFNE = 0).
* 5) If the next processing block is the last block, the CPU must pad
* (when applicable) the data with zeroes to obtain a complete block
* 6) When the operation is complete, the cryptographic processor can
* be disabled by clearing the CRYPEN bit in CRYP_CR register.
*
* 35.4.7 Preparing the CRYP AES key for decryption:
*
* When performing an AES ECB or CBC decryption, the AES key
* has to be prepared. Indeed, in AES encryption the round 0 key
* is the one stored in the key registers, and AES decryption must
* start using the last round key. Hence, as the encryption key
* is stored in memory, a special key scheduling must be performed
* to obtain the decryption key. This preparation is not required
* in any other AES modes than ECB or CBC decryption.
*
* When the cryptographic processor is disabled (CRYPEN = 0),
* the CRYP key preparation process is performed as follows:
* 1) Program ALGOMODE bits to 0x7 and ALGODIR to 0x0 in CRYP_CR.
* In addition, configure the key length with the KEYSIZE bits.
* 2) Write the symmetric key to the CRYP_KxL/R registers, as
* described in Section 35.4.17: CRYP key registers.
* 3) Enable the cryptographic processor by setting the CRYPEN bit
* in the CRYP_CR register. It immediately starts an AES round
* for key preparation (BUSY = 1).
* 4) Wait until the BUSY bit is cleared in the CRYP_SR register.
* Then update ALGOMODE bits in the CRYP_CR register to select
* the correct chaining mode, that is 0x4 for ECB or 0x5 for CBC.
* 5) The AES key is available in the CRYP key registers, ready
* to use for decryption.
* Note: As the CRYPEN bitfield is reset by hardware at the end of
* the key preparation, the application software must set it
* again for the next operation.
* The latency of the key preparation operation is 14, 16 or 18
* clock cycles depending on the key size (128, 192 or 256 bits).
*
* 35.4.8 CRYP stealing and data padding
*
* When using DES or AES algorithm in ECB or CBC modes to manage
* messages that are not multiple of the block size (64 bits for DES,
* 128 bits for AES), use ciphertext stealing techniques such as those
* described in NIST Special Publication 800-38A, Recommendation
* for Block Cipher Modes of Operation: Three Variants of Ciphertext
* Stealing for CBC Mode. Since the cryptographic processor does not
* implement such techniques, the last two blocks must be handled in
* a special way by the application.
*
* Note: Ciphertext stealing techniques are not documented in this
* reference manual.
*
* Similarly, when the AES algorithm is used in other modes than ECB
* or CBC, incomplete input data blocks (i.e. block shorter than 128
* bits) have to be padded with zeroes by the application prior to
* encryption (i.e. extra bits should be appended to the trailing end
* of the data string). After decryption, the extra bits have to be
* discarded. The cryptographic processor does not implement automatic
* data padding operation to the last block, so the application should
* follow the recommendation given in Section 35.4.5: CRYP procedure to
* perform a cipher operation to manage messages that are not multiple
* of 128 bits.
*
* Note: Padding data are swapped in a similar way as normal data,
* according to the DATATYPE field in CRYP_CR register (see
* Section 35.4.16: CRYP data registers and data swapping for
* details).
*/
int aes_cypher(void *out, const void *in, size_t size,
const void *iv, const void *key, size_t keysize,
int mode, int encrypt)
{
int ret = OK;
/* CRYP peripheral clock is already enabled;
* make sure it gets reset (once)
*/
if (!g_stm32aes_initdone)
{
ret = stm32_aesreset();
if (ret < 0)
{
return ret; /* AES init failed */
}
g_stm32aes_initdone = true;
}
if ((size & (AES_BLOCK_SIZE - 1)) != 0)
{
return -EINVAL;
}
if (keysize != 16 && keysize != 24 && keysize != 32)
{
return -EINVAL;
}
ret = nxmutex_lock(&g_stm32aes_lock);
if (ret < 0)
{
return ret;
}
/* AES must be disabled before changing mode, key or IV. */
stm32aes_enable(false);
ret = stm32aes_setup_cr(mode, encrypt, key, keysize);
if (ret < 0)
{
goto out;
}
if (iv != NULL)
{
stm32aes_setiv(iv);
}
stm32aes_wait_not_busy();
stm32aes_flush_fifos();
stm32aes_wait_not_busy();
stm32aes_enable(true);
while (size)
{
stm32aes_encryptblock(out, in);
out = (uint8_t *)out + AES_BLOCK_SIZE;
in = (uint8_t *)in + AES_BLOCK_SIZE;
size -= AES_BLOCK_SIZE;
}
stm32aes_enable(false);
out:
nxmutex_unlock(&g_stm32aes_lock);
return ret;
}

View file

@ -0,0 +1,58 @@
/****************************************************************************
* arch/arm/src/stm32h7/stm32_aes.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_STM32H7_STM32_AES_H
#define __ARCH_ARM_SRC_STM32H7_STM32_AES_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include "chip.h"
/* For simplicity support STM32753ZI, not sure what other STM32H7
* variants include CRYP
*/
#ifdef CONFIG_STM32H7_HAVE_CRYP
# include "hardware/stm32h7xxxx_cryp.h"
#else
# error "Unknown chip for AES"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Inline Functions
****************************************************************************/
#endif /* __ARCH_ARM_SRC_STM32H7_STM32_AES_H */

View file

@ -0,0 +1,163 @@
/****************************************************************************
* arch/arm/src/stm32h7/stm32_crypto.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/debug.h>
#include <errno.h>
#include <stdint.h>
#include <crypto/cryptodev.h>
#include <crypto/xform.h>
#include <nuttx/crypto/crypto.h>
/****************************************************************************
* Private Data
****************************************************************************/
static uint32_t g_stm32_sesnum = 0;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_newsession
*
* Description:
* create new session for crypto.
*
****************************************************************************/
static int stm32_newsession(uint32_t *sid, struct cryptoini *cri)
{
int klen;
if (sid == NULL || cri == NULL)
{
return -EINVAL;
}
switch (cri->cri_alg)
{
case CRYPTO_AES_CBC:
*sid = g_stm32_sesnum++;
break;
case CRYPTO_AES_CTR:
klen = cri->cri_klen / 8 - 4;
if ((klen != 16) && (klen != 24) && (klen != 32))
{
/* stm32h7 aes-ctr key bits support 128, 192, or 256 */
return -EINVAL;
}
*sid = g_stm32_sesnum++;
break;
default:
return -EINVAL;
}
return OK;
}
/****************************************************************************
* Name: stm32_freesession
*
* Description:
* free session.
*
****************************************************************************/
static int stm32_freesession(uint64_t tid)
{
return 0;
}
/****************************************************************************
* Name: stm32_process
*
* Description:
* process session to use hardware algorithm.
*
****************************************************************************/
static int stm32_process(struct cryptop *crp)
{
struct cryptodesc *crd;
uint8_t iv[AESCTR_BLOCKSIZE];
for (crd = crp->crp_desc; crd; crd = crd->crd_next)
{
switch (crd->crd_alg)
{
case CRYPTO_AES_CBC:
return aes_cypher(crp->crp_dst, crp->crp_buf, crd->crd_len,
crp->crp_iv, crd->crd_key, 16,
AES_MODE_CBC, crd->crd_flags & CRD_F_ENCRYPT);
case CRYPTO_AES_CTR:
memcpy(iv, crd->crd_key + crd->crd_klen / 8 - AESCTR_NONCESIZE,
AESCTR_NONCESIZE);
memcpy(iv + AESCTR_NONCESIZE, crp->crp_iv, AESCTR_IVSIZE);
memcpy(iv + AESCTR_NONCESIZE + AESCTR_IVSIZE,
(uint8_t *)crp->crp_iv + AESCTR_IVSIZE, 4);
return aes_cypher(crp->crp_dst, crp->crp_buf,
crd->crd_len, iv, crd->crd_key,
crd->crd_klen / 8 - AESCTR_NONCESIZE,
AES_MODE_CTR, crd->crd_flags & CRD_F_ENCRYPT);
default:
return -EINVAL;
}
}
return OK;
}
/****************************************************************************
* Name: hwcr_init
*
* Description:
* register the hardware crypto driver.
*
****************************************************************************/
void hwcr_init(void)
{
int hwcr_id;
int algs[CRYPTO_ALGORITHM_MAX + 1];
hwcr_id = crypto_get_driverid(0);
DEBUGASSERT(hwcr_id >= 0);
memset(algs, 0, sizeof(algs));
algs[CRYPTO_AES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_AES_CTR] = CRYPTO_ALG_FLAG_SUPPORTED;
crypto_register(hwcr_id, algs, stm32_newsession,
stm32_freesession, stm32_process);
}

View file

@ -326,6 +326,12 @@ static inline void rcc_enableahb2(void)
regval |= RCC_AHB2ENR_RNGEN;
#endif
#ifdef CONFIG_STM32H7_CRYP
/* Cryptographic clock enable */
regval |= RCC_AHB2ENR_CRYPTEN;
#endif
putreg32(regval, STM32_RCC_AHB2ENR); /* Enable peripherals */
}

View file

@ -0,0 +1,56 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_NSH_DISABLE_IFCONFIG is not set
# CONFIG_NSH_DISABLE_PS is not set
# CONFIG_STANDARD_SERIAL is not set
# CONFIG_TESTING_CRYPTO_3DES_CBC is not set
# CONFIG_TESTING_CRYPTO_AES_XTS is not set
# CONFIG_TESTING_CRYPTO_HMAC is not set
CONFIG_ALLOW_BSD_COMPONENTS=y
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="nucleo-h753zi"
CONFIG_ARCH_BOARD_NUCLEO_H753ZI=y
CONFIG_ARCH_CHIP="stm32h7"
CONFIG_ARCH_CHIP_STM32H753ZI=y
CONFIG_ARCH_CHIP_STM32H7=y
CONFIG_ARCH_CHIP_STM32H7_CORTEXM7=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARMV7M_DCACHE=y
CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y
CONFIG_ARMV7M_DTCM=y
CONFIG_ARMV7M_ICACHE=y
CONFIG_BOARD_LOOPSPERMSEC=43103
CONFIG_BUILTIN=y
CONFIG_CRYPTO=y
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_CRYPTODEV=y
CONFIG_CRYPTO_CRYPTODEV_HARDWARE=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INTELHEX_BINARY=y
CONFIG_LINE_MAX=64
CONFIG_MM_REGIONS=4
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=245760
CONFIG_RAM_START=0x20010000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_STM32H7_CRYP=y
CONFIG_STM32H7_USART3=y
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=0
CONFIG_TESTING_CRYPTO=y
CONFIG_TESTING_CRYPTO_STACKSIZE=4096
CONFIG_USART3_SERIAL_CONSOLE=y