mirror of https://github.com/wolfSSL/wolfBoot.git
Fixes for PUF ROT
parent
851130293c
commit
79437e5865
|
|
@ -233,15 +233,147 @@ Note: To generate a report of a boot.bin use the `bootgen_utility` or after 2022
|
|||
`bootgen -arch zynqmp -read BOOT.BIN`
|
||||
|
||||
|
||||
# CSU Support
|
||||
## CSU Support
|
||||
|
||||
The Configuration Security Unit (CSU) is a dedicate core that contains security functions like PUF, SHA3, RSA, Tamper Protection. These registers can only be accessed through the PMU, which is a separate dedicated core. If operating from LE2 or lower the calls must be done through the BL31 (TF-A) SIP service to elevate privledges.
|
||||
|
||||
Access to most CSU registers can be done by setting the `-DSECURE_ACCESS_VAL=1` build option.
|
||||
|
||||
Enabling PMU firmware support for access to the CSU.
|
||||
In PetaLinux menuconfig under PMU Configuration add compiler flag `-DSECURE_ACCESS_VAL=1`.
|
||||
|
||||
```sh
|
||||
petalinux-build -c pmufw
|
||||
petalinux-build
|
||||
```
|
||||
|
||||
### CSU PUF
|
||||
|
||||
The PUF (Physically Unclonable Function) provides a way to generate a unique key for encryption specific to the device. It is useful for wrapping other keys to pair/bind them and allows external storage of the encrypted key.
|
||||
|
||||
This feature is enabled with `CFLAGS_EXTRA+=-DCSU_PUF_ROT`.
|
||||
|
||||
For PUF functionality a patch must be applied to the PMUFW to enable access to the PUF registers. See `pm_mmio_access.c` patch below:
|
||||
|
||||
```
|
||||
+ /* CSU PUF Registers */
|
||||
+ {
|
||||
+ .startAddr = ( ( CSU_BASEADDR ) + 0X00004000 ),
|
||||
+ .endAddr = ( ( CSU_BASEADDR ) + 0X00004018 ),
|
||||
+ .access = MMIO_ACCESS_RW(IPI_PMU_0_IER_APU_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_0_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_1_MASK),
|
||||
+ },
|
||||
```
|
||||
|
||||
Example PUF Generation Output:
|
||||
|
||||
```
|
||||
wolfBoot Secure Boot
|
||||
Current EL: 2
|
||||
QSPI Init: Ref=300MHz, Div=8, Bus=37500000, IO=DMA
|
||||
Read FlashID Lower: Ret 0, 20 BB 22
|
||||
Read FlashID Upper: Ret 0, 20 BB 22
|
||||
PMUFW Ver: 1.1
|
||||
CSU ID 0x24738093, Ver 0x00000003
|
||||
Enabling JTAG
|
||||
JTAG Attached: status 0x3
|
||||
CSU Puf Register
|
||||
Ret 0, SyndromeSz 560, CHASH 0xA014DD88, AUX 0x00408A64
|
||||
462273FBECB98600E3D099415B30F1AF3DD6B29369102847EC61B708AB37AF2A6999596BC9071F84773142631BA2C1109C14FACC156B7343FB8436CE06292DB95B4C1941E6DC8F982404462DEFB91792076EC428D1C0C8A10F271E3B67F652F562885384B97717B0AA3B8B24CC0AD54D1641860355C343D0FE38E1F6D6F4289C38AEC5EFD1046C736423EF881DE0A04F64165B9D275E5050D91F3EBD9241FE67D55BEA336E46B174112F86361FB2AA78197C6BF5812533E4EC1E88BC7125366C5E8BE8B70483FE5FC144B9F608D72964690D6DE0E8E8B65C23D2B9ED8262DF77AC4E2EE67ABF18DC2EC452B0731B0E229CAD555BC61CF0FE26066F1E54C33C7DC7C86DC56BFFF391689F937CD3C565D4B28D68C74793562B4938D6FE5667644F247CEFCCC926A57B54048A4986E8AC9F1B7D673CC14C2CC5DDD4A548986BF925B938FF92D6F7D3A2CD1ACD3943C6A35CF9CFFD8A786682032D3826CFDBAD38FDCBFD2B3480A933CAAEB391685E58A0BBDECDF9B69A5D685AE0D93BAC6B55E9D447565FBFF68E35F12B779EBC5918E0A5CD3CE00C7B5AF833A33CACD0F871A2FB89218BC2F1F02F0B68CB65F9B122D5B5D72116F1F6ED111B87DEB7E1BC4873E5889C2C6915CD362B75DA211264CF66F093C368F37EC54721AAFA6313C5892514011CE9BFDD72C51FDEA7320377692A1AF8FD0D563A66E465AA9AD51BF91B2A5CE6178E517032D3786B1F714681339C2286BBE5E71B7334F923FABBFBEC382E2EF6880471BB13956
|
||||
```
|
||||
|
||||
### CSU JTAG Enable
|
||||
|
||||
When RSA authentication is enabled the JTAG feature is disabled in the PMU. To re-enable it (assuming eFuse allows it) build with `CFLAGS_EXTRA+=-DDEBUG_CSU=2` and apply the PMUFW patches below.
|
||||
|
||||
To patch the PMUFW from PetaLinux use the following steps (for 2022.1 or later):
|
||||
|
||||
Based on instructions from: https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/2587197506/Zynq+UltraScale+MPSoC+JTAG+Enable+in+U-Boot
|
||||
|
||||
`pim/project-spec/meta-user/recipes-bsp/embeddedsw/pmu-firmware_%.bbappend`:
|
||||
|
||||
```
|
||||
# Patch for PMUFW
|
||||
|
||||
SRC_URI_append = " file://0001-csu-regs.patch"
|
||||
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
|
||||
```
|
||||
|
||||
`pim/project-spec/meta-user/recipes-bsp/embeddedsw/files/0001-csu-regs.patch`:
|
||||
```
|
||||
diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_mmio_access.c b/lib/sw_apps/zynqmp_pmufw/src/pm_mmio_access.c
|
||||
index 73066576a5..ce9490916d 100644
|
||||
--- a/lib/sw_apps/zynqmp_pmufw/src/pm_mmio_access.c
|
||||
+++ b/lib/sw_apps/zynqmp_pmufw/src/pm_mmio_access.c
|
||||
@@ -99,6 +99,22 @@ static const PmAccessRegion pmAccessTable[] = {
|
||||
IPI_PMU_0_IER_RPU_1_MASK),
|
||||
},
|
||||
|
||||
+ /* WOLF: Adding DBG_LPD_CTRL and RST_LPD_DBG to support JTAG Enable in u-boot */
|
||||
+ {
|
||||
+ .startAddr = CRL_APB_DBG_LPD_CTRL,
|
||||
+ .endAddr = CRL_APB_DBG_LPD_CTRL,
|
||||
+ .access = MMIO_ACCESS_RW(IPI_PMU_0_IER_APU_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_0_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_1_MASK),
|
||||
+ },
|
||||
+ {
|
||||
+ .startAddr = CRL_APB_RST_LPD_DBG,
|
||||
+ .endAddr = CRL_APB_RST_LPD_DBG,
|
||||
+ .access = MMIO_ACCESS_RW(IPI_PMU_0_IER_APU_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_0_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_1_MASK),
|
||||
+ },
|
||||
+
|
||||
/* PMU's global Power Status register*/
|
||||
{
|
||||
.startAddr = PMU_GLOBAL_PWR_STATE,
|
||||
@@ -415,15 +431,24 @@ static const PmAccessRegion pmAccessTable[] = {
|
||||
IPI_PMU_0_IER_RPU_1_MASK),
|
||||
},
|
||||
|
||||
+ /* WOLF: separate CSU_JTAG_CHAIN_CFG so it can be made RW */
|
||||
/* CSU ier register*/
|
||||
{
|
||||
.startAddr = CSU_IER,
|
||||
- .endAddr = CSU_JTAG_CHAIN_CFG,
|
||||
+ .endAddr = CSU_IDR,
|
||||
.access = MMIO_ACCESS_WO(IPI_PMU_0_IER_APU_MASK |
|
||||
IPI_PMU_0_IER_RPU_0_MASK |
|
||||
IPI_PMU_0_IER_RPU_1_MASK),
|
||||
},
|
||||
|
||||
+ {
|
||||
+ .startAddr = CSU_JTAG_CHAIN_CFG,
|
||||
+ .endAddr = CSU_JTAG_CHAIN_CFG,
|
||||
+ .access = MMIO_ACCESS_RW(IPI_PMU_0_IER_APU_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_0_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_1_MASK),
|
||||
+ },
|
||||
+
|
||||
/* CSU idr register*/
|
||||
{
|
||||
.startAddr = CSU_IDR,
|
||||
@@ -504,6 +529,15 @@ static const PmAccessRegion pmAccessTable[] = {
|
||||
IPI_PMU_0_IER_RPU_1_MASK),
|
||||
},
|
||||
|
||||
+ /* CSU PUF Registers */
|
||||
+ {
|
||||
+ .startAddr = ( ( CSU_BASEADDR ) + 0X00004000 ),
|
||||
+ .endAddr = ( ( CSU_BASEADDR ) + 0X00004018 ),
|
||||
+ .access = MMIO_ACCESS_RW(IPI_PMU_0_IER_APU_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_0_MASK |
|
||||
+ IPI_PMU_0_IER_RPU_1_MASK),
|
||||
+ },
|
||||
+
|
||||
/*CSU tamper-status register */
|
||||
{
|
||||
.startAddr = CSU_TAMPER_STATUS,
|
||||
```
|
||||
|
||||
Then rebuild PMUFW: `petalinux-build -c pmufw`
|
||||
|
||||
|
||||
## Post Quantum
|
||||
|
||||
### PQ XMSS
|
||||
|
|
|
|||
65
hal/zynq.c
65
hal/zynq.c
|
|
@ -288,30 +288,59 @@ void wc_Sha3_384_Free(wc_Sha3* sha)
|
|||
#endif
|
||||
|
||||
/* CSU PUF */
|
||||
#define PUF_REG_TIMEOUT 500000
|
||||
#ifdef CSU_PUF_ROT
|
||||
#define CSU_PUF_SYNDROME_WORDS 386
|
||||
#ifndef CSU_PUF_REG_TIMEOUT
|
||||
#define CSU_PUF_REG_TIMEOUT 500000
|
||||
#endif
|
||||
|
||||
static int csu_puf_wait_word(uint32_t* puf_status)
|
||||
{
|
||||
int ret = -1; /* timeout */
|
||||
uint32_t timeout = 0;
|
||||
|
||||
while (++timeout < CSU_PUF_REG_TIMEOUT) {
|
||||
*puf_status = pmu_mmio_read(CSU_PUF_STATUS);
|
||||
if ((*puf_status & CSU_PUF_STATUS_SYN_WRD_RDY_MASK) != 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int csu_puf_register(uint32_t* syndrome, uint32_t* syndromeSz, uint32_t* chash,
|
||||
uint32_t* aux)
|
||||
{
|
||||
int ret;
|
||||
uint32_t puf_status, timeout = 0, idx = 0;
|
||||
uint32_t reg32, puf_status = 0, idx = 0;
|
||||
|
||||
#if defined(DEBUG_CSU) && DEBUG_CSU >= 1
|
||||
wolfBoot_printf("CSU Puf Register\n");
|
||||
#endif
|
||||
|
||||
pmu_mmio_write(CSU_PUF_CFG0, CSU_PUF_CFG0_INIT);
|
||||
pmu_mmio_write(CSU_PUF_CFG1, CSU_PUF_CFG1_INIT);
|
||||
pmu_mmio_write(CSU_PUF_SHUTTER, CSU_PUF_SHUTTER_INIT);
|
||||
pmu_mmio_write(CSU_PUF_CMD, CSU_PUF_CMD_REGISTRATION);
|
||||
while (1) {
|
||||
/* Wait for PUF status done */
|
||||
while (((puf_status = pmu_mmio_read(CSU_PUF_STATUS))
|
||||
& CSU_PUF_STATUS_SYN_WRD_RDY_MASK) == 0
|
||||
&& ++timeout < PUF_REG_TIMEOUT);
|
||||
if (timeout == PUF_REG_TIMEOUT) {
|
||||
ret = -1; /* timeout */
|
||||
/* try a read from register to make sure PMU has permission */
|
||||
reg32 = pmu_mmio_read(CSU_PUF_SHUTTER);
|
||||
if (reg32 == 0) {
|
||||
wolfBoot_printf("PMUFW PUF Register access not enabled in "
|
||||
"pm_mmio_access pmAccessTable!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = pmu_mmio_write(CSU_PUF_CFG0, CSU_PUF_CFG0_INIT);
|
||||
if (ret == 0)
|
||||
ret = pmu_mmio_write(CSU_PUF_CFG1, CSU_PUF_CFG1_INIT);
|
||||
if (ret == 0)
|
||||
ret = pmu_mmio_write(CSU_PUF_SHUTTER, CSU_PUF_SHUTTER_INIT);
|
||||
if (ret == 0)
|
||||
ret = pmu_mmio_write(CSU_PUF_CMD, CSU_PUF_CMD_REGISTRATION);
|
||||
while (ret == 0) {
|
||||
/* wait for PUF word ready */
|
||||
puf_status = 0;
|
||||
ret = csu_puf_wait_word(&puf_status);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((idx * 4) > *syndromeSz) {
|
||||
ret = -2; /* overrun */
|
||||
break;
|
||||
|
|
@ -341,14 +370,16 @@ int csu_puf_register(uint32_t* syndrome, uint32_t* syndromeSz, uint32_t* chash,
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CSU_PUF_ROT */
|
||||
|
||||
#define CSU_PUF_SYNDROME_WORDS 386
|
||||
int csu_init(void)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
#ifdef CSU_PUF_ROT
|
||||
uint32_t syndrome[CSU_PUF_SYNDROME_WORDS];
|
||||
uint32_t syndromeSz = (uint32_t)sizeof(syndrome);
|
||||
uint32_t chash=0, aux=0;
|
||||
#endif
|
||||
uint32_t reg1 = pmu_mmio_read(CSU_IDCODE);
|
||||
uint32_t reg2 = pmu_mmio_read(CSU_VERSION);
|
||||
|
||||
|
|
@ -371,7 +402,9 @@ int csu_init(void)
|
|||
hal_delay_ms(500); /* give time for debugger to break */
|
||||
#endif
|
||||
|
||||
#ifdef CSU_PUF_ROT
|
||||
ret = csu_puf_register(syndrome, &syndromeSz, &chash, &aux);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
15
hal/zynq.h
15
hal/zynq.h
|
|
@ -477,6 +477,7 @@
|
|||
#define CSU_PUF_CFG1 (CSU_BASE + 0x4008U)
|
||||
#define CSU_PUF_SHUTTER (CSU_BASE + 0x400CU)
|
||||
#define CSU_PUF_STATUS (CSU_BASE + 0x4010U)
|
||||
#define CSU_PUF_DBG (CSU_BASE + 0x4014U)
|
||||
#define CSU_PUF_WORD (CSU_BASE + 0x4018U)
|
||||
|
||||
#define CSU_PUF_CMD_CLEAR 0x6 /* Clear PUF status */
|
||||
|
|
@ -485,14 +486,14 @@
|
|||
#define CSU_PUF_CMD_REGISTRATION 0x1 /* Key registration */
|
||||
|
||||
#define CSU_PUF_CFG0_INIT 0x2
|
||||
#define CSU_PUF_CFG1_INIT 0x0C230090 /* 0x00080080 */
|
||||
#define CSU_PUF_SHUTTER_INIT 0x0100005E /* 0x01000100 */
|
||||
#define CSU_PUF_CFG1_INIT 0x0C230090U /* 4K */
|
||||
#define CSU_PUF_SHUTTER_INIT 0x00100005E
|
||||
|
||||
#define CSU_PUF_STATUS_OVERFLOW_MASK 0x30000000 /* Overflow, if bits are not 0. Reduce SHUT[SOPEN] value. */
|
||||
#define CSU_PUF_STATUS_AUX_MASK 0x0FFFFFF0 /* During provisioning, auxiliary sundrome bits are stored here and must be written to the eFuse or boot image. */
|
||||
#define CSU_PUF_STATUS_KEY_RDY_MASK 0x00000008
|
||||
#define CSU_PUF_STATUS_KEY_ZERO_MASK 0x00000002 /* Indicates that the PUF key has been zeroized */
|
||||
#define CSU_PUF_STATUS_SYN_WRD_RDY_MASK 0x00000001 /* Indicates a syndrome word is ready in the PUF_WORD register. */
|
||||
#define CSU_PUF_STATUS_OVERFLOW_MASK (0x3U << 28) /* Overflow, if bits are not 0. Reduce SHUT[SOPEN] value. */
|
||||
#define CSU_PUF_STATUS_AUX_MASK (0xFFFFFFU << 4) /* During provisioning, auxiliary sundrome bits are stored here and must be written to the eFuse or boot image. */
|
||||
#define CSU_PUF_STATUS_KEY_RDY_MASK (0x1U << 3) /* Indicates that the key is ready */
|
||||
#define CSU_PUF_STATUS_KEY_ZERO_MASK (0x1U << 1) /* Indicates that the PUF key has been zeroized */
|
||||
#define CSU_PUF_STATUS_SYN_WRD_RDY_MASK (0x1U << 0) /* Indicates a syndrome word is ready in the PUF_WORD register */
|
||||
|
||||
/* SHA3 */
|
||||
#define CSU_SHA_START (CSU_BASE + 0x2000U)
|
||||
|
|
|
|||
Loading…
Reference in New Issue