Progress on RoT. Creation of PUF, Regeneration and use of it for AES Key wrapping.

pull/568/head
David Garske 2025-02-07 17:51:25 -08:00 committed by Daniele Lacamera
parent 79437e5865
commit 64c74b8233
3 changed files with 386 additions and 71 deletions

View File

@ -274,11 +274,50 @@ Read FlashID Lower: Ret 0, 20 BB 22
Read FlashID Upper: Ret 0, 20 BB 22 Read FlashID Upper: Ret 0, 20 BB 22
PMUFW Ver: 1.1 PMUFW Ver: 1.1
CSU ID 0x24738093, Ver 0x00000003 CSU ID 0x24738093, Ver 0x00000003
Enabling JTAG PUF Status 0x00000002
JTAG Attached: status 0x3 eFuse SEC_CTRL 0x00000000
eFuse PUF CHASH 0x00000000, AUX 0x00000000
CSU Puf Register CSU Puf Register
Ret 0, SyndromeSz 560, CHASH 0xA014DD88, AUX 0x00408A64 Ret 0, Syndrome 1544, CHASH 0x9B7A8C30, AUX 0x005AE021
462273FBECB98600E3D099415B30F1AF3DD6B29369102847EC61B708AB37AF2A6999596BC9071F84773142631BA2C1109C14FACC156B7343FB8436CE06292DB95B4C1941E6DC8F982404462DEFB91792076EC428D1C0C8A10F271E3B67F652F562885384B97717B0AA3B8B24CC0AD54D1641860355C343D0FE38E1F6D6F4289C38AEC5EFD1046C736423EF881DE0A04F64165B9D275E5050D91F3EBD9241FE67D55BEA336E46B174112F86361FB2AA78197C6BF5812533E4EC1E88BC7125366C5E8BE8B70483FE5FC144B9F608D72964690D6DE0E8E8B65C23D2B9ED8262DF77AC4E2EE67ABF18DC2EC452B0731B0E229CAD555BC61CF0FE26066F1E54C33C7DC7C86DC56BFFF391689F937CD3C565D4B28D68C74793562B4938D6FE5667644F247CEFCCC926A57B54048A4986E8AC9F1B7D673CC14C2CC5DDD4A548986BF925B938FF92D6F7D3A2CD1ACD3943C6A35CF9CFFD8A786682032D3826CFDBAD38FDCBFD2B3480A933CAAEB391685E58A0BBDECDF9B69A5D685AE0D93BAC6B55E9D447565FBFF68E35F12B779EBC5918E0A5CD3CE00C7B5AF833A33CACD0F871A2FB89218BC2F1F02F0B68CB65F9B122D5B5D72116F1F6ED111B87DEB7E1BC4873E5889C2C6915CD362B75DA211264CF66F093C368F37EC54721AAFA6313C5892514011CE9BFDD72C51FDEA7320377692A1AF8FD0D563A66E465AA9AD51BF91B2A5CE6178E517032D3786B1F714681339C2286BBE5E71B7334F923FABBFBEC382E2EF6880471BB13956 4662F39BEC998700E2D299E15B30F1AF563FC596A3854ACE05FDA4FBC2AD32DF9B66E2081A55D8CA0CB84B88735B005548C0671BD561AE7A9FBB266E228368F6D1FD916C8D172572094E210826106B8C80AB1E8910647283DB22076560FC5E10C02C614F4EF80001B218501AD9D07580C2DB47E487940DB24615509EBE85B037AB2FCDE820661EAB45C345863735F64689AECCEAE783DC413052E615B231931E265EC00C15D8FCD2D83E9F8FC836178C0415587E683D48A7ADADC1B53E17743859CA5984A314D1CC85AF58226376E705AC6C2973ACCE05FF2263DBE951A2D0FFD9D218C57F1D1398640E5A3D03BB9478530035952642C40258AFEB196F0A6D130BC8C2E064C622AC9FA0827BBFCF35FCBAFC9593085D1D296F8446C3550784DECF964B4A65249E9A002A7CEE9886DBB7F33DC3A7404C66497218FF7762E4C81B048986BF9257968FF92D6F7D1AACB1A8CDE48E8ECDD8B7A74C3C16FF10FD00D119E3B5F4DB19854AF60C2B063CB26A3740FC8658425EB44F27B52CDD6C1A16E3C45394BA9629B0A8A0410979CA0ED488E787F36B4BC05E1CEBD8F5CFF6DAF3D3F8B885E6F0A616675DA0B748F3C4E334545920C3062113230741795AA97D4A32B7E1BC4953E588902C7915CD362B75DA33BB941B523932B172589E27759A924A857CD66EE0E02BE697188776E4A646F7A73203E769285BF9FD09562A67CC67E2EB6CC7D8F15C138991AC177030D9057750A70E0C4F6144A8412F436A8B952597D664BADF3997DC0249DB4ABF6355DEB09B7A8C300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009B7A8C30005AE021
CSU Register PUF 0: 281ms
Regen: PUF Status 0x05AE0218
CSU Regen PUF 0: 8ms
Red Key 32
64F03AFD7D0C70D2591CDF34305F7B8A5BA4593C0A0E1B8C5ECDFF9F5900192C
Black IV 16
D142AC7C560F158BA95A213100000000
Black Key 32
2599B8619240E98E264A0CE3CD42C58A9E3457F1982D1DEEE1FC75A1A1284C72
```
Example .bif that includes the PUF helper data and black key/iv. This enables the CSU boot ROM to load up the black AES key for use with the CSU AES engine.
```
the_ROM_image:
{
// Boot Header Authentication Enable
[fsbl_config] a53_x64, bh_auth_enable, puf4kmode, shutter=0x0100005E, pufhd_bh, auth_only
[keysrc_encryption] bh_blk_key
[puf_file] helperdata.txt
[bh_key_iv] black_iv.txt
[bh_keyfile] black_key.txt
// Use the primary public key 0 and secondary public key id 0
[auth_params] ppk_select=0; spk_id=0x00000000
// primary and secondary secret (private) keys
[pskfile] pskf.pem
[sskfile] sskf.pem
[bootloader, authentication=rsa, destination_cpu=a53-0] zynqmp_fsbl.elf
[destination_cpu=pmu, authentication=rsa] pmufw.elf
[destination_device=pl, authentication=rsa] system.bit
[destination_cpu=a53-0, authentication=rsa, exception_level=el-3, trustzone] bl31.elf
[destination_cpu=a53-0, authentication=rsa, load=0x00100000] system.dtb
[destination_cpu=a53-0, authentication=rsa, exception_level=el-2] wolfboot.elf
[destination_cpu=a53-0, partition_owner=uboot, offset=0x800000] hello_world_v1_signed.bin
}
``` ```
### CSU JTAG Enable ### CSU JTAG Enable

View File

@ -183,6 +183,30 @@ static void smc_call(struct pt_regs *args)
#define PM_MMIO_WRITE 0x13 #define PM_MMIO_WRITE 0x13
#define PM_MMIO_READ 0x14 #define PM_MMIO_READ 0x14
/* AES */
/* requires PMU built with -DENABLE_SECURE_VAL=1 */
#define PM_SECURE_AES 0x2F
typedef struct pmu_aes {
uint64_t src; /* source address */
uint64_t iv; /* initialization vector address */
uint64_t key; /* key address */
uint64_t dst; /* destination address */
uint64_t size; /* size */
uint64_t op; /* operation: 0=Decrypt, 1=Encrypt */
uint64_t keySrc; /* key source 0=KUP, 1=Device Key, 2=Use PUF (do regen) */
} pmu_aes;
/* EFUSE */
/* requires PMU built with -DENABLE_EFUSE_ACCESS=1 */
#define PM_EFUSE_ACCESS 0x35
typedef struct pmu_efuse {
uint64_t src; /* adress of data buffer */
uint32_t size; /* size in words */
uint32_t offset; /* offset */
uint32_t flag; /* 0: to read efuse, 1: to write efuse */
uint32_t pufUserFuse;/* 0: PUF HD, 1: eFuses for User Data */
} pmu_efuse;
/* Secure Monitor Call (SMC) to BL31 Silicon Provider (SIP) service, /* Secure Monitor Call (SMC) to BL31 Silicon Provider (SIP) service,
* which is the PMU Firmware */ * which is the PMU Firmware */
static int pmu_request(uint32_t api_id, static int pmu_request(uint32_t api_id,
@ -219,6 +243,27 @@ uint32_t pmu_get_version(void)
return ret_payload[1]; return ret_payload[1];
} }
/* Aligned data buffer for DMA */
#define EFUSE_MAX_BUFSZ (sizeof(pmu_efuse) + 48 /* SHA3-384 Digest */)
static uint8_t XALIGNED(32) efuseBuf[EFUSE_MAX_BUFSZ];
uint32_t pmu_efuse_read(uint32_t offset, uint32_t* data, uint32_t size)
{
pmu_efuse* efuseCmd = (pmu_efuse*)efuseBuf;
uint8_t* efuseData = (efuseBuf + sizeof(pmu_efuse));
uint64_t efuseCmdPtr = (uint64_t)efuseCmd;
uint32_t ret_payload[PM_ARGS_CNT];
memset(ret_payload, 0, sizeof(ret_payload));
memset(efuseBuf, 0, sizeof(efuseBuf));
efuseCmd->src = (uint64_t)efuseData;
efuseCmd->offset = (offset & 0xFF); /* offset is only the last 0xFF bits */
efuseCmd->size = (size/sizeof(uint32_t)); /* number of 32-bit words */
pmu_request(PM_EFUSE_ACCESS, (efuseCmdPtr >> 32), (efuseCmdPtr & 0xFFFFFFFF),
0, 0, ret_payload);
memcpy(data, efuseData, size);
return ret_payload[0]; /* 0=Success, 30=No Access */
}
uint32_t pmu_mmio_read(uint32_t addr) uint32_t pmu_mmio_read(uint32_t addr)
{ {
uint32_t ret_payload[PM_ARGS_CNT]; uint32_t ret_payload[PM_ARGS_CNT];
@ -240,6 +285,15 @@ uint32_t pmu_mmio_write(uint32_t addr, uint32_t val)
return pmu_mmio_writemask(addr, 0xFFFFFFFF, val); return pmu_mmio_writemask(addr, 0xFFFFFFFF, val);
} }
int pmu_mmio_wait(uint32_t addr, uint32_t wait_mask, uint32_t wait_val,
uint32_t tries)
{
uint32_t regval, timeout = 0;
while ((((regval = pmu_mmio_read(addr)) & wait_mask) != wait_val)
&& ++timeout < tries);
return (timeout < tries) ? 0 : -1;
}
#ifdef WOLFBOOT_ZYNQMP_CSU #ifdef WOLFBOOT_ZYNQMP_CSU
#ifdef WOLFBOOT_HASH_SHA3_384 #ifdef WOLFBOOT_HASH_SHA3_384
@ -247,7 +301,7 @@ uint32_t pmu_mmio_write(uint32_t addr, uint32_t val)
#define XSECURE_SHA3_INIT 1U #define XSECURE_SHA3_INIT 1U
#define XSECURE_SHA3_UPDATE 2U #define XSECURE_SHA3_UPDATE 2U
#define XSECURE_SHA3_FINAL 4U #define XSECURE_SHA3_FINAL 4U
static uint32_t secure_sha3(uint64_t addr, uint32_t sz, uint32_t flags) static uint32_t csu_sha3(uint64_t addr, uint32_t sz, uint32_t flags)
{ {
uint32_t ret_payload[PM_ARGS_CNT]; uint32_t ret_payload[PM_ARGS_CNT];
memset(ret_payload, 0, sizeof(ret_payload)); memset(ret_payload, 0, sizeof(ret_payload));
@ -261,7 +315,7 @@ int wc_InitSha3_384(wc_Sha3* sha, void* heap, int devId)
(void)sha; (void)sha;
(void)heap; (void)heap;
(void)devId; (void)devId;
return secure_sha3(0, 0, XSECURE_SHA3_INIT); return csu_sha3(0, 0, XSECURE_SHA3_INIT);
} }
int wc_Sha3_384_Update(wc_Sha3* sha, const byte* data, word32 len) int wc_Sha3_384_Update(wc_Sha3* sha, const byte* data, word32 len)
{ {
@ -269,7 +323,7 @@ int wc_Sha3_384_Update(wc_Sha3* sha, const byte* data, word32 len)
flush_dcache_range( flush_dcache_range(
(unsigned long)data, (unsigned long)data,
(unsigned long)data + len); (unsigned long)data + len);
return secure_sha3((uint64_t)data, len, XSECURE_SHA3_UPDATE); return csu_sha3((uint64_t)data, len, XSECURE_SHA3_UPDATE);
} }
int wc_Sha3_384_Final(wc_Sha3* sha, byte* out) int wc_Sha3_384_Final(wc_Sha3* sha, byte* out)
{ {
@ -277,7 +331,7 @@ int wc_Sha3_384_Final(wc_Sha3* sha, byte* out)
flush_dcache_range( flush_dcache_range(
(unsigned long)out, (unsigned long)out,
(unsigned long)out + WC_SHA3_384_DIGEST_SIZE); (unsigned long)out + WC_SHA3_384_DIGEST_SIZE);
return secure_sha3((uint64_t)out, 0, XSECURE_SHA3_FINAL); return csu_sha3((uint64_t)out, 0, XSECURE_SHA3_FINAL);
} }
void wc_Sha3_384_Free(wc_Sha3* sha) void wc_Sha3_384_Free(wc_Sha3* sha)
{ {
@ -289,28 +343,13 @@ void wc_Sha3_384_Free(wc_Sha3* sha)
/* CSU PUF */ /* CSU PUF */
#ifdef CSU_PUF_ROT #ifdef CSU_PUF_ROT
/* 1544 bytes is fixed size for boot header used by CSU ROM */
#define CSU_PUF_SYNDROME_WORDS 386 #define CSU_PUF_SYNDROME_WORDS 386
#ifndef CSU_PUF_REG_TIMEOUT #ifndef CSU_PUF_REG_TRIES
#define CSU_PUF_REG_TIMEOUT 500000 #define CSU_PUF_REG_TRIES 500000
#endif #endif
static int csu_puf_wait_word(uint32_t* puf_status) int csu_puf_register(uint32_t* syndrome, uint32_t* chash, uint32_t* aux)
{
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; int ret;
uint32_t reg32, puf_status = 0, idx = 0; uint32_t reg32, puf_status = 0, idx = 0;
@ -336,52 +375,235 @@ int csu_puf_register(uint32_t* syndrome, uint32_t* syndromeSz, uint32_t* chash,
ret = pmu_mmio_write(CSU_PUF_CMD, CSU_PUF_CMD_REGISTRATION); ret = pmu_mmio_write(CSU_PUF_CMD, CSU_PUF_CMD_REGISTRATION);
while (ret == 0) { while (ret == 0) {
/* wait for PUF word ready */ /* wait for PUF word ready */
puf_status = 0; ret = pmu_mmio_wait(CSU_PUF_STATUS,
ret = csu_puf_wait_word(&puf_status); CSU_PUF_STATUS_SYN_WRD_RDY_MASK,
CSU_PUF_STATUS_SYN_WRD_RDY_MASK,
CSU_PUF_REG_TRIES);
if (ret != 0) if (ret != 0)
break; break;
if ((idx * 4) > *syndromeSz) { if ((idx > CSU_PUF_SYNDROME_WORDS-2) /* room for chash and aux */) {
ret = -2; /* overrun */ ret = -2; /* overrun */
break; break;
} }
puf_status = pmu_mmio_read(CSU_PUF_STATUS);
/* Read in the syndrome */
syndrome[idx++] = pmu_mmio_read(CSU_PUF_WORD);
if (puf_status & CSU_PUF_STATUS_KEY_RDY_MASK) { if (puf_status & CSU_PUF_STATUS_KEY_RDY_MASK) {
*chash = pmu_mmio_read(CSU_PUF_WORD); *chash = pmu_mmio_read(CSU_PUF_WORD);
syndrome[CSU_PUF_SYNDROME_WORDS-2] = *chash;
*aux = (puf_status & CSU_PUF_STATUS_AUX_MASK) >> 4; *aux = (puf_status & CSU_PUF_STATUS_AUX_MASK) >> 4;
syndrome[CSU_PUF_SYNDROME_WORDS-1] = *aux;
ret = 0; ret = 0;
break; break;
} }
else {
/* Read in the syndrome */
syndrome[idx++] = pmu_mmio_read(CSU_PUF_WORD);
}
} }
*syndromeSz = idx * 4;
#if defined(DEBUG_CSU) && DEBUG_CSU >= 1 #if defined(DEBUG_CSU) && DEBUG_CSU >= 1
wolfBoot_printf("Ret %d, SyndromeSz %d, CHASH 0x%08x, AUX 0x%08x\n", wolfBoot_printf("Ret %d, Syndrome %d, CHASH 0x%08x, AUX 0x%08x\n",
ret, *syndromeSz, *chash, *aux); ret, (CSU_PUF_SYNDROME_WORDS*4), *chash, *aux);
#if DEBUG_CSU >= 2 for (idx=0; idx<CSU_PUF_SYNDROME_WORDS; idx++) {
for (idx=0; idx<*syndromeSz/4; idx++) { wolfBoot_printf("%08x", syndrome[idx]);
wolfBoot_printf("%02x", syndrome[idx]);
} }
#endif wolfBoot_printf("\n");
#endif #endif
return ret; return ret;
} }
int csu_puf_regeneration(uint32_t* syndrome, uint32_t chash, uint32_t aux)
{
int ret;
uint32_t puf_status = 0;
(void)syndrome;
(void)chash;
(void)aux;
ret = pmu_mmio_write(CSU_PUF_CFG0, CSU_PUF_CFG0_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_REGENERATION);
/* wait 6ms */
hal_delay_ms(6);
/* read the puf_status */
puf_status = pmu_mmio_read(CSU_PUF_STATUS);
wolfBoot_printf("Regen: PUF Status 0x%08x\n", puf_status);
return ret;
}
#endif /* CSU_PUF_ROT */ #endif /* CSU_PUF_ROT */
#define CSU_AES_TIMEOUT 150000
#define CSU_DMA_TIMEOUT 300000000U
static int csu_dma_wait_done(int ch)
{
/* wait for DMA channel done */
int ret = pmu_mmio_wait(CSUDMA_ISTS(ch), CSUDMA_ISR_DONE, CSUDMA_ISR_DONE,
CSU_DMA_TIMEOUT);
/* clear status interrupt */
if (ret == 0)
ret = pmu_mmio_write(CSUDMA_ISTS(ch), pmu_mmio_read(CSUDMA_ISTS(ch)));
return ret;
}
static int csu_dma_transfer(int ch, uintptr_t addr, uint32_t sz, uint32_t flags)
{
int ret = pmu_mmio_write(CSUDMA_ADDR(ch), (addr & 0xFFFFFFFF));
if (ret == 0)
ret = pmu_mmio_write(CSUDMA_ADDR_MSB(ch), (addr >> 32));
if (ret == 0)
ret = pmu_mmio_write(CSUDMA_SIZE(ch), (sz | flags));
return ret;
}
static int csu_aes_reset(void)
{
/* Reset AES (set and clear) */
int ret = pmu_mmio_write(CSU_AES_RESET, 1);
if (ret == 0)
ret = pmu_mmio_write(CSU_AES_RESET, 0);
return ret;
}
static int csu_dma_config(int ch, int doSwap)
{
int ret = 0;
uint32_t regs, reg;
regs = reg = pmu_mmio_read(CSUDMA_CTRL(ch));
if (doSwap)
reg |= CSUDMA_CTRL_ENDIANNESS;
else
reg &= ~CSUDMA_CTRL_ENDIANNESS;
if (regs != reg)
ret = pmu_mmio_write(CSUDMA_CTRL(ch), reg);
return ret;
}
/* AES GCM Encrypt or Decrypt with Device Key setup by CSU ROM */
/* Output must also have room for updated IV at end */
#define AES_GCM_TAG_SZ 12
int csu_aes(int enc, const uint8_t* iv, const uint8_t* in, uint8_t* out, uint32_t sz)
{
int ret;
uint32_t reg;
/* Flush data cache for variables used */
flush_dcache_range((unsigned long)iv, (unsigned long)iv + AES_GCM_TAG_SZ);
flush_dcache_range((unsigned long)in, (unsigned long)in);
flush_dcache_range((unsigned long)out, (unsigned long)out + AES_GCM_TAG_SZ);
/* Configure SSS for DMA <-> AES */
ret = pmu_mmio_write(CSU_SSS_CFG,
(CSU_SSS_CFG_AES(CSU_SSS_CFG_SRC_DMA) |
CSU_SSS_CFG_DMA(CSU_SSS_CFG_SRC_AES)));
/* Reset AES (set and clear) */
if (ret == 0)
ret = csu_aes_reset();
/* Setup AES GCM Key (use device key) */
if (ret == 0)
ret = pmu_mmio_write(CSU_AES_KEY_SRC, CSU_AES_KEY_SRC_DEVICE_KEY);
/* Trigger key load */
if (ret == 0)
ret = pmu_mmio_write(CSU_AES_KEY_LOAD, 1);
/* Wait till key init done */
if (ret == 0)
ret = pmu_mmio_wait(CSU_AES_STATUS, CSU_AES_STATUS_KEY_INIT_DONE,
CSU_AES_STATUS_KEY_INIT_DONE, CSU_AES_TIMEOUT);
/* Enable DMA byte swapping */
if (ret == 0)
ret = csu_dma_config(CSUDMA_CH_SRC, 1);
if (ret == 0)
ret = csu_dma_config(CSUDMA_CH_DST, 1);
/* Set encrypt or decrypt */
if (ret == 0)
ret = pmu_mmio_write(CSU_AES_CFG, enc);
/* Issue start and wait for DMA IV and data */
if (ret == 0)
ret = pmu_mmio_write(CSU_AES_START_MSG, 1);
/* Send IV with byte swap (not last) */
if (ret == 0)
ret = csu_dma_transfer(CSUDMA_CH_SRC,
(uintptr_t)iv, AES_GCM_TAG_SZ, 0);
/* wait for IV to send and cear interrupt */
if (ret == 0)
ret = csu_dma_wait_done(CSUDMA_CH_SRC);
/* Setup data to recieve */
if (ret == 0)
ret = csu_dma_transfer(CSUDMA_CH_DST,
(uintptr_t)out, sz + AES_GCM_TAG_SZ, 0);
/* Send data */
if (ret == 0)
ret = csu_dma_transfer(CSUDMA_CH_SRC,
(uintptr_t)in, sz, CSUDMA_SIZE_LAST_WORD);
/* Wait for DMA to complete and clear */
if (ret == 0)
ret = csu_dma_wait_done(CSUDMA_CH_SRC);
if (ret == 0)
ret = csu_dma_wait_done(CSUDMA_CH_DST);
/* Disable DMA byte swapping */
if (ret == 0)
ret = csu_dma_config(CSUDMA_CH_SRC, 0);
if (ret == 0)
ret = csu_dma_config(CSUDMA_CH_DST, 0);
/* Wait for AES done */
if (ret == 0)
ret = pmu_mmio_wait(CSU_AES_STATUS, CSU_AES_STATUS_BUSY,
0, CSU_AES_TIMEOUT);
return ret;
}
/* zero the kup and expanded key */
int csu_aes_key_zero(void)
{
int ret;
uint32_t reg = pmu_mmio_read(CSU_AES_KEY_CLEAR);
ret = pmu_mmio_write(CSU_AES_KEY_CLEAR,
(reg | CSU_AES_KEY_CLEAR_KUP | CSU_AES_KEY_CLEAR_EXP));
if (ret == 0) {
ret = pmu_mmio_wait(CSU_AES_STATUS,
(CSU_AES_STATUS_AES_KEY_ZEROED | CSU_AES_STATUS_KUP_ZEROED),
(CSU_AES_STATUS_AES_KEY_ZEROED | CSU_AES_STATUS_KUP_ZEROED),
CSU_AES_TIMEOUT);
}
return ret;
}
#ifdef CSU_PUF_ROT
#define KEY_WRAP_SZ 32
/* Red (sensitive key), Black (protected key), Grey (unknown) */
/* Example key to encrypt */
static const uint8_t XALIGNED(32) redKey[KEY_WRAP_SZ] = {
0x64, 0xF0, 0x3A, 0xFD, 0x7D, 0x0C, 0x70, 0xD2,
0x59, 0x1C, 0xDF, 0x34, 0x30, 0x5F, 0x7B, 0x8A,
0x5B, 0xA4, 0x59, 0x3C, 0x0A, 0x0E, 0x1B, 0x8C,
0x5E, 0xCD, 0xFF, 0x9F, 0x59, 0x00, 0x19, 0x2C
};
/* Example IV to use for wrapping */
static const uint8_t XALIGNED(32) blackIv[AES_GCM_TAG_SZ] = {
0xD1, 0x42, 0xAC, 0x7C, 0x56, 0x0F, 0x15, 0x8B,
0xA9, 0x5A, 0x21, 0x31
};
static uint8_t XALIGNED(32) blackKey[KEY_WRAP_SZ+AES_GCM_TAG_SZ];
#endif
int csu_init(void) int csu_init(void)
{ {
int ret = 0; int ret = 0;
#ifdef CSU_PUF_ROT #ifdef CSU_PUF_ROT
uint32_t syndrome[CSU_PUF_SYNDROME_WORDS]; uint32_t syndrome[CSU_PUF_SYNDROME_WORDS];
uint32_t syndromeSz = (uint32_t)sizeof(syndrome);
uint32_t chash=0, aux=0; uint32_t chash=0, aux=0;
#if defined(DEBUG_CSU) && DEBUG_CSU >= 1
uint32_t idx;
#endif
#endif #endif
uint32_t reg1 = pmu_mmio_read(CSU_IDCODE); uint32_t reg1 = pmu_mmio_read(CSU_IDCODE);
uint32_t reg2 = pmu_mmio_read(CSU_VERSION); uint32_t reg2 = pmu_mmio_read(CSU_VERSION);
uint64_t ms;
wolfBoot_printf("CSU ID 0x%08x, Ver 0x%08x\n", wolfBoot_printf("CSU ID 0x%08x, Ver 0x%08x\n",
reg1, reg2 & CSU_VERSION_MASK); reg1, reg2 & CSU_VERSION_MASK);
@ -403,7 +625,58 @@ int csu_init(void)
#endif #endif
#ifdef CSU_PUF_ROT #ifdef CSU_PUF_ROT
ret = csu_puf_register(syndrome, &syndromeSz, &chash, &aux); reg1 = pmu_mmio_read(CSU_PUF_STATUS);
wolfBoot_printf("PUF Status 0x%08x\n", reg1);
/* Read eFuse SEC ctrl bits */
pmu_efuse_read(ZYNQMP_EFUSE_SEC_CTRL, &reg1, sizeof(reg1));
wolfBoot_printf("eFuse SEC_CTRL 0x%08x\n", reg1);
/* Read eFUSE helper data */
pmu_efuse_read(ZYNQMP_EFUSE_PUF_CHASH, &reg1, sizeof(reg1));
pmu_efuse_read(ZYNQMP_EFUSE_PUF_AUX, &reg2, sizeof(reg2));
wolfBoot_printf("eFuse PUF CHASH 0x%08x, AUX 0x%08x\n", reg1, reg2);
memset(syndrome, 0, sizeof(syndrome));
ms = hal_timer_ms();
ret = csu_puf_register(syndrome, &chash, &aux);
wolfBoot_printf("CSU Register PUF %d: %dms\n", ret, hal_timer_ms() - ms);
if (ret == 0) {
ms = hal_timer_ms();
/* regenerate - load kek */
ret = csu_puf_regeneration(syndrome, chash, aux);
wolfBoot_printf("CSU Regen PUF %d: %dms\n", ret, hal_timer_ms() - ms);
}
if (ret == 0) {
/* Use CSU ROM device key and IV to encrypt the red key */
/* Possible PUF syndrome location 0xFFC30000 */
#if defined(DEBUG_CSU) && DEBUG_CSU >= 1
wolfBoot_printf("Red Key %d\n", sizeof(redKey));
for (idx=0; idx<sizeof(redKey); idx++) {
wolfBoot_printf("%02x", redKey[idx]);
}
wolfBoot_printf("\nBlack IV %d\n", sizeof(blackIv));
for (idx=0; idx<sizeof(blackIv); idx++) {
wolfBoot_printf("%02x", blackIv[idx]);
}
wolfBoot_printf("\n");
#endif
ret = csu_aes(CSU_AES_CFG_ENC, blackIv, redKey, blackKey, KEY_WRAP_SZ);
#if defined(DEBUG_CSU) && DEBUG_CSU >= 1
wolfBoot_printf("Black Key %d\n", KEY_WRAP_SZ);
for (idx=0; idx<KEY_WRAP_SZ; idx++) {
wolfBoot_printf("%02x", blackKey[idx]);
}
wolfBoot_printf("\nNew IV %d\n", AES_GCM_TAG_SZ);
for (idx=0; idx<AES_GCM_TAG_SZ; idx++) {
wolfBoot_printf("%02x", blackKey[KEY_WRAP_SZ+idx]);
}
wolfBoot_printf("\n");
#endif
}
#endif #endif
return ret; return ret;
@ -415,13 +688,7 @@ int csu_init(void)
/* Xilinx BSP Driver */ /* Xilinx BSP Driver */
/* Aligned page data buffer for DMA */ /* Aligned page data buffer for DMA */
#ifdef __ICCARM__ static uint8_t XALIGNED(32) pageData[FLASH_PAGE_SIZE];
#pragma data_alignment = 32
static uint8_t pageData[FLASH_PAGE_SIZE];
#pragma data_alignment = 4
#else
static uint8_t pageData[FLASH_PAGE_SIZE] __attribute__ ((aligned(32)));;
#endif
static int qspi_transfer(QspiDev_t* pDev, static int qspi_transfer(QspiDev_t* pDev,
const uint8_t* cmdData, uint32_t cmdSz, const uint8_t* cmdData, uint32_t cmdSz,
const uint8_t* txData, uint32_t txSz, const uint8_t* txData, uint32_t txSz,
@ -823,7 +1090,8 @@ static int qspi_transfer(QspiDev_t* pDev,
xferSz = qspi_calc_exp(xferSz, &reg_genfifo); xferSz = qspi_calc_exp(xferSz, &reg_genfifo);
} }
GQSPIDMA_DST = (unsigned long)dmarxptr; GQSPIDMA_DST = ((uintptr_t)dmarxptr & 0xFFFFFFFF);
GQSPIDMA_DST_MSB = ((uintptr_t)dmarxptr >> 32);
GQSPIDMA_SIZE = xferSz; GQSPIDMA_SIZE = xferSz;
GQSPIDMA_IER = GQSPIDMA_ISR_DONE; /* enable DMA done interrupt */ GQSPIDMA_IER = GQSPIDMA_ISR_DONE; /* enable DMA done interrupt */
flush_dcache_range((unsigned long)dmarxptr, flush_dcache_range((unsigned long)dmarxptr,

View File

@ -288,20 +288,22 @@
/* eFUSE support */ /* eFUSE support */
#define ZYNQMP_EFUSE_BASE 0xFFCC0000 #define ZYNQMP_EFUSE_BASE 0xFFCC0000
#define ZYNQMP_EFUSE_STATUS (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x0008))) #define ZYNQMP_EFUSE_STATUS (ZYNQMP_EFUSE_BASE + 0x0008)
#define ZYNQMP_EFUSE_SEC_CTRL (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x1058))) #define ZYNQMP_EFUSE_PUF_CHASH (ZYNQMP_EFUSE_BASE + 0x1050)
#define ZYNQMP_EFUSE_PPK0_0 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A0))) #define ZYNQMP_EFUSE_PUF_AUX (ZYNQMP_EFUSE_BASE + 0x1054)
#define ZYNQMP_EFUSE_PPK0_1 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A4))) #define ZYNQMP_EFUSE_SEC_CTRL (ZYNQMP_EFUSE_BASE + 0x1058)
#define ZYNQMP_EFUSE_PPK0_2 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A8))) #define ZYNQMP_EFUSE_PPK0_0 (ZYNQMP_EFUSE_BASE + 0x10A0)
#define ZYNQMP_EFUSE_PPK0_3 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10AC))) #define ZYNQMP_EFUSE_PPK0_1 (ZYNQMP_EFUSE_BASE + 0x10A4)
#define ZYNQMP_EFUSE_PPK0_4 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B0))) #define ZYNQMP_EFUSE_PPK0_2 (ZYNQMP_EFUSE_BASE + 0x10A8)
#define ZYNQMP_EFUSE_PPK0_5 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B4))) #define ZYNQMP_EFUSE_PPK0_3 (ZYNQMP_EFUSE_BASE + 0x10AC)
#define ZYNQMP_EFUSE_PPK0_6 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B8))) #define ZYNQMP_EFUSE_PPK0_4 (ZYNQMP_EFUSE_BASE + 0x10B0)
#define ZYNQMP_EFUSE_PPK0_7 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10BC))) #define ZYNQMP_EFUSE_PPK0_5 (ZYNQMP_EFUSE_BASE + 0x10B4)
#define ZYNQMP_EFUSE_PPK0_8 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C0))) #define ZYNQMP_EFUSE_PPK0_6 (ZYNQMP_EFUSE_BASE + 0x10B8)
#define ZYNQMP_EFUSE_PPK0_9 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C4))) #define ZYNQMP_EFUSE_PPK0_7 (ZYNQMP_EFUSE_BASE + 0x10BC)
#define ZYNQMP_EFUSE_PPK0_10 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C8))) #define ZYNQMP_EFUSE_PPK0_8 (ZYNQMP_EFUSE_BASE + 0x10C0)
#define ZYNQMP_EFUSE_PPK0_11 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10CC))) #define ZYNQMP_EFUSE_PPK0_9 (ZYNQMP_EFUSE_BASE + 0x10C4)
#define ZYNQMP_EFUSE_PPK0_10 (ZYNQMP_EFUSE_BASE + 0x10C8)
#define ZYNQMP_EFUSE_PPK0_11 (ZYNQMP_EFUSE_BASE + 0x10CC)
/* eFUSE STATUS Registers */ /* eFUSE STATUS Registers */
#define ZYNQMP_EFUSE_STATUS_CACHE_DONE (1UL << 5) #define ZYNQMP_EFUSE_STATUS_CACHE_DONE (1UL << 5)
@ -430,13 +432,13 @@
/* SSS - Secure Stream Switch */ /* SSS - Secure Stream Switch */
#define CSU_SSS_CFG (CSU_BASE + 0x0008U) #define CSU_SSS_CFG (CSU_BASE + 0x0008U)
#define CSU_SSS_CFG_PCAP_MASK 0x0000000FU #define CSU_SSS_CFG_PCAP_MASK 0x0000000FU
#define CSU_SSS_CFG_PCAP(n) (((n) << 0) & CSU_SSS_CFG_PCAP_SSS_MASK) #define CSU_SSS_CFG_PCAP(n) (((n) << 0) & CSU_SSS_CFG_PCAP_MASK)
#define CSU_SSS_CFG_DMA_MASK 0x000000F0U #define CSU_SSS_CFG_DMA_MASK 0x000000F0U
#define CSU_SSS_CFG_DMA(n) (((n) << 4) & CSU_SSS_CFG_DMA_SSS_MASK) #define CSU_SSS_CFG_DMA(n) (((n) << 4) & CSU_SSS_CFG_DMA_MASK)
#define CSU_SSS_CFG_AES_MASK 0x00000F00U #define CSU_SSS_CFG_AES_MASK 0x00000F00U
#define CSU_SSS_CFG_AES(n) (((n) << 8) & CSU_SSS_CFG_AES_SSS_MASK) #define CSU_SSS_CFG_AES(n) (((n) << 8) & CSU_SSS_CFG_AES_MASK)
#define CSU_SSS_CFG_SHA_MASK 0x0000F000U #define CSU_SSS_CFG_SHA_MASK 0x0000F000U
#define CSU_SSS_CFG_SHA(n) (((n) << 12) & CSU_SSS_CFG_SHA_SSS_MASK) #define CSU_SSS_CFG_SHA(n) (((n) << 12) & CSU_SSS_CFG_SHA_MASK)
/* Data Sources */ /* Data Sources */
#define CSU_SSS_CFG_SRC_NONE 0x0 #define CSU_SSS_CFG_SRC_NONE 0x0
#define CSU_SSS_CFG_SRC_PCAP 0x3 /* Processor Configuration Access Port */ #define CSU_SSS_CFG_SRC_PCAP 0x3 /* Processor Configuration Access Port */
@ -471,6 +473,10 @@
#define CSU_AES_KEY_CLEAR_KUP (1 << 1) /* Zeroize KUP key */ #define CSU_AES_KEY_CLEAR_KUP (1 << 1) /* Zeroize KUP key */
#define CSU_AES_KEY_CLEAR_EXP (1 << 0) /* Zeroize expanded key */ #define CSU_AES_KEY_CLEAR_EXP (1 << 0) /* Zeroize expanded key */
#define CSU_AES_CFG_DEC 0
#define CSU_AES_CFG_ENC 1
/* PUF */ /* PUF */
#define CSU_PUF_CMD (CSU_BASE + 0x4000U) #define CSU_PUF_CMD (CSU_BASE + 0x4000U)
#define CSU_PUF_CFG0 (CSU_BASE + 0x4004U) #define CSU_PUF_CFG0 (CSU_BASE + 0x4004U)
@ -506,7 +512,7 @@
/* CSU DMA */ /* CSU DMA */
/* Addresses and sizes must be word aligned last two bits = 0 */ /* Addresses and sizes must be word aligned last two bits = 0 */
/* 128 x 32-bit data FIFO for each channel (two channels) */ /* 128 x 32-bit data FIFO for each channel (two channels) */
#define CSUDMA_BASE(ch) (0xFFC80000UL * (((ch) & 0x1) * 0x800)) #define CSUDMA_BASE(ch) (0xFFC80000UL + (((ch) & 0x1) * 0x800))
#define CSUDMA_ADDR(ch) (CSUDMA_BASE(ch) + 0x0000U) /* Mem address (lower 32-bits) */ #define CSUDMA_ADDR(ch) (CSUDMA_BASE(ch) + 0x0000U) /* Mem address (lower 32-bits) */
#define CSUDMA_ADDR_MSB(ch) (CSUDMA_BASE(ch) + 0x0028U) /* (upper 17 bits) */ #define CSUDMA_ADDR_MSB(ch) (CSUDMA_BASE(ch) + 0x0028U) /* (upper 17 bits) */
#define CSUDMA_SIZE(ch) (CSUDMA_BASE(ch) + 0x0004U) /* DMA transfer payload size */ #define CSUDMA_SIZE(ch) (CSUDMA_BASE(ch) + 0x0004U) /* DMA transfer payload size */
@ -519,6 +525,8 @@
#define CSUDMA_IDIS(ch) (CSUDMA_BASE(ch) + 0x001CU) #define CSUDMA_IDIS(ch) (CSUDMA_BASE(ch) + 0x001CU)
#define CSUDMA_IMASK(ch) (CSUDMA_BASE(ch) + 0x0020U) #define CSUDMA_IMASK(ch) (CSUDMA_BASE(ch) + 0x0020U)
#define CSUDMA_SIZE_LAST_WORD (1 << 0)
#define CSUDMA_STS_DONE_CNT (0x07 << 13) #define CSUDMA_STS_DONE_CNT (0x07 << 13)
#define CSUDMA_STS_SRC_FIFO_LEVEL (0xFF << 5) #define CSUDMA_STS_SRC_FIFO_LEVEL (0xFF << 5)
#define CSUDMA_STS_RD_OUTSTANDING (0x0F << 1) #define CSUDMA_STS_RD_OUTSTANDING (0x0F << 1)