From 64c74b8233e40bfefc380ceceffd57282591addc Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 7 Feb 2025 17:51:25 -0800 Subject: [PATCH] Progress on RoT. Creation of PUF, Regeneration and use of it for AES Key wrapping. --- IDE/XilinxSDK/README.md | 47 +++++- hal/zynq.c | 364 ++++++++++++++++++++++++++++++++++------ hal/zynq.h | 46 ++--- 3 files changed, 386 insertions(+), 71 deletions(-) diff --git a/IDE/XilinxSDK/README.md b/IDE/XilinxSDK/README.md index e739f2bd..765772ef 100644 --- a/IDE/XilinxSDK/README.md +++ b/IDE/XilinxSDK/README.md @@ -274,11 +274,50 @@ 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 +PUF Status 0x00000002 +eFuse SEC_CTRL 0x00000000 +eFuse PUF CHASH 0x00000000, AUX 0x00000000 CSU Puf Register -Ret 0, SyndromeSz 560, CHASH 0xA014DD88, AUX 0x00408A64 -462273FBECB98600E3D099415B30F1AF3DD6B29369102847EC61B708AB37AF2A6999596BC9071F84773142631BA2C1109C14FACC156B7343FB8436CE06292DB95B4C1941E6DC8F982404462DEFB91792076EC428D1C0C8A10F271E3B67F652F562885384B97717B0AA3B8B24CC0AD54D1641860355C343D0FE38E1F6D6F4289C38AEC5EFD1046C736423EF881DE0A04F64165B9D275E5050D91F3EBD9241FE67D55BEA336E46B174112F86361FB2AA78197C6BF5812533E4EC1E88BC7125366C5E8BE8B70483FE5FC144B9F608D72964690D6DE0E8E8B65C23D2B9ED8262DF77AC4E2EE67ABF18DC2EC452B0731B0E229CAD555BC61CF0FE26066F1E54C33C7DC7C86DC56BFFF391689F937CD3C565D4B28D68C74793562B4938D6FE5667644F247CEFCCC926A57B54048A4986E8AC9F1B7D673CC14C2CC5DDD4A548986BF925B938FF92D6F7D3A2CD1ACD3943C6A35CF9CFFD8A786682032D3826CFDBAD38FDCBFD2B3480A933CAAEB391685E58A0BBDECDF9B69A5D685AE0D93BAC6B55E9D447565FBFF68E35F12B779EBC5918E0A5CD3CE00C7B5AF833A33CACD0F871A2FB89218BC2F1F02F0B68CB65F9B122D5B5D72116F1F6ED111B87DEB7E1BC4873E5889C2C6915CD362B75DA211264CF66F093C368F37EC54721AAFA6313C5892514011CE9BFDD72C51FDEA7320377692A1AF8FD0D563A66E465AA9AD51BF91B2A5CE6178E517032D3786B1F714681339C2286BBE5E71B7334F923FABBFBEC382E2EF6880471BB13956 +Ret 0, Syndrome 1544, CHASH 0x9B7A8C30, AUX 0x005AE021 +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 diff --git a/hal/zynq.c b/hal/zynq.c index 4ba41c80..6658ae16 100644 --- a/hal/zynq.c +++ b/hal/zynq.c @@ -183,6 +183,30 @@ static void smc_call(struct pt_regs *args) #define PM_MMIO_WRITE 0x13 #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, * which is the PMU Firmware */ static int pmu_request(uint32_t api_id, @@ -219,6 +243,27 @@ uint32_t pmu_get_version(void) 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 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); } +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_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_UPDATE 2U #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]; 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)heap; (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) { @@ -269,7 +323,7 @@ int wc_Sha3_384_Update(wc_Sha3* sha, const byte* data, word32 len) flush_dcache_range( (unsigned long)data, (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) { @@ -277,7 +331,7 @@ int wc_Sha3_384_Final(wc_Sha3* sha, byte* out) flush_dcache_range( (unsigned long)out, (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) { @@ -289,28 +343,13 @@ void wc_Sha3_384_Free(wc_Sha3* sha) /* CSU PUF */ #ifdef CSU_PUF_ROT +/* 1544 bytes is fixed size for boot header used by CSU ROM */ #define CSU_PUF_SYNDROME_WORDS 386 -#ifndef CSU_PUF_REG_TIMEOUT -#define CSU_PUF_REG_TIMEOUT 500000 +#ifndef CSU_PUF_REG_TRIES +#define CSU_PUF_REG_TRIES 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 csu_puf_register(uint32_t* syndrome, uint32_t* chash, uint32_t* aux) { int ret; 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); while (ret == 0) { /* wait for PUF word ready */ - puf_status = 0; - ret = csu_puf_wait_word(&puf_status); + ret = pmu_mmio_wait(CSU_PUF_STATUS, + CSU_PUF_STATUS_SYN_WRD_RDY_MASK, + CSU_PUF_STATUS_SYN_WRD_RDY_MASK, + CSU_PUF_REG_TRIES); if (ret != 0) break; - if ((idx * 4) > *syndromeSz) { + if ((idx > CSU_PUF_SYNDROME_WORDS-2) /* room for chash and aux */) { ret = -2; /* overrun */ 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) { *chash = pmu_mmio_read(CSU_PUF_WORD); + syndrome[CSU_PUF_SYNDROME_WORDS-2] = *chash; *aux = (puf_status & CSU_PUF_STATUS_AUX_MASK) >> 4; + syndrome[CSU_PUF_SYNDROME_WORDS-1] = *aux; ret = 0; break; } - else { - /* Read in the syndrome */ - syndrome[idx++] = pmu_mmio_read(CSU_PUF_WORD); - } } - *syndromeSz = idx * 4; #if defined(DEBUG_CSU) && DEBUG_CSU >= 1 - wolfBoot_printf("Ret %d, SyndromeSz %d, CHASH 0x%08x, AUX 0x%08x\n", - ret, *syndromeSz, *chash, *aux); - #if DEBUG_CSU >= 2 - for (idx=0; idx<*syndromeSz/4; idx++) { - wolfBoot_printf("%02x", syndrome[idx]); + wolfBoot_printf("Ret %d, Syndrome %d, CHASH 0x%08x, AUX 0x%08x\n", + ret, (CSU_PUF_SYNDROME_WORDS*4), *chash, *aux); + for (idx=0; idx> 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 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; + #if defined(DEBUG_CSU) && DEBUG_CSU >= 1 + uint32_t idx; + #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); + uint64_t ms; wolfBoot_printf("CSU ID 0x%08x, Ver 0x%08x\n", reg1, reg2 & CSU_VERSION_MASK); @@ -403,7 +625,58 @@ int csu_init(void) #endif #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, ®1, sizeof(reg1)); + wolfBoot_printf("eFuse SEC_CTRL 0x%08x\n", reg1); + + /* Read eFUSE helper data */ + pmu_efuse_read(ZYNQMP_EFUSE_PUF_CHASH, ®1, sizeof(reg1)); + pmu_efuse_read(ZYNQMP_EFUSE_PUF_AUX, ®2, 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= 1 + wolfBoot_printf("Black Key %d\n", KEY_WRAP_SZ); + for (idx=0; idx> 32); GQSPIDMA_SIZE = xferSz; GQSPIDMA_IER = GQSPIDMA_ISR_DONE; /* enable DMA done interrupt */ flush_dcache_range((unsigned long)dmarxptr, diff --git a/hal/zynq.h b/hal/zynq.h index adfe6fdc..c86ba93d 100644 --- a/hal/zynq.h +++ b/hal/zynq.h @@ -288,20 +288,22 @@ /* eFUSE support */ #define ZYNQMP_EFUSE_BASE 0xFFCC0000 -#define ZYNQMP_EFUSE_STATUS (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x0008))) -#define ZYNQMP_EFUSE_SEC_CTRL (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x1058))) -#define ZYNQMP_EFUSE_PPK0_0 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A0))) -#define ZYNQMP_EFUSE_PPK0_1 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A4))) -#define ZYNQMP_EFUSE_PPK0_2 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10A8))) -#define ZYNQMP_EFUSE_PPK0_3 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10AC))) -#define ZYNQMP_EFUSE_PPK0_4 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B0))) -#define ZYNQMP_EFUSE_PPK0_5 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B4))) -#define ZYNQMP_EFUSE_PPK0_6 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10B8))) -#define ZYNQMP_EFUSE_PPK0_7 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10BC))) -#define ZYNQMP_EFUSE_PPK0_8 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C0))) -#define ZYNQMP_EFUSE_PPK0_9 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C4))) -#define ZYNQMP_EFUSE_PPK0_10 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10C8))) -#define ZYNQMP_EFUSE_PPK0_11 (*((volatile uint32_t*)(ZYNQMP_EFUSE_BASE + 0x10CC))) +#define ZYNQMP_EFUSE_STATUS (ZYNQMP_EFUSE_BASE + 0x0008) +#define ZYNQMP_EFUSE_PUF_CHASH (ZYNQMP_EFUSE_BASE + 0x1050) +#define ZYNQMP_EFUSE_PUF_AUX (ZYNQMP_EFUSE_BASE + 0x1054) +#define ZYNQMP_EFUSE_SEC_CTRL (ZYNQMP_EFUSE_BASE + 0x1058) +#define ZYNQMP_EFUSE_PPK0_0 (ZYNQMP_EFUSE_BASE + 0x10A0) +#define ZYNQMP_EFUSE_PPK0_1 (ZYNQMP_EFUSE_BASE + 0x10A4) +#define ZYNQMP_EFUSE_PPK0_2 (ZYNQMP_EFUSE_BASE + 0x10A8) +#define ZYNQMP_EFUSE_PPK0_3 (ZYNQMP_EFUSE_BASE + 0x10AC) +#define ZYNQMP_EFUSE_PPK0_4 (ZYNQMP_EFUSE_BASE + 0x10B0) +#define ZYNQMP_EFUSE_PPK0_5 (ZYNQMP_EFUSE_BASE + 0x10B4) +#define ZYNQMP_EFUSE_PPK0_6 (ZYNQMP_EFUSE_BASE + 0x10B8) +#define ZYNQMP_EFUSE_PPK0_7 (ZYNQMP_EFUSE_BASE + 0x10BC) +#define ZYNQMP_EFUSE_PPK0_8 (ZYNQMP_EFUSE_BASE + 0x10C0) +#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 */ #define ZYNQMP_EFUSE_STATUS_CACHE_DONE (1UL << 5) @@ -430,13 +432,13 @@ /* SSS - Secure Stream Switch */ #define CSU_SSS_CFG (CSU_BASE + 0x0008U) #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(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(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(n) (((n) << 12) & CSU_SSS_CFG_SHA_SSS_MASK) +#define CSU_SSS_CFG_SHA(n) (((n) << 12) & CSU_SSS_CFG_SHA_MASK) /* Data Sources */ #define CSU_SSS_CFG_SRC_NONE 0x0 #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_EXP (1 << 0) /* Zeroize expanded key */ +#define CSU_AES_CFG_DEC 0 +#define CSU_AES_CFG_ENC 1 + + /* PUF */ #define CSU_PUF_CMD (CSU_BASE + 0x4000U) #define CSU_PUF_CFG0 (CSU_BASE + 0x4004U) @@ -506,7 +512,7 @@ /* CSU DMA */ /* Addresses and sizes must be word aligned last two bits = 0 */ /* 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_MSB(ch) (CSUDMA_BASE(ch) + 0x0028U) /* (upper 17 bits) */ #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_IMASK(ch) (CSUDMA_BASE(ch) + 0x0020U) +#define CSUDMA_SIZE_LAST_WORD (1 << 0) + #define CSUDMA_STS_DONE_CNT (0x07 << 13) #define CSUDMA_STS_SRC_FIFO_LEVEL (0xFF << 5) #define CSUDMA_STS_RD_OUTSTANDING (0x0F << 1)