Fixes for PUF ROT

pull/568/head
David Garske 2025-02-03 11:28:15 -08:00 committed by Daniele Lacamera
parent 851130293c
commit 79437e5865
3 changed files with 192 additions and 26 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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)