arch/arm/src/stm32h7: Extend crypto interface to support HW HASH

Add stm32h7 support for HASH HW accelerator for MD5, SHA1, SHA2-224,
and SHA2-256 as well as their HMAC variants.

Signed-off-by: Peter Barada <peter.barada@gmail.com>
This commit is contained in:
Peter Barada 2026-07-20 13:46:09 -04:00 committed by Alin Jerpelea
parent 13c6c7032e
commit c0e796e55d
5 changed files with 758 additions and 51 deletions

View file

@ -280,9 +280,10 @@ config ARCH_CHIP_STM32H750VB
select STM32H7_IO_CONFIG_V
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7+M4, 128 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP100
with cryptographic & hash accelerator, LQFP100
config ARCH_CHIP_STM32H750ZB
bool "STM32H750ZB"
@ -291,9 +292,10 @@ config ARCH_CHIP_STM32H750ZB
select STM32H7_IO_CONFIG_Z
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7+M4, 128 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP144
with cryptographic & hash accelerator, LQFP144
config ARCH_CHIP_STM32H750IB
bool "STM32H750IB"
@ -302,9 +304,10 @@ config ARCH_CHIP_STM32H750IB
select STM32H7_IO_CONFIG_I
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7+M4, 128 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP176 or UFBGA176+25
with cryptographic & hash accelerator, LQFP176 or UFBGA176+25
config ARCH_CHIP_STM32H750XB
bool "STM32H750XB"
@ -313,9 +316,10 @@ config ARCH_CHIP_STM32H750XB
select STM32H7_IO_CONFIG_X
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7+M4, 128 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, TFBGA240+25
with cryptographic & hash accelerator, TFBGA240+25
config ARCH_CHIP_STM32H753AI
bool "STM32H753AI"
@ -324,9 +328,10 @@ config ARCH_CHIP_STM32H753AI
select STM32H7_IO_CONFIG_A
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, UFBGA169
with cryptographic & hash accelerator, UFBGA169
config ARCH_CHIP_STM32H753BI
bool "STM32H753BI"
@ -335,9 +340,10 @@ config ARCH_CHIP_STM32H753BI
select STM32H7_IO_CONFIG_B
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP208
with cryptographic & hash accelerator, LQFP208
config ARCH_CHIP_STM32H753II
bool "STM32H753II"
@ -346,9 +352,10 @@ config ARCH_CHIP_STM32H753II
select STM32H7_IO_CONFIG_I
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP176/UFBGA176
with cryptographic & hash accelerator, LQFP176/UFBGA176
config ARCH_CHIP_STM32H753VI
bool "STM32H753VI"
@ -357,9 +364,10 @@ config ARCH_CHIP_STM32H753VI
select STM32H7_IO_CONFIG_V
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP100/TFBGA100
with cryptographic & hash accelerator, LQFP100/TFBGA100
config ARCH_CHIP_STM32H753XI
bool "STM32H753XI"
@ -368,9 +376,10 @@ config ARCH_CHIP_STM32H753XI
select STM32H7_IO_CONFIG_X
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, TFBGA240
with cryptographic & hash accelerator, TFBGA240
config ARCH_CHIP_STM32H753ZI
bool "STM32H753ZI"
@ -379,9 +388,10 @@ config ARCH_CHIP_STM32H753ZI
select STM32H7_IO_CONFIG_Z
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP144
with cryptographic & hash accelerator, LQFP144
config ARCH_CHIP_STM32H7B3LI
bool "STM32H7B3LI"
@ -391,9 +401,10 @@ config ARCH_CHIP_STM32H7B3LI
select STM32_HAVE_SMPS
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1376 Kb SRAM,
with cryptographic accelerator, TFBGA225
with cryptographic & hash accelerator, TFBGA225
config ARCH_CHIP_STM32H755II
bool "STM32H755II"
@ -404,9 +415,10 @@ config ARCH_CHIP_STM32H755II
select STM32_HAVE_FDCAN2
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, LQFP176/UFBGA176
with cryptographic & hash accelerator, LQFP176/UFBGA176
config ARCH_CHIP_STM32H755XI
bool "STM32H755XI"
@ -417,9 +429,10 @@ config ARCH_CHIP_STM32H755XI
select STM32_HAVE_FDCAN2
select STM32_HAVE_CRYP
select STM32_HAVE_IP_CRYPTO_H7
select STM32_HAVE_HASH
---help---
STM32 H7 Cortex M7, 2048 Kb FLASH, 1024K Kb SRAM,
with cryptographic accelerator, TFBGA240
with cryptographic & hash accelerator, TFBGA240
endchoice # STM32 H7 Chip Selection

View file

@ -0,0 +1,180 @@
/****************************************************************************
* arch/arm/src/stm32h7/hardware/stm32h7xxxx_hash.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_STM32H7XXXX_HASH_H
#define __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32H7XXXX_HASH_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
****************************************************************************/
/* HASH register offsets ****************************************************/
#define STM32_HASH_CR_OFFSET 0x0000 /* Control Register */
#define STM32_HASH_DIN_OFFSET 0x0004 /* Data Input Register */
#define STM32_HASH_STR_OFFSET 0x0008 /* Start Register */
#define STM32_HASH_HRA0_OFFSET 0x000C /* Alias Digest Reg 0 */
#define STM32_HASH_HRA1_OFFSET 0x0010 /* Alias Digest Reg 1 */
#define STM32_HASH_HRA2_OFFSET 0x0014 /* Alias Digest Reg 2 */
#define STM32_HASH_HRA3_OFFSET 0x0018 /* Alias Digest Reg 3 */
#define STM32_HASH_HRA4_OFFSET 0x001C /* Alias Digest Reg 4 */
#define STM32_HASH_IMR_OFFSET 0x0020 /* Interrupt Mask Register */
#define STM32_HASH_SR_OFFSET 0x0024 /* Status Register */
#define STM32_HASH_CSR0_OFFSET 0x00f8 /* Context swap Register 0 */
#define STM32_HASH_CSRx_OFFSET(x) (STM32_HASH_CSR0_OFFSET + 4 * (x))
#define STM32_HASH_HR0_OFFSET 0x0310 /* Digest Reg 0 */
#define STM32_HASH_HR1_OFFSET 0x0314 /* Digest Reg 1 */
#define STM32_HASH_HR2_OFFSET 0x0318 /* Digest Reg 2 */
#define STM32_HASH_HR3_OFFSET 0x031c /* Digest Reg 3 */
#define STM32_HASH_HR4_OFFSET 0x0320 /* Digest Reg 4 */
#define STM32_HASH_HR5_OFFSET 0x0324 /* Supplemental Digest Reg 5 */
#define STM32_HASH_HR6_OFFSET 0x0328 /* Supplemental Digest Reg 6 */
#define STM32_HASH_HR7_OFFSET 0x032C /* Supplemental Digest Reg 7 */
/* HASH register addresses **************************************************/
#define STM32_HASH_CR (STM32_HASH_BASE + STM32_HASH_CR_OFFSET)
#define STM32_HASH_DIN (STM32_HASH_BASE + STM32_HASH_DIN_OFFSET)
#define STM32_HASH_STR (STM32_HASH_BASE + STM32_HASH_STR_OFFSET)
#define STM32_HASH_DMACR (STM32_HASH_BASE + STM32_HASH_DMACR_OFFSET)
#define STM32_HASH_HRA0 (STM32_HASH_BASE + STM32_HASH_HRA0_OFFSET)
#define STM32_HASH_HRA1 (STM32_HASH_BASE + STM32_HASH_HRA1_OFFSET)
#define STM32_HASH_HRA2 (STM32_HASH_BASE + STM32_HASH_HRA2_OFFSET)
#define STM32_HASH_HRA3 (STM32_HASH_BASE + STM32_HASH_HRA3_OFFSET)
#define STM32_HASH_HRA4 (STM32_HASH_BASE + STM32_HASH_HRA4_OFFSET)
#define STM32_HASH_IMR (STM32_HASH_BASE + STM32_HASH_IMR_OFFSET)
#define STM32_HASH_SR (STM32_HASH_BASE + STM32_HASH_SR_OFFSET)
#define STM32_HASH_CSR0 (STM32_HASH_BASE + STM32_HASH_CSR0_OFFSET)
#define STM32_HASH_HR0 (STM32_HASH_BASE + STM32_HASH_HR0_OFFSET)
#define STM32_HASH_HR1 (STM32_HASH_BASE + STM32_HASH_HR1_OFFSET)
#define STM32_HASH_HR2 (STM32_HASH_BASE + STM32_HASH_HR2_OFFSET)
#define STM32_HASH_HR3 (STM32_HASH_BASE + STM32_HASH_HR3_OFFSET)
#define STM32_HASH_HR4 (STM32_HASH_BASE + STM32_HASH_HR4_OFFSET)
#define STM32_HASH_HR5 (STM32_HASH_BASE + STM32_HASH_HR5_OFFSET)
#define STM32_HASH_HR6 (STM32_HASH_BASE + STM32_HASH_HR6_OFFSET)
#define STM32_HASH_HR7 (STM32_HASH_BASE + STM32_HASH_HR7_OFFSET)
/* HASH register bit definitions ********************************************/
/* HASH CR register */
#define HASH_CR_LKEY_SHIFT 16
#define HASH_CR_LKEY_MASK (1 << HASH_CR_LKEY_SHIFT)
#define HASH_CR_LKEY_LE_64 (0 << HASH_CR_LKEY_SHIFT)
#define HASH_CR_LKEY_GT_64 (1 << HASH_CR_LKEY_SHIFT)
#define HASH_CR_MDMAT_SHIFT 13
#define HASH_CR_MDMAT_MASK (1 << HASH_CR_MDMAT_SHIFT)
#define HASH_CR_MDMAT_AUTO_SET (0 << HASH_CR_MDMAT_SHIFT)
#define HASH_CR_MDMAT_NOT_AUTO_SET (0 << HASH_CR_MDMAT_SHIFT)
#define HASH_CR_DINNE_SHIFT 12
#define HASH_CR_DINNE_MASK (1 << HASH_CR_DINNE_SHIFT)
#define HASH_CR_DINNE_EMPTY (0 << HASH_CR_DINNE_SHIFT)
#define HASH_CR_DINNE_NOT_EMPTY (1 << HASH_CR_DINNE_SHIFT)
#define HASH_CR_NBW_SHIFT 8
/* If 0 && DINNE == 0 then no word pushed; if DINNEset then one word pushed.
* If 1 then two words pushed (one in HASH_DIN and other in FIFO)
*/
#define HASH_CR_NBW_MASK (0xf << HASH_CR_NBW_SHIFT)
#define HASH_CR_ALGO_MASK ((1 << 18) | (1 << 7))
#define HASH_CR_ALGO_SHA1 ((0 << 18) | (0 << 7))
#define HASH_CR_ALGO_MD5 ((0 << 18) | (1 << 7))
#define HASH_CR_ALGO_SHA2_224 ((1 << 18) | (0 << 7))
#define HASH_CR_ALGO_SHA2_256 ((1 << 18) | (1 << 7))
#define HASH_CR_MODE_SHIFT 6
#define HASH_CR_MODE_MASK (1 << HASH_CR_MODE_SHIFT)
#define HASH_CR_MODE_HASH (0 << HASH_CR_MODE_SHIFT)
#define HASH_CR_MODE_HMAC (1 << HASH_CR_MODE_SHIFT)
#define HASH_CR_DATATYPE_SHIFT 4
#define HASH_CR_DATATYPE_MASK (0x3 << HASH_CR_DATATYPE_SHiFT)
#define HASH_CR_DATATYPE_32 (0 << HASH_CR_DATATYPE_SHIFT)
#define HASH_CR_DATATYPE_16 (1 << HASH_CR_DATATYPE_SHIFT)
#define HASH_CR_DATATYPE_8 (2 << HASH_CR_DATATYPE_SHIFT)
#define HASH_CR_DATATYPE_1 (3 << HASH_CR_DATATYPE_SHIFT)
#define HASH_CR_DMAE_SHIFT 3
#define HASH_CR_DMAE_MASK (1 << HASH_CR_DMAE_SHIFT)
#define HASH_CR_DMAE_DISABLE (0 << HASH_CR_DMAE_SHIFT)
#define HASH_CR_DMAE_ENABLE (1 << HASH_CR_DMAE_SHIFT)
#define HASH_CR_INIT_SHIFT 2
#define HASH_CR_INIT_MASK (1 << HASH_CR_INIT_SHIFT)
#define HASH_CR_INIT HASH_CR_INIT_MASK
/* HASH STR register */
#define HASH_STR_DCAL_SHIFT 8
#define HASH_STR_DCAL (1 << HASH_STR_DCAL_SHIFT)
#define HASH_STR_DCAL_START HASH_STR_DCAL_MASK
#define HASH_STR_NBLW_SHIFT 0
#define HASH_STR_NBLW_MASK (0x1F << HASH_STR_NBLW_SHIFT)
#define HASH_STR_NBLW(n) (((n) << HASH_STR_NBLW_SHIFT) \
& HASH_STR_NBLW_MASK)
#define HASH_STR_NBLW_BYTES(n) ((((n) * 8) << HASH_STR_NBLW_SHIFT) \
& HASH_STR_NBLW_MASK)
/* HASH IMR register */
#define HASH_IMR_DCIE_SHIFT 1
#define HASH_IMR_DCIE_MASK (1 << HASH_IMR_DCIE_SHIFT)
#define HASH_IMR_DCIE_DISABLE (0 << HASH_IMR_DCIE_SHIFT)
#define HASH_IMR_DCIE_ENABLE (1 << HASH_IMR_DCIE_SHIFT)
#define HASH_IMR_DINIE_SHIFT 1
#define HASH_IMR_DINIE_MASK (1 << HASH_IMR_DINIE_SHIFT)
#define HASH_IMR_DINIE_DISABLE (0 << HASH_IMR_DINIE_SHIFT)
#define HASH_IMR_DINIE_ENABLE (1 << HASH_IMR_DINIE_SHIFT)
/* HASH SR register */
#define HASH_SR_BUSY_SHIFT 3
#define HASH_SR_BUSY_MASK (1 << HASH_SR_BUSY_SHIFT)
#define HASH_SR_BUSY HASH_SR_BUSY_MASK
#define HASH_SR_DMAS_SHIFT 2
#define HASH_SR_DMAS_MASK (1 << HASH_SR_DMAS_SHIFT)
#define HASH_SR_DMAS HASH_SR_DMAS_MASK
#define HASH_SR_DCIS_SHIFT 1
#define HASH_SR_DCIS_MASK (1 << HASH_SR_DCIS_SHIFT)
#define HASH_SR_DCIS HASH_SR_DCIS_MASK
#define HASH_SR_DINIS_SHIFT 0
#define HASH_SR_DINIS_MASK (1 << HASH_SR_DINIS_SHIFT)
#define HASH_SR_DINIS HASH_SR_DINIS_MASK
#endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32H7XXXX_HASH_H */

View file

@ -37,6 +37,7 @@
#include "arm_internal.h"
#include "hardware/stm32h7x3xx_rcc.h"
#include "hardware/stm32h7xxxx_crc.h"
#include "hardware/stm32h7xxxx_hash.h"
/* Following constants used in reverse32() to reverse
* bit order of 32-bit value
@ -46,10 +47,19 @@
#define REV32_CONST3 0x0F0F0F0F
#define REV32_CONST4 0x00FF00FF
#define STM32H7_CRC_RESET_TIMEOUT 1000 /* should be enough loops to reset */
/* number polling iterations to wait for CRC to reset */
#define STM32H7_CRC_TIMEOUT 1000 /* should be enough... */
/* number polling iterations to wait for HASH to set CDIS/DINIS,
* or to clear BUSY
*/
#define STM32H7_HASH_TIMEOUT 1000 /* should be enough... */
#define CRC32_XOR_VALUE 0xFFFFFFFFUL
#undef CONFIG_STM32_CRYPTO_DEBUG
/* #define CONFIG_STM32_CRYPTO_DEBUG */
#ifdef CONFIG_STM32_CRYPTO_DEBUG
#define stm32cryptoinfo(format, ...) \
@ -78,6 +88,7 @@
****************************************************************************/
static bool g_stm32_crc_initialized = false;
static bool g_stm32_hash_initialized = false;
static uint32_t g_stm32_sesnum = 0;
@ -90,8 +101,17 @@ struct stm32_crypto_data
{
struct stm32_crc32
{
uint32_t init; /* init/interim CRC value */
uint32_t init; /* init/interim CRC value */
} crc;
struct stm32_hash
{
bool hmac; /* true if hmac */
uint8_t *key; /* hmac key */
uint32_t klen; /* hmac key length */
uint32_t rdata; /* unaligned hash data */
uint32_t dsize; /* # byte sin digest */
uint32_t rlen; /* # bytes accumulated in rdata */
} hash;
} u;
struct stm32_crypto_data *hw_next;
};
@ -116,38 +136,115 @@ struct rn
static struct rn stm32_crypto_regnames [] =
{
{
"RCC_AHB4RSTR",
STM32_RCC_AHB4RSTR,
"RCC_AHB4RSTR", STM32_RCC_AHB4RSTR,
},
{
"RCC_AHB4ENR",
STM32_RCC_AHB4ENR,
"RCC_AHB4ENR", STM32_RCC_AHB4ENR,
},
{
"CRC_DR",
STM32_CRC_DR,
"CRC_DR", STM32_CRC_DR,
},
{
"CRC_IDR",
STM32_CRC_IDR,
"CRC_IDR", STM32_CRC_IDR,
},
{
"CRC_CR",
STM32_CRC_CR,
"CRC_CR", STM32_CRC_CR,
},
{
"CRC_INIT",
STM32_CRC_INIT,
"CRC_INIT", STM32_CRC_INIT,
},
{
"CRC_POL",
STM32_CRC_POL,
"CRC_POL", STM32_CRC_POL,
},
{
"RCC_AHB2RSTR", STM32_RCC_AHB2RSTR,
},
{
"RCC_AHB2ENR", STM32_RCC_AHB2ENR,
},
{
"HASH_CR", STM32_HASH_CR,
},
{
"HASH_DIN", STM32_HASH_DIN,
},
{
"HASH_STR", STM32_HASH_STR,
},
{
"HASH_HRA0", STM32_HASH_HRA0,
},
{
"HASH_HRA1", STM32_HASH_HRA1,
},
{
"HASH_HRA2", STM32_HASH_HRA2,
},
{
"HASH_HRA3", STM32_HASH_HRA3,
},
{
"HASH_HRA4", STM32_HASH_HRA4,
},
{
"HASH_HR0", STM32_HASH_HR0,
},
{
"HASH_HR1", STM32_HASH_HR1,
},
{
"HASH_HR2", STM32_HASH_HR2,
},
{
"HASH_HR3", STM32_HASH_HR3,
},
{
"HASH_HR4", STM32_HASH_HR4,
},
{
"HASH_HR5", STM32_HASH_HR5,
},
{
"HASH_HR6", STM32_HASH_HR6,
},
{
"HASH_HR7", STM32_HASH_HR7,
},
{
"HASH_IMR", STM32_HASH_IMR,
},
{
"HASH_SR", STM32_HASH_SR,
},
{
"HASH_CSR0", STM32_HASH_CSR0,
},
};
@ -237,18 +334,42 @@ static void stm32_crypto_putreg32(const char *func, int line,
* Name: stm32_wait_for_clr
*
* Description:
* wait for a bitmask to clear in HW register
* wait for all bits in bitmask to clear in HW register
*
****************************************************************************/
static int stm32_wait_for_clr(uintptr_t regaddr, uint32_t bitmask,
uint32_t timeout)
uint32_t timeout)
{
uint32_t regval;
while (timeout--)
{
regval = stm32crypto_getreg32(regaddr);
if (regval & bitmask)
if ((regval & bitmask) == 0)
{
return 0;
}
}
return -ETIMEDOUT;
}
/****************************************************************************
* Name: stm32_wait_for_set
*
* Description:
* wait for all bits in bitmask to set in HW register
*
****************************************************************************/
static int stm32_wait_for_set(uintptr_t regaddr, uint32_t bitmask,
uint32_t timeout)
{
uint32_t regval;
while (timeout--)
{
regval = stm32crypto_getreg32(regaddr);
if ((regval & bitmask) == bitmask)
{
return 0;
}
@ -317,7 +438,7 @@ static int crc32_init(struct stm32_crypto_data *sw)
stm32crypto_putreg32(regval, STM32_CRC_CR);
ret = stm32_wait_for_clr(STM32_CRC_CR, CRC_CR_RESET,
STM32H7_CRC_RESET_TIMEOUT);
STM32H7_CRC_TIMEOUT);
return ret;
}
@ -383,6 +504,250 @@ static int crc32_final(struct stm32_crypto_data *sw, caddr_t digest)
return 0;
}
static int hash_init(struct stm32_crypto_data *sw)
{
irqstate_t flags;
uint32_t regval;
stm32cryptoinfo("");
if (!g_stm32_hash_initialized)
{
g_stm32_hash_initialized = true;
flags = enter_critical_section();
/* Clear/set AHB2RSTR to reset CRYP peripheral */
regval = stm32crypto_getreg32(STM32_RCC_AHB2RSTR);
regval |= RCC_AHB2RSTR_HASHRST;
stm32crypto_putreg32(regval, STM32_RCC_AHB2RSTR);
regval &= ~RCC_AHB2RSTR_HASHRST;
stm32crypto_putreg32(regval, STM32_RCC_AHB2RSTR);
leave_critical_section(flags);
}
/* Set the algorithm and digest size */
regval = 0;
switch (sw->hw_alg)
{
case CRYPTO_SHA1:
case CRYPTO_SHA1_HMAC:
regval = HASH_CR_ALGO_SHA1;
sw->u.hash.dsize = 20;
break;
case CRYPTO_MD5:
case CRYPTO_MD5_HMAC:
regval = HASH_CR_ALGO_MD5;
sw->u.hash.dsize = 16;
break;
case CRYPTO_SHA2_224:
case CRYPTO_SHA2_224_HMAC:
regval = HASH_CR_ALGO_SHA2_224;
sw->u.hash.dsize = 28;
break;
case CRYPTO_SHA2_256:
case CRYPTO_SHA2_256_HMAC:
regval = HASH_CR_ALGO_SHA2_256;
sw->u.hash.dsize = 32;
break;
default:
return -EINVAL;
}
/* If HMAC set mode, and key is large set HASH_CR_LKEY bit */
if (sw->u.hash.hmac)
{
regval |= HASH_CR_MODE_HMAC;
stm32cryptoinfo("klen %" PRIx32 "", sw->u.hash.klen);
if (sw->u.hash.klen > 64)
{
regval |= HASH_CR_LKEY_GT_64;
}
}
regval |= HASH_CR_INIT; /* set init to configure HASH algorithm */
regval |= HASH_CR_DATATYPE_8; /* 8-bit data... */
stm32crypto_putreg32(regval, STM32_HASH_CR);
sw->u.hash.rlen = 0;
sw->u.hash.rdata = 0;
return 0;
}
static int hash_update(struct stm32_crypto_data *sw,
uint8_t *buf, uint32_t len)
{
const uint8_t *in_byte = buf;
const uint32_t *in_block;
int ret;
stm32cryptoinfo("buf %" PRIxPTR " len %" PRIu32 "",
(uintptr_t)buf, len);
if (len == 0)
{
return 0;
}
/* If any remainder leftover from previous accumulation
* then accumulate them into hash.rdata to
* push into DIN
*/
if (sw->u.hash.rlen)
{
while (sw->u.hash.rlen < sizeof(uint32_t))
{
if (!len)
{
break;
}
sw->u.hash.rdata |= (in_byte[0] << (8 * sw->u.hash.rlen));
in_byte++;
sw->u.hash.rlen++;
len--;
}
/* If hash_rlen still not sizeof(uint32_t) then input buffer
* doesn't hold enough bytes to write into DIN.
*/
if (sw->u.hash.rlen < sizeof(uint32_t))
{
return 0;
}
stm32crypto_putreg32(sw->u.hash.rdata, STM32_HASH_DIN);
sw->u.hash.rlen = 0;
sw->u.hash.rdata = 0x0;
}
in_block = (uint32_t *)in_byte;
/* Loop pushing uint32_t of hash data into HASH_DIN */
while (len >= sizeof(uint32_t))
{
ret = stm32_wait_for_clr(STM32_HASH_SR, HASH_SR_BUSY,
STM32H7_HASH_TIMEOUT);
if (ret < 0)
{
return ret;
}
stm32crypto_putreg32(*in_block, STM32_HASH_DIN);
in_block++;
len -= sizeof(uint32_t);
}
/* Accumulate any remaining bytes into hash.rdata */
if (len)
{
stm32cryptoinfo("len %" PRIu32 " hash.rlen: %" PRIu32 "",
len, sw->u.hash.rlen);
in_byte = (uint8_t *)in_block;
while (len)
{
sw->u.hash.rdata |= (in_byte[0] << (8 * sw->u.hash.rlen));
sw->u.hash.rlen++;
in_byte++;
len--;
}
}
return 0;
}
static int hash_final(struct stm32_crypto_data *sw, caddr_t digest,
uint32_t wait_flag)
{
uint32_t *out = (uint32_t *)digest;
uint32_t regval;
int ret;
stm32cryptoinfo("digest %" PRIxPTR "", (uintptr_t)digest);
/* If any data left in rdata, write it out */
if (sw->u.hash.rlen)
{
stm32crypto_putreg32(sw->u.hash.rdata, STM32_HASH_DIN);
}
/* Start digest calculation. Set NBLW to number of
* bits of valid data in last write to HASH_DIN, and
* set DCAL to start the digest calculation.
*/
regval = HASH_STR_NBLW_BYTES((uint32_t)sw->u.hash.rlen);
stm32crypto_putreg32(regval, STM32_HASH_STR);
/* Set DCAL _after_ setting NBLW; have seen incorrect HMAC hash
* result if both done at same time.
*/
regval |= HASH_STR_DCAL;
stm32crypto_putreg32(regval, STM32_HASH_STR);
sw->u.hash.rlen = 0;
sw->u.hash.rdata = 0x0;
/* Wait for the digest to compute
* (for HMAC wait for data to be ready)
*/
ret = stm32_wait_for_set(STM32_HASH_SR, wait_flag,
STM32H7_HASH_TIMEOUT);
if (ret < 0)
{
return ret;
}
/* Extract the resultant hash (if desired) */
if (digest)
{
regval = stm32crypto_getreg32(STM32_HASH_HRA0);
*out++ = __builtin_bswap32(regval);
regval = stm32crypto_getreg32(STM32_HASH_HRA1);
*out++ = __builtin_bswap32(regval);
regval = stm32crypto_getreg32(STM32_HASH_HRA2);
*out++ = __builtin_bswap32(regval);
regval = stm32crypto_getreg32(STM32_HASH_HRA3);
*out++ = __builtin_bswap32(regval);
if (sw->u.hash.dsize >= 20)
{
regval = stm32crypto_getreg32(STM32_HASH_HRA4);
*out++ = __builtin_bswap32(regval);
}
if (sw->u.hash.dsize >= 28)
{
regval = stm32crypto_getreg32(STM32_HASH_HR5);
*out++ = __builtin_bswap32(regval);
regval = stm32crypto_getreg32(STM32_HASH_HR6);
*out++ = __builtin_bswap32(regval);
}
if (sw->u.hash.dsize == 32)
{
regval = stm32crypto_getreg32(STM32_HASH_HR7);
*out++ = __builtin_bswap32(regval);
}
}
return 0;
}
/****************************************************************************
* Name: stm32_freesession
*
@ -393,8 +758,9 @@ static int crc32_final(struct stm32_crypto_data *sw, caddr_t digest)
static int stm32_freesession(uint64_t tid)
{
FAR struct stm32_crypto_data *swd;
FAR struct stm32_crypto_data *sw;
uint32_t sid = ((uint32_t) tid) & 0xffffffff;
int ret = 0;
if (sid > g_stm32_sesnum || stm32_crypto_sessions == NULL
|| stm32_crypto_sessions[sid] == NULL)
@ -409,25 +775,41 @@ static int stm32_freesession(uint64_t tid)
return 0;
}
while ((swd = stm32_crypto_sessions[sid]) != NULL)
while ((sw = stm32_crypto_sessions[sid]) != NULL)
{
stm32_crypto_sessions[sid] = swd->hw_next;
stm32_crypto_sessions[sid] = sw->hw_next;
switch (swd->hw_alg)
switch (sw->hw_alg)
{
case CRYPTO_SHA1_HMAC:
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA2_224_HMAC:
case CRYPTO_SHA2_256_HMAC:
if (sw->u.hash.key)
{
explicit_bzero(sw->u.hash.key, sw->u.hash.klen);
kmm_free(sw->u.hash.key);
}
break;
case CRYPTO_CRC32:
case CRYPTO_SHA1:
case CRYPTO_MD5:
case CRYPTO_SHA2_224:
case CRYPTO_SHA2_256:
case CRYPTO_AES_CBC:
case CRYPTO_AES_CTR:
break;
default:
return -EINVAL;
ret = -EINVAL;
break;
}
kmm_free(swd);
kmm_free(sw);
}
return 0;
return ret;
}
/****************************************************************************
@ -441,8 +823,10 @@ static int stm32_freesession(uint64_t tid)
static int stm32_newsession(uint32_t *sid, struct cryptoini *cri)
{
FAR struct stm32_crypto_data **swd;
int klen;
FAR struct stm32_crypto_data *sw;
uint32_t i;
int klen;
int ret;
stm32cryptoinfo("");
@ -508,20 +892,75 @@ static int stm32_newsession(uint32_t *sid, struct cryptoini *cri)
while (cri)
{
*swd = kmm_zalloc(sizeof(struct stm32_crypto_data));
if (*swd == NULL)
sw = kmm_zalloc(sizeof(struct stm32_crypto_data));
*swd = sw;
if (sw == NULL)
{
stm32_freesession(i);
return -ENOBUFS;
}
sw->hw_alg = cri->cri_alg;
switch (cri->cri_alg)
{
case CRYPTO_CRC32:
crc32_init(*swd);
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1_HMAC:
case CRYPTO_SHA2_224_HMAC:
case CRYPTO_SHA2_256_HMAC:
sw->u.hash.hmac = true;
sw->u.hash.klen = cri->cri_klen / 8;
sw->u.hash.key = kmm_malloc(sw->u.hash.klen);
if (sw->u.hash.key == NULL)
{
return -ENOBUFS;
}
bcopy(cri->cri_key, sw->u.hash.key, sw->u.hash.klen);
/* Initialize HW, push the key into DIN, wait for DINIS */
ret = hash_init(sw);
if (ret < 0)
{
return ret;
}
stm32cryptoinfo("Push %" PRIu32 " bytes of outer hash into DIN",
sw->u.hash.klen);
ret = hash_update(sw, sw->u.hash.key, sw->u.hash.klen);
if (ret < 0)
{
return ret;
}
stm32cryptoinfo("Wait for DINIS");
ret = hash_final(sw, NULL, HASH_SR_DINIS);
if (ret < 0)
{
return ret;
}
break;
case CRYPTO_MD5:
case CRYPTO_SHA1:
case CRYPTO_SHA2_224:
case CRYPTO_SHA2_256:
sw->u.hash.hmac = false;
ret = hash_init(sw);
if (ret < 0)
{
return ret;
}
break;
case CRYPTO_CRC32:
crc32_init(sw);
break;
case CRYPTO_AES_CBC:
break;
case CRYPTO_AES_CTR:
klen = cri->cri_klen / 8 - 4;
if ((klen != 16) && (klen != 24) && (klen != 32))
@ -538,9 +977,9 @@ static int stm32_newsession(uint32_t *sid, struct cryptoini *cri)
return -EINVAL;
}
(*swd)->hw_alg = cri->cri_alg;
sw->hw_alg = cri->cri_alg;
cri = cri->cri_next;
swd = &((*swd)->hw_next);
swd = &(sw->hw_next);
}
return 0;
@ -560,6 +999,7 @@ static int stm32_process(struct cryptop *crp)
struct cryptodesc *crd;
uint8_t iv[AESCTR_BLOCKSIZE];
uint32_t lid;
int ret;
stm32cryptoinfo("");
@ -567,11 +1007,13 @@ static int stm32_process(struct cryptop *crp)
if (crp == NULL)
{
stm32cryptoinfo("");
return -EINVAL;
}
if (crp->crp_desc == NULL || crp->crp_buf == NULL)
if (crp->crp_desc == NULL)
{
stm32cryptoinfo("");
crp->crp_etype = -EINVAL;
goto done;
}
@ -580,6 +1022,7 @@ static int stm32_process(struct cryptop *crp)
if (lid >= g_stm32_sesnum || lid == 0
|| stm32_crypto_sessions[lid] == NULL)
{
stm32cryptoinfo("");
crp->crp_etype = -ENOENT;
goto done;
}
@ -605,11 +1048,64 @@ static int stm32_process(struct cryptop *crp)
if (sw == NULL)
{
stm32cryptoinfo("");
return -EINVAL;
}
switch (crd->crd_alg)
{
case CRYPTO_MD5:
case CRYPTO_SHA1:
case CRYPTO_SHA2_224:
case CRYPTO_SHA2_256:
if (crd->crd_flags & CRD_F_UPDATE)
{
return hash_update(sw, crp->crp_buf, crd->crd_len);
}
else
{
return hash_final(sw, crp->crp_mac, HASH_SR_DCIS);
}
break;
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1_HMAC:
case CRYPTO_SHA2_224_HMAC:
case CRYPTO_SHA2_256_HMAC:
ret = hash_update(sw, crp->crp_buf, crd->crd_len);
if (ret < 0 || (crd->crd_flags & CRD_F_UPDATE))
{
return ret;
}
/* All HMAC data has been hashed, next step is
* 1) set DCAL and HBLW, wait for DINIS
*/
ret = hash_final(sw, NULL, HASH_SR_DINIS);
if (ret < 0)
{
stm32cryptoinfo("");
return ret;
}
/* 2) Push outer hash (same as inner hash) into DIN */
stm32cryptoinfo("Push %" PRIu32 " bytes of inner hash",
sw->u.hash.klen);
ret = hash_update(sw, sw->u.hash.key, sw->u.hash.klen);
if (ret < 0)
{
stm32cryptoinfo("");
return ret;
}
/* 3) normal finalization */
return hash_final(sw, crp->crp_mac, HASH_SR_DCIS);
break;
case CRYPTO_CRC32:
if (crd->crd_flags & CRD_F_UPDATE)
{
@ -637,6 +1133,7 @@ static int stm32_process(struct cryptop *crp)
crd->crd_klen / 8 - AESCTR_NONCESIZE,
AES_MODE_CTR, crd->crd_flags & CRD_F_ENCRYPT);
default:
stm32cryptoinfo("crc_alg %d", crd->crd_alg);
return -EINVAL;
}
}
@ -664,6 +1161,15 @@ void hwcr_init(void)
memset(algs, 0, sizeof(algs));
algs[CRYPTO_CRC32] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_MD5] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA1] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_224] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_256] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_MD5_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_224_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_AES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_AES_CTR] = CRYPTO_ALG_FLAG_SUPPORTED;

View file

@ -332,6 +332,12 @@ static inline void rcc_enableahb2(void)
regval |= RCC_AHB2ENR_CRYPTEN;
#endif
#ifdef CONFIG_STM32_HASH
/* Hash clock enable */
regval |= RCC_AHB2ENR_HASHEN;
#endif
putreg32(regval, STM32_RCC_AHB2ENR); /* Enable peripherals */
}

View file

@ -10,7 +10,6 @@
# 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"
@ -50,10 +49,13 @@ CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_STM32_CRC=y
CONFIG_STM32_CRYP=y
CONFIG_STM32_HASH=y
CONFIG_STM32_USART3=y
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=0
CONFIG_TESTING_CRYPTO=y
CONFIG_TESTING_CRYPTO_CRC32=y
CONFIG_TESTING_CRYPTO_STACKSIZE=4096
CONFIG_TESTING_CRYPTO_HASH=y
CONFIG_TESTING_CRYPTO_HASH_DISABLE_SHA512=y
CONFIG_TESTING_CRYPTO_STACKSIZE=8192
CONFIG_USART3_SERIAL_CONSOLE=y