fsl_puf.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. /*
  2. * Copyright 2018 NXP
  3. * All rights reserved.
  4. *
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_puf.h"
  9. #include "fsl_clock.h"
  10. #include "fsl_reset.h"
  11. #include "fsl_common.h"
  12. static void puf_wait_usec(uint32_t usec, uint32_t coreClockFrequencyMHz)
  13. {
  14. while (usec > 0)
  15. {
  16. usec--;
  17. /* number of MHz is directly number of core clocks to wait 1 usec. */
  18. /* the while loop below is actually 4 clocks so divide by 4 for ~1 usec */
  19. register uint32_t ticksCount = coreClockFrequencyMHz / 4u + 1u;
  20. while (ticksCount--)
  21. {
  22. }
  23. }
  24. }
  25. static status_t puf_waitForInit(PUF_Type *base)
  26. {
  27. status_t status = kStatus_Fail;
  28. /* wait until status register reads non-zero. All zero is not valid. It should be BUSY or OK or ERROR */
  29. while (0 == base->STAT)
  30. {
  31. }
  32. /* wait if busy */
  33. while ((base->STAT & PUF_STAT_BUSY_MASK) != 0)
  34. {
  35. }
  36. /* return status */
  37. if (base->STAT & (PUF_STAT_SUCCESS_MASK | PUF_STAT_ERROR_MASK))
  38. {
  39. status = kStatus_Success;
  40. }
  41. return status;
  42. }
  43. static void puf_powerOn(PUF_Type *base)
  44. {
  45. #if defined(FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL) && (FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL > 0)
  46. /* RT6xxs */
  47. base->PWRCTRL = 0x5u;
  48. base->PWRCTRL = 0xDu;
  49. base->PWRCTRL = 0x9u;
  50. #else /* !FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL */
  51. /* Niobe4 & Aruba FL */
  52. base->PWRCTRL = PUF_PWRCTRL_RAMON_MASK;
  53. while (0 == (PUF_PWRCTRL_RAMSTAT_MASK & base->PWRCTRL))
  54. {
  55. }
  56. #endif /* FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL */
  57. }
  58. static status_t puf_powerCycle(PUF_Type *base, uint32_t dischargeTimeMsec, uint32_t coreClockFrequencyHz)
  59. {
  60. #if defined(FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL) && (FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL > 0)
  61. /* RT6xxs */
  62. uint32_t coreClockFrequencyMHz = coreClockFrequencyHz / 1000000u;
  63. base->PWRCTRL = 0xDu; /* disable RAM CK */
  64. /* enter ASPS mode */
  65. base->PWRCTRL = 0xCu; /* SLEEP = 1 */
  66. base->PWRCTRL = 0x8u; /* enable RAM CK */
  67. base->PWRCTRL = 0xF8u; /* SLEEP=1, PSW*=1 */
  68. /* Wait enough time to discharge fully */
  69. puf_wait_usec(dischargeTimeMsec * 1000u, coreClockFrequencyHz / 1000000u);
  70. /* write PWRCTRL=0x38. wait time > 1 us */
  71. base->PWRCTRL = 0x38u; /* SLEEP=1. PSWSMALL*=0. PSWLARGE*=1. */
  72. puf_wait_usec(1, coreClockFrequencyMHz);
  73. /* write PWRCTRL=0x8. wait time > 1 us */
  74. base->PWRCTRL = 0x08u; /* SLEEP=1. PSWSMALL*=0. PSWLARGE*=0 */
  75. puf_wait_usec(1, coreClockFrequencyMHz);
  76. base->PWRCTRL = 0xCu;
  77. base->PWRCTRL = 0xDu;
  78. base->PWRCTRL = 0x9u;
  79. /* Generate INITN low pulse */
  80. base->PWRCTRL = 0xDu;
  81. base->PWRCTRL = 0x5u;
  82. base->PWRCTRL = 0x1u;
  83. #else
  84. /* Niobe4 & Aruba FL */
  85. base->PWRCTRL = 0x0u;
  86. while (PUF_PWRCTRL_RAMSTAT_MASK & base->PWRCTRL)
  87. {
  88. }
  89. /* Wait enough time to discharge fully */
  90. puf_wait_usec(dischargeTimeMsec * 1000u, coreClockFrequencyHz / 1000000u);
  91. #endif
  92. /* Reset PUF and reenable power to PUF SRAM */
  93. RESET_PeripheralReset(kPUF_RST_SHIFT_RSTn);
  94. puf_powerOn(base);
  95. return kStatus_Success;
  96. }
  97. /*!
  98. * brief Initialize PUF
  99. *
  100. * This function enables power to PUF block and waits until the block initializes.
  101. *
  102. * param base PUF peripheral base address
  103. * param dischargeTimeMsec time in ms to wait for PUF SRAM to fully discharge
  104. * param coreClockFrequencyHz core clock frequency in Hz
  105. * return Status of the init operation
  106. */
  107. status_t PUF_Init(PUF_Type *base, uint32_t dischargeTimeMsec, uint32_t coreClockFrequencyHz)
  108. {
  109. status_t status = kStatus_Fail;
  110. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  111. CLOCK_EnableClock(kCLOCK_Puf);
  112. #endif
  113. /* Reset PUF */
  114. RESET_PeripheralReset(kPUF_RST_SHIFT_RSTn);
  115. /* Enable power to PUF SRAM */
  116. puf_powerOn(base);
  117. /* Wait for peripheral to become ready */
  118. status = puf_waitForInit(base);
  119. /* In case of error or enroll & start not allowed, do power-cycle */
  120. if ((status != kStatus_Success) || ((PUF_ALLOW_ALLOWENROLL_MASK | PUF_ALLOW_ALLOWSTART_MASK) !=
  121. (base->ALLOW & (PUF_ALLOW_ALLOWENROLL_MASK | PUF_ALLOW_ALLOWSTART_MASK))))
  122. {
  123. puf_powerCycle(base, dischargeTimeMsec, coreClockFrequencyHz);
  124. status = puf_waitForInit(base);
  125. }
  126. return status;
  127. }
  128. /*!
  129. * brief Denitialize PUF
  130. *
  131. * This function disables power to PUF SRAM and peripheral clock.
  132. *
  133. * param base PUF peripheral base address
  134. */
  135. void PUF_Deinit(PUF_Type *base, uint32_t dischargeTimeMsec, uint32_t coreClockFrequencyHz)
  136. {
  137. #if defined(FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL) && (FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL > 0)
  138. /* RT6xxs */
  139. base->PWRCTRL = 0xDu; /* disable RAM CK */
  140. /* enter ASPS mode */
  141. base->PWRCTRL = 0xCu; /* SLEEP = 1 */
  142. base->PWRCTRL = 0x8u; /* enable RAM CK */
  143. base->PWRCTRL = 0xF8u; /* SLEEP=1, PSW*=1 */
  144. #else /* !FSL_FEATURE_PUF_PWR_HAS_MANUAL_SLEEP_CONTROL */
  145. /* Niobe4 & Aruba FL */
  146. base->PWRCTRL = 0x00u;
  147. #endif
  148. /* Wait enough time to discharge fully */
  149. puf_wait_usec(dischargeTimeMsec * 1000u, coreClockFrequencyHz / 1000000u);
  150. RESET_SetPeripheralReset(kPUF_RST_SHIFT_RSTn);
  151. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  152. CLOCK_DisableClock(kCLOCK_Puf);
  153. #endif
  154. }
  155. /*!
  156. * brief Enroll PUF
  157. *
  158. * This function derives a digital fingerprint, generates the corresponding Activation Code (AC)
  159. * and returns it to be stored in an NVM or a file. This step needs to be
  160. * performed only once for each device. This function may be permanently disallowed by a fuse.
  161. *
  162. * param base PUF peripheral base address
  163. * param[out] activationCode Word aligned address of the resulting activation code.
  164. * param activationCodeSize Size of the activationCode buffer in bytes. Shall be 1192 bytes.
  165. * return Status of enroll operation.
  166. */
  167. status_t PUF_Enroll(PUF_Type *base, uint8_t *activationCode, size_t activationCodeSize)
  168. {
  169. status_t status = kStatus_Fail;
  170. uint32_t *activationCodeAligned = NULL;
  171. register uint32_t temp32 = 0;
  172. /* check that activation code buffer size is at least 1192 bytes */
  173. if (activationCodeSize < PUF_ACTIVATION_CODE_SIZE)
  174. {
  175. return kStatus_InvalidArgument;
  176. }
  177. /* only work with aligned activationCode */
  178. if (0x3u & (uintptr_t)activationCode)
  179. {
  180. return kStatus_InvalidArgument;
  181. }
  182. activationCodeAligned = (uint32_t *)(uintptr_t)activationCode;
  183. /* check if ENROLL is allowed */
  184. if (0x0u == (base->ALLOW & PUF_ALLOW_ALLOWENROLL_MASK))
  185. {
  186. return kStatus_Fail;
  187. }
  188. /* write PUF Enroll command */
  189. base->CTRL = PUF_CTRL_ENROLL_MASK;
  190. /* check status */
  191. while (0 == (base->STAT & (PUF_STAT_BUSY_MASK | PUF_STAT_ERROR_MASK)))
  192. {
  193. }
  194. /* read out AC */
  195. while (0 != (base->STAT & PUF_STAT_BUSY_MASK))
  196. {
  197. if (0 != (PUF_STAT_CODEOUTAVAIL_MASK & base->STAT))
  198. {
  199. temp32 = base->CODEOUTPUT;
  200. if (activationCodeSize >= sizeof(uint32_t))
  201. {
  202. *activationCodeAligned = temp32;
  203. activationCodeAligned++;
  204. activationCodeSize -= sizeof(uint32_t);
  205. }
  206. }
  207. }
  208. if ((base->STAT & PUF_STAT_SUCCESS_MASK) && (activationCodeSize == 0))
  209. {
  210. status = kStatus_Success;
  211. }
  212. return status;
  213. }
  214. /*!
  215. * brief Start PUF
  216. *
  217. * The Activation Code generated during the Enroll operation is used to
  218. * reconstruct the digital fingerprint. This needs to be done after every power-up
  219. * and reset.
  220. *
  221. * param base PUF peripheral base address
  222. * param activationCode Word aligned address of the input activation code.
  223. * param activationCodeSize Size of the activationCode buffer in bytes. Shall be 1192 bytes.
  224. * return Status of start operation.
  225. */
  226. status_t PUF_Start(PUF_Type *base, const uint8_t *activationCode, size_t activationCodeSize)
  227. {
  228. status_t status = kStatus_Fail;
  229. const uint32_t *activationCodeAligned = NULL;
  230. register uint32_t temp32 = 0;
  231. /* check that activation code size is at least 1192 bytes */
  232. if (activationCodeSize < 1192)
  233. {
  234. return kStatus_InvalidArgument;
  235. }
  236. /* only work with aligned activationCode */
  237. if (0x3u & (uintptr_t)activationCode)
  238. {
  239. return kStatus_InvalidArgument;
  240. }
  241. activationCodeAligned = (const uint32_t *)(uintptr_t)activationCode;
  242. /* check if START is allowed */
  243. if (0x0u == (base->ALLOW & PUF_ALLOW_ALLOWSTART_MASK))
  244. {
  245. return kStatus_Fail;
  246. }
  247. /* run PUF Start command */
  248. base->CTRL = PUF_CTRL_START_MASK;
  249. /* check status */
  250. while (0 == (base->STAT & (PUF_STAT_BUSY_MASK | PUF_STAT_ERROR_MASK)))
  251. {
  252. }
  253. /* while busy send AC */
  254. while (0 != (base->STAT & PUF_STAT_BUSY_MASK))
  255. {
  256. if (0 != (PUF_STAT_CODEINREQ_MASK & base->STAT))
  257. {
  258. if (activationCodeSize >= sizeof(uint32_t))
  259. {
  260. temp32 = *activationCodeAligned;
  261. activationCodeAligned++;
  262. activationCodeSize -= sizeof(uint32_t);
  263. }
  264. base->CODEINPUT = temp32;
  265. }
  266. }
  267. /* get status */
  268. if (0 != (base->STAT & PUF_STAT_SUCCESS_MASK))
  269. {
  270. status = kStatus_Success;
  271. }
  272. return status;
  273. }
  274. /*!
  275. * brief Set intrinsic key
  276. *
  277. * The digital fingerprint generated during the Enroll/Start
  278. * operations is used to generate a Key Code (KC) that defines a unique intrinsic
  279. * key. This KC is returned to be stored in an NVM or a file. This operation
  280. * needs to be done only once for each intrinsic key.
  281. * Each time a Set Intrinsic Key operation is executed a new unique key is
  282. * generated.
  283. *
  284. * param base PUF peripheral base address
  285. * param keyIndex PUF key index register
  286. * param keySize Size of the intrinsic key to generate in bytes.
  287. * param[out] keyCode Word aligned address of the resulting key code.
  288. * param keyCodeSize Size of the keyCode buffer in bytes. Shall be PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(keySize).
  289. * return Status of set intrinsic key operation.
  290. */
  291. status_t PUF_SetIntrinsicKey(
  292. PUF_Type *base, puf_key_index_register_t keyIndex, size_t keySize, uint8_t *keyCode, size_t keyCodeSize)
  293. {
  294. status_t status = kStatus_Fail;
  295. uint32_t *keyCodeAligned = NULL;
  296. register uint32_t temp32 = 0;
  297. /* check if SET KEY is allowed */
  298. if (0x0u == (base->ALLOW & PUF_ALLOW_ALLOWSETKEY_MASK))
  299. {
  300. return kStatus_Fail;
  301. }
  302. /* only work with aligned keyCode */
  303. if (0x3u & (uintptr_t)keyCode)
  304. {
  305. return kStatus_InvalidArgument;
  306. }
  307. /* Check that keySize is in the correct range and that it is multiple of 8 */
  308. if ((keySize < kPUF_KeySizeMin) || (keySize > kPUF_KeySizeMax) || (keySize & 0x7))
  309. {
  310. return kStatus_InvalidArgument;
  311. }
  312. /* check that keyCodeSize is correct for given keySize */
  313. if (keyCodeSize < PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(keySize))
  314. {
  315. return kStatus_InvalidArgument;
  316. }
  317. if ((uint32_t)keyIndex > kPUF_KeyIndexMax)
  318. {
  319. return kStatus_InvalidArgument;
  320. }
  321. keyCodeAligned = (uint32_t *)(uintptr_t)keyCode;
  322. /* program the key size and index */
  323. base->KEYSIZE = keySize >> 3;
  324. base->KEYINDEX = (uint32_t)keyIndex;
  325. /* start generate key command */
  326. base->CTRL = PUF_CTRL_GENERATEKEY_MASK;
  327. /* wait till command is accepted */
  328. while (0 == (base->STAT & (PUF_STAT_BUSY_MASK | PUF_STAT_ERROR_MASK)))
  329. {
  330. }
  331. /* while busy read KC */
  332. while (0 != (base->STAT & PUF_STAT_BUSY_MASK))
  333. {
  334. if (0 != (PUF_STAT_CODEOUTAVAIL_MASK & base->STAT))
  335. {
  336. temp32 = base->CODEOUTPUT;
  337. if (keyCodeSize >= sizeof(uint32_t))
  338. {
  339. *keyCodeAligned = temp32;
  340. keyCodeAligned++;
  341. keyCodeSize -= sizeof(uint32_t);
  342. }
  343. }
  344. }
  345. /* get status */
  346. if (0 != (base->STAT & PUF_STAT_SUCCESS_MASK))
  347. {
  348. status = kStatus_Success;
  349. }
  350. return status;
  351. }
  352. /*!
  353. * brief Set user key
  354. *
  355. * The digital fingerprint generated during the Enroll/Start
  356. * operations and a user key (UK) provided as input are used to
  357. * generate a Key Code (KC). This KC is sent returned to be stored
  358. * in an NVM or a file. This operation needs to be done only once for each user key.
  359. *
  360. * param base PUF peripheral base address
  361. * param keyIndex PUF key index register
  362. * param userKey Word aligned address of input user key.
  363. * param userKeySize Size of the input user key in bytes.
  364. * param[out] keyCode Word aligned address of the resulting key code.
  365. * param keyCodeSize Size of the keyCode buffer in bytes. Shall be PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(userKeySize).
  366. * return Status of set user key operation.
  367. */
  368. status_t PUF_SetUserKey(PUF_Type *base,
  369. puf_key_index_register_t keyIndex,
  370. const uint8_t *userKey,
  371. size_t userKeySize,
  372. uint8_t *keyCode,
  373. size_t keyCodeSize)
  374. {
  375. status_t status = kStatus_Fail;
  376. uint32_t *keyCodeAligned = NULL;
  377. const uint32_t *userKeyAligned = NULL; // RK why const?
  378. register uint32_t temp32 = 0;
  379. /* check if SET KEY is allowed */
  380. if (0x0u == (base->ALLOW & PUF_ALLOW_ALLOWSETKEY_MASK))
  381. {
  382. return kStatus_Fail;
  383. }
  384. /* only work with aligned keyCode */
  385. if (0x3u & (uintptr_t)keyCode)
  386. {
  387. return kStatus_InvalidArgument;
  388. }
  389. /* Check that userKeySize is in the correct range and that it is multiple of 8 */
  390. if ((userKeySize < kPUF_KeySizeMin) || (userKeySize > kPUF_KeySizeMax) || (userKeySize & 0x7))
  391. {
  392. return kStatus_InvalidArgument;
  393. }
  394. /* check that keyCodeSize is correct for given userKeySize */
  395. if (keyCodeSize < PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(userKeySize))
  396. {
  397. return kStatus_InvalidArgument;
  398. }
  399. if ((uint32_t)keyIndex > kPUF_KeyIndexMax)
  400. {
  401. return kStatus_InvalidArgument;
  402. }
  403. keyCodeAligned = (uint32_t *)(uintptr_t)keyCode;
  404. userKeyAligned = (const uint32_t *)(uintptr_t)userKey;
  405. /* program the key size and index */
  406. base->KEYSIZE = userKeySize >> 3; /* convert to 64-bit blocks */
  407. base->KEYINDEX = (uint32_t)keyIndex;
  408. /*if key index 0 - to be sent to AES, PRINCE, change endianess and */
  409. if (keyIndex == 0)
  410. {
  411. uint32_t * pa = (uint32_t *)userKeyAligned;
  412. uint32_t * pd = (uint32_t *)(&userKeyAligned[userKeySize >> 2]-1);
  413. uint32_t i;
  414. for(i = 0; i < (userKeySize >> 3); i++)
  415. {
  416. temp32 = *pa;
  417. *pa++ = swap_bytes(*pd);
  418. *pd-- = swap_bytes(temp32);
  419. }
  420. }
  421. /* begin */
  422. base->CTRL = PUF_CTRL_SETKEY_MASK;
  423. /* wait till command is accepted */
  424. while (0 == (base->STAT & (PUF_STAT_BUSY_MASK | PUF_STAT_ERROR_MASK)))
  425. {
  426. }
  427. /* while busy write UK and read KC */
  428. while (0 != (base->STAT & PUF_STAT_BUSY_MASK))
  429. {
  430. if (0 != (PUF_STAT_KEYINREQ_MASK & base->STAT))
  431. {
  432. if (userKeySize >= sizeof(uint32_t))
  433. {
  434. temp32 = *userKeyAligned;
  435. userKeyAligned++;
  436. userKeySize -= sizeof(uint32_t);
  437. }
  438. base->KEYINPUT = temp32;
  439. }
  440. if (0 != (PUF_STAT_CODEOUTAVAIL_MASK & base->STAT))
  441. {
  442. temp32 = base->CODEOUTPUT;
  443. if (keyCodeSize >= sizeof(uint32_t))
  444. {
  445. *keyCodeAligned = temp32;
  446. keyCodeAligned++;
  447. keyCodeSize -= sizeof(uint32_t);
  448. }
  449. }
  450. }
  451. /* get status */
  452. if (0 != (base->STAT & PUF_STAT_SUCCESS_MASK))
  453. {
  454. status = kStatus_Success;
  455. }
  456. return status;
  457. }
  458. static status_t puf_getHwKey(PUF_Type *base, const uint8_t *keyCode, size_t keyCodeSize)
  459. {
  460. status_t status = kStatus_Fail;
  461. uint32_t *keyCodeAligned = NULL;
  462. register uint32_t temp32 = 0;
  463. keyCodeAligned = (uint32_t *)(uintptr_t)keyCode;
  464. /* begin */
  465. base->CTRL = PUF_CTRL_GETKEY_MASK;
  466. /* wait till command is accepted */
  467. while (0 == (base->STAT & (PUF_STAT_BUSY_MASK | PUF_STAT_ERROR_MASK)))
  468. {
  469. }
  470. /* while busy send KC, key is reconstructed to HW bus */
  471. while (0 != (base->STAT & PUF_STAT_BUSY_MASK))
  472. {
  473. if (0 != (PUF_STAT_CODEINREQ_MASK & base->STAT))
  474. {
  475. if (keyCodeSize >= sizeof(uint32_t))
  476. {
  477. temp32 = *keyCodeAligned;
  478. keyCodeAligned++;
  479. keyCodeSize -= sizeof(uint32_t);
  480. }
  481. base->CODEINPUT = temp32;
  482. }
  483. }
  484. /* get status */
  485. if (0 != (base->STAT & PUF_STAT_SUCCESS_MASK))
  486. {
  487. status = kStatus_Success;
  488. }
  489. return status;
  490. }
  491. /*!
  492. * brief Reconstruct hw bus key from a key code
  493. *
  494. * The digital fingerprint generated during the Start operation and the KC
  495. * generated during a Set Key operation (Set intrinsic key or Set user key) are used to retrieve a stored key. This
  496. * operation needs to be done every time a key is needed.
  497. * This function accepts only Key Codes created for PUF index register kPUF_KeyIndex_00.
  498. * Such a key is output directly to a dedicated hardware bus. The reconstructed key is not exposed to system memory.
  499. *
  500. * param base PUF peripheral base address
  501. * param keyCode Word aligned address of the input key code.
  502. * param keyCodeSize Size of the keyCode buffer in bytes. Shall be PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(keySize).
  503. * param keySlot key slot to output on hw bus. Parameter is ignored on devices with less than two key slots.
  504. * param keyMask key masking value. Shall be random for each POR/reset. Value does not have to be cryptographicaly
  505. * secure.
  506. * return Status of get key operation.
  507. */
  508. status_t PUF_GetHwKey(
  509. PUF_Type *base, const uint8_t *keyCode, size_t keyCodeSize, puf_key_slot_t keySlot, uint32_t keyMask)
  510. {
  511. status_t status = kStatus_Fail;
  512. uint32_t keyIndex;
  513. /* check if GET KEY is allowed */
  514. if (0x0u == (base->ALLOW & PUF_ALLOW_ALLOWGETKEY_MASK))
  515. {
  516. return kStatus_Fail;
  517. }
  518. /* only work with aligned keyCode */
  519. if (0x3u & (uintptr_t)keyCode)
  520. {
  521. return kStatus_Fail;
  522. }
  523. /* check that keyCodeSize is at least PUF_MIN_KEY_CODE_SIZE */
  524. if (keyCodeSize < PUF_MIN_KEY_CODE_SIZE)
  525. {
  526. return kStatus_InvalidArgument;
  527. }
  528. keyIndex = 0x0Fu & keyCode[1];
  529. /* check the Key Code header byte 1. index must be zero for the hw key. */
  530. if (kPUF_KeyIndex_00 != (puf_key_index_register_t)keyIndex)
  531. {
  532. return kStatus_Fail;
  533. }
  534. #if defined(FSL_FEATURE_PUF_HAS_KEYSLOTS) && (FSL_FEATURE_PUF_HAS_KEYSLOTS > 0)
  535. //volatile uint32_t *keyMask_reg = NULL;
  536. #define PUF_KEYSLOT_EN 2
  537. uint32_t regVal = (PUF_KEYSLOT_EN << (2 * keySlot));
  538. if (keySlot >= FSL_FEATURE_PUF_HAS_KEYSLOTS)
  539. {
  540. return kStatus_InvalidArgument;
  541. }
  542. #endif /* FSL_FEATURE_PUF_HAS_KEYSLOTS */
  543. #if defined(FSL_FEATURE_PUF_HAS_KEYSLOTS) && (FSL_FEATURE_PUF_HAS_KEYSLOTS > 0)
  544. base->KEYRESET = regVal;
  545. base->KEYENABLE = regVal;
  546. base->KEYMASK[keySlot] = keyMask;
  547. #endif /* FSL_FEATURE_PUF_HAS_KEYSLOTS */
  548. status = puf_getHwKey(base, keyCode, keyCodeSize);
  549. #if defined(FSL_FEATURE_PUF_HAS_SHIFT_STATUS) && (FSL_FEATURE_PUF_HAS_SHIFT_STATUS > 0)
  550. size_t keyWords = 0;
  551. if (status == kStatus_Success)
  552. {
  553. /* if the corresponding shift count does not match, return fail anyway */
  554. keyWords = ((((size_t)keyCode[3]) * 2) - 1u) << (keySlot << 2);
  555. if (keyWords != ((0x0Fu << (keySlot << 2)) & base->SHIFT_STATUS))
  556. {
  557. status = kStatus_Fail;
  558. }
  559. }
  560. #endif /* FSL_FEATURE_PUF_HAS_SHIFT_STATUS */
  561. return status;
  562. }
  563. /*!
  564. * brief Checks if Get Key operation is allowed.
  565. *
  566. * This function returns true if get key operation is allowed.
  567. *
  568. * param base PUF peripheral base address
  569. * return true if get key operation is allowed
  570. */
  571. bool PUF_IsGetKeyAllowed(PUF_Type *base)
  572. {
  573. /* check if GET KEY is allowed */
  574. if (0x0u == (base->ALLOW & PUF_ALLOW_ALLOWGETKEY_MASK))
  575. {
  576. return false;
  577. }
  578. return true;
  579. }
  580. /*!
  581. * brief Reconstruct key from a key code
  582. *
  583. * The digital fingerprint generated during the Start operation and the KC
  584. * generated during a Set Key operation (Set intrinsic key or Set user key) are used to retrieve a stored key. This
  585. * operation needs to be done every time a key is needed.
  586. * This function accepts only Key Codes created for PUF index registers kPUF_KeyIndex_01 to kPUF_KeyIndex_15.
  587. *
  588. * param base PUF peripheral base address
  589. * param keyCode Word aligned address of the input key code.
  590. * param keyCodeSize Size of the keyCode buffer in bytes. Shall be PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(keySize).
  591. * param[out] key Word aligned address of output key.
  592. * param keySize Size of the output key in bytes.
  593. * return Status of get key operation.
  594. */
  595. status_t PUF_GetKey(PUF_Type *base, const uint8_t *keyCode, size_t keyCodeSize, uint8_t *key, size_t keySize)
  596. {
  597. status_t status = kStatus_Fail;
  598. uint32_t *keyCodeAligned = NULL;
  599. uint32_t *keyAligned = NULL;
  600. uint32_t keyIndex;
  601. register uint32_t temp32 = 0;
  602. /* check if GET KEY is allowed */
  603. if (0x0u == (base->ALLOW & PUF_ALLOW_ALLOWGETKEY_MASK))
  604. {
  605. return kStatus_Fail;
  606. }
  607. /* only work with aligned keyCode */
  608. if (0x3u & (uintptr_t)keyCode)
  609. {
  610. return kStatus_Fail;
  611. }
  612. /* only work with aligned key */
  613. if (0x3u & (uintptr_t)key)
  614. {
  615. return kStatus_Fail;
  616. }
  617. /* check that keyCodeSize is correct for given keySize */
  618. if (keyCodeSize < PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(keySize))
  619. {
  620. return kStatus_InvalidArgument;
  621. }
  622. keyIndex = 0x0Fu & keyCode[1];
  623. /* check the Key Code header byte 1. index must be non-zero for the register key. */
  624. if (kPUF_KeyIndex_00 == (puf_key_index_register_t)keyIndex)
  625. {
  626. return kStatus_Fail;
  627. }
  628. keyCodeAligned = (uint32_t *)(uintptr_t)keyCode;
  629. keyAligned = (uint32_t *)(uintptr_t)key;
  630. /* begin */
  631. base->CTRL = PUF_CTRL_GETKEY_MASK;
  632. /* wait till command is accepted */
  633. while (0 == (base->STAT & (PUF_STAT_BUSY_MASK | PUF_STAT_ERROR_MASK)))
  634. {
  635. }
  636. /* while busy send KC, read key */
  637. while (0 != (base->STAT & PUF_STAT_BUSY_MASK))
  638. {
  639. if (0 != (PUF_STAT_CODEINREQ_MASK & base->STAT))
  640. {
  641. temp32 = 0;
  642. if (keyCodeSize >= sizeof(uint32_t))
  643. {
  644. temp32 = *keyCodeAligned;
  645. keyCodeAligned++;
  646. keyCodeSize -= sizeof(uint32_t);
  647. }
  648. base->CODEINPUT = temp32;
  649. }
  650. if (0 != (PUF_STAT_KEYOUTAVAIL_MASK & base->STAT))
  651. {
  652. keyIndex = base->KEYOUTINDEX;
  653. temp32 = base->KEYOUTPUT;
  654. if (keySize >= sizeof(uint32_t))
  655. {
  656. *keyAligned = temp32;
  657. keyAligned++;
  658. keySize -= sizeof(uint32_t);
  659. }
  660. }
  661. }
  662. /* get status */
  663. if ((keyIndex) && (0 != (base->STAT & PUF_STAT_SUCCESS_MASK)))
  664. {
  665. status = kStatus_Success;
  666. }
  667. return status;
  668. }
  669. /*!
  670. * brief Zeroize PUF
  671. *
  672. * This function clears all PUF internal logic and puts the PUF to error state.
  673. *
  674. * param base PUF peripheral base address
  675. * return Status of the zeroize operation.
  676. */
  677. status_t PUF_Zeroize(PUF_Type *base)
  678. {
  679. status_t status = kStatus_Fail;
  680. /* zeroize command is always allowed */
  681. base->CTRL = PUF_CTRL_ZEROIZE_MASK;
  682. /* check that command is accepted */
  683. if ((0 != (base->STAT & PUF_STAT_ERROR_MASK)) && (0 == base->ALLOW))
  684. {
  685. status = kStatus_Success;
  686. }
  687. return status;
  688. }