fsl_dcp.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129
  1. /*
  2. * The Clear BSD License
  3. * Copyright 2017 NXP
  4. * All rights reserved.
  5. *
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include "fsl_dcp.h"
  35. /*******************************************************************************
  36. * Definitions
  37. ******************************************************************************/
  38. /* Component ID definition, used by tools. */
  39. #ifndef FSL_COMPONENT_ID
  40. #define FSL_COMPONENT_ID "platform.drivers.dcp"
  41. #endif
  42. /*! Compile time sizeof() check */
  43. #define BUILD_ASSURE(condition, msg) extern int msg[1 - 2 * (!(condition))] __attribute__((unused))
  44. #define dcp_memcpy memcpy
  45. /*! Internal states of the HASH creation process */
  46. typedef enum _dcp_hash_algo_state
  47. {
  48. kDCP_StateHashInit = 1u, /*!< Init state. */
  49. kDCP_StateHashUpdate, /*!< Update state. */
  50. } dcp_hash_algo_state_t;
  51. /*! multiple of 64-byte block represented as byte array of 32-bit words */
  52. typedef union _dcp_hash_block
  53. {
  54. uint32_t w[DCP_HASH_BLOCK_SIZE / 4]; /*!< array of 32-bit words */
  55. uint8_t b[DCP_HASH_BLOCK_SIZE]; /*!< byte array */
  56. } dcp_hash_block_t;
  57. /*! internal dcp_hash context structure */
  58. typedef struct _dcp_hash_ctx_internal
  59. {
  60. dcp_hash_block_t blk; /*!< memory buffer. only full blocks are written to DCP during hash updates */
  61. size_t blksz; /*!< number of valid bytes in memory buffer */
  62. dcp_hash_algo_t algo; /*!< selected algorithm from the set of supported algorithms */
  63. dcp_hash_algo_state_t state; /*!< finite machine state of the hash software process */
  64. uint32_t fullMessageSize; /*!< track message size */
  65. uint32_t ctrl0; /*!< HASH_INIT and HASH_TERM flags */
  66. uint32_t runningHash[9]; /*!< running hash. up to SHA-256 plus size, that is 36 bytes. */
  67. dcp_handle_t *handle;
  68. } dcp_hash_ctx_internal_t;
  69. /*!< SHA-1/SHA-2 digest length in bytes */
  70. enum _dcp_hash_digest_len
  71. {
  72. kDCP_OutLenSha1 = 20u,
  73. kDCP_OutLenSha256 = 32u,
  74. kDCP_OutLenCrc32 = 4u,
  75. };
  76. enum _dcp_work_packet_bit_definitions
  77. {
  78. kDCP_CONTROL0_DECR_SEMAPHOR = 1u << 1, /* DECR_SEMAPHOR */
  79. kDCP_CONTROL0_ENABLE_HASH = 1u << 6, /* ENABLE_HASH */
  80. kDCP_CONTROL0_HASH_INIT = 1u << 12, /* HASH_INIT */
  81. kDCP_CONTROL0_HASH_TERM = 1u << 13, /* HASH_TERM */
  82. kDCP_CONTROL1_HASH_SELECT_SHA256 = 2u << 16,
  83. kDCP_CONTROL1_HASH_SELECT_SHA1 = 0u << 16,
  84. kDCP_CONTROL1_HASH_SELECT_CRC32 = 1u << 16,
  85. };
  86. /*! 64-byte block represented as byte array of 16 32-bit words */
  87. typedef union _dcp_sha_block
  88. {
  89. uint32_t w[64 / 4]; /*!< array of 32-bit words */
  90. uint8_t b[64]; /*!< byte array */
  91. } dcp_sha_block_t;
  92. #if defined(DCP_HASH_CAVP_COMPATIBLE)
  93. /* result of sha1 hash for message with zero size */
  94. static uint8_t s_nullSha1[] = {0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
  95. 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09};
  96. /* result of sha256 hash for message with zero size */
  97. static uint8_t s_nullSha256[] = {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4,
  98. 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b,
  99. 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55};
  100. #endif /* DCP_HASH_CAVP_COMPATIBLE */
  101. /*******************************************************************************
  102. * Variables
  103. ******************************************************************************/
  104. static dcp_context_t s_dcpContextSwitchingBuffer;
  105. /*******************************************************************************
  106. * Code
  107. ******************************************************************************/
  108. static void dcp_reverse_and_copy(uint8_t *src, uint8_t *dest, size_t src_len)
  109. {
  110. for (int i = 0; i < src_len; i++)
  111. {
  112. dest[i] = src[src_len - 1 - i];
  113. }
  114. }
  115. static status_t dcp_get_channel_status(DCP_Type *base, dcp_channel_t channel)
  116. {
  117. uint32_t statReg = 0;
  118. uint32_t semaReg = 0;
  119. status_t status = kStatus_Fail;
  120. switch (channel)
  121. {
  122. case kDCP_Channel0:
  123. statReg = base->CH0STAT;
  124. semaReg = base->CH0SEMA;
  125. break;
  126. case kDCP_Channel1:
  127. statReg = base->CH1STAT;
  128. semaReg = base->CH1SEMA;
  129. break;
  130. case kDCP_Channel2:
  131. statReg = base->CH2STAT;
  132. semaReg = base->CH2SEMA;
  133. break;
  134. case kDCP_Channel3:
  135. statReg = base->CH3STAT;
  136. semaReg = base->CH3SEMA;
  137. break;
  138. default:
  139. break;
  140. }
  141. if (!((semaReg & DCP_CH0SEMA_VALUE_MASK) || (statReg & DCP_CH0STAT_ERROR_CODE_MASK)))
  142. {
  143. status = kStatus_Success;
  144. }
  145. return status;
  146. }
  147. static void dcp_clear_status(DCP_Type *base)
  148. {
  149. volatile uint32_t *dcpStatClrPtr = &base->STAT + 2u;
  150. *dcpStatClrPtr = 0xFFu;
  151. }
  152. static void dcp_clear_channel_status(DCP_Type *base, uint32_t mask)
  153. {
  154. volatile uint32_t *chStatClrPtr;
  155. if (mask & kDCP_Channel0)
  156. {
  157. chStatClrPtr = &base->CH0STAT + 2u;
  158. *chStatClrPtr = 0xFFu;
  159. }
  160. if (mask & kDCP_Channel1)
  161. {
  162. chStatClrPtr = &base->CH1STAT + 2u;
  163. *chStatClrPtr = 0xFFu;
  164. }
  165. if (mask & kDCP_Channel2)
  166. {
  167. chStatClrPtr = &base->CH2STAT + 2u;
  168. *chStatClrPtr = 0xFFu;
  169. }
  170. if (mask & kDCP_Channel3)
  171. {
  172. chStatClrPtr = &base->CH3STAT + 2u;
  173. *chStatClrPtr = 0xFFu;
  174. }
  175. }
  176. static status_t dcp_aes_set_sram_based_key(DCP_Type *base, dcp_handle_t *handle, const uint8_t *key)
  177. {
  178. base->KEY = DCP_KEY_INDEX(handle->keySlot) | DCP_KEY_SUBWORD(0);
  179. /* move the key by 32-bit words */
  180. int i = 0;
  181. size_t keySize = 16u;
  182. while (keySize)
  183. {
  184. keySize -= sizeof(uint32_t);
  185. base->KEYDATA = ((uint32_t *)(uintptr_t)key)[i];
  186. i++;
  187. }
  188. return kStatus_Success;
  189. }
  190. static status_t dcp_schedule_work(DCP_Type *base, dcp_handle_t *handle, dcp_work_packet_t *dcpPacket)
  191. {
  192. status_t status;
  193. /* check if our channel is active */
  194. if ((base->STAT & (uint32_t)handle->channel) != handle->channel)
  195. {
  196. /* disable global interrupt */
  197. uint32_t currPriMask = DisableGlobalIRQ();
  198. /* re-check if our channel is still available */
  199. if ((base->STAT & (uint32_t)handle->channel) == 0)
  200. {
  201. volatile uint32_t *cmdptr = NULL;
  202. volatile uint32_t *chsema = NULL;
  203. switch (handle->channel)
  204. {
  205. case kDCP_Channel0:
  206. cmdptr = &base->CH0CMDPTR;
  207. chsema = &base->CH0SEMA;
  208. break;
  209. case kDCP_Channel1:
  210. cmdptr = &base->CH1CMDPTR;
  211. chsema = &base->CH1SEMA;
  212. break;
  213. case kDCP_Channel2:
  214. cmdptr = &base->CH2CMDPTR;
  215. chsema = &base->CH2SEMA;
  216. break;
  217. case kDCP_Channel3:
  218. cmdptr = &base->CH3CMDPTR;
  219. chsema = &base->CH3SEMA;
  220. break;
  221. default:
  222. break;
  223. }
  224. if (cmdptr && chsema)
  225. {
  226. /* set out packet to DCP CMDPTR */
  227. *cmdptr = (uint32_t)dcpPacket;
  228. /* set the channel semaphore */
  229. *chsema = 1u;
  230. }
  231. status = kStatus_Success;
  232. }
  233. else
  234. {
  235. status = kStatus_DCP_Again;
  236. }
  237. /* global interrupt enable */
  238. EnableGlobalIRQ(currPriMask);
  239. }
  240. else
  241. {
  242. return kStatus_DCP_Again;
  243. }
  244. return status;
  245. }
  246. status_t DCP_AES_SetKey(DCP_Type *base, dcp_handle_t *handle, const uint8_t *key, size_t keySize)
  247. {
  248. status_t status = kStatus_Fail;
  249. if ((kDCP_OtpKey == handle->keySlot) || (kDCP_OtpUniqueKey == handle->keySlot))
  250. {
  251. /* for AES OTP and unique key, check and return read from fuses status */
  252. if ((base->STAT & DCP_STAT_OTP_KEY_READY_MASK) == DCP_STAT_OTP_KEY_READY_MASK)
  253. {
  254. status = kStatus_Success;
  255. }
  256. }
  257. else
  258. {
  259. /* only work with aligned key[] */
  260. if (0x3U & (uintptr_t)key)
  261. {
  262. return kStatus_InvalidArgument;
  263. }
  264. /* keySize must be 16. */
  265. if (keySize != 16U)
  266. {
  267. return kStatus_InvalidArgument;
  268. }
  269. /* move the key by 32-bit words */
  270. int i = 0;
  271. while (keySize)
  272. {
  273. keySize -= sizeof(uint32_t);
  274. handle->keyWord[i] = ((uint32_t *)(uintptr_t)key)[i];
  275. i++;
  276. }
  277. if (kDCP_PayloadKey != handle->keySlot)
  278. {
  279. /* move the key by 32-bit words to DCP SRAM-based key storage */
  280. status = dcp_aes_set_sram_based_key(base, handle, key);
  281. }
  282. else
  283. {
  284. /* for PAYLOAD_KEY, just return Ok status now */
  285. status = kStatus_Success;
  286. }
  287. }
  288. return status;
  289. }
  290. status_t DCP_AES_EncryptEcb(
  291. DCP_Type *base, dcp_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size)
  292. {
  293. status_t completionStatus = kStatus_Fail;
  294. dcp_work_packet_t dcpWork = {0};
  295. do
  296. {
  297. completionStatus = DCP_AES_EncryptEcbNonBlocking(base, handle, &dcpWork, plaintext, ciphertext, size);
  298. } while (completionStatus == kStatus_DCP_Again);
  299. if (completionStatus != kStatus_Success)
  300. {
  301. return completionStatus;
  302. }
  303. return DCP_WaitForChannelComplete(base, handle);
  304. }
  305. status_t DCP_AES_EncryptEcbNonBlocking(DCP_Type *base,
  306. dcp_handle_t *handle,
  307. dcp_work_packet_t *dcpPacket,
  308. const uint8_t *plaintext,
  309. uint8_t *ciphertext,
  310. size_t size)
  311. {
  312. /* Size must be 16-byte multiple */
  313. if ((size < 16u) || (size % 16u))
  314. {
  315. return kStatus_InvalidArgument;
  316. }
  317. dcpPacket->control0 = 0x122u; /* CIPHER_ENCRYPT | ENABLE_CIPHER | DECR_SEMAPHORE */
  318. dcpPacket->sourceBufferAddress = (uint32_t)plaintext;
  319. dcpPacket->destinationBufferAddress = (uint32_t)ciphertext;
  320. dcpPacket->bufferSize = (uint32_t)size;
  321. if (handle->keySlot == kDCP_OtpKey)
  322. {
  323. dcpPacket->control0 |= (1u << 10); /* OTP_KEY */
  324. dcpPacket->control1 = (0xFFu << 8); /* KEY_SELECT = OTP_KEY */
  325. }
  326. else if (handle->keySlot == kDCP_OtpUniqueKey)
  327. {
  328. dcpPacket->control0 |= (1u << 10); /* OTP_KEY */
  329. dcpPacket->control1 = (0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */
  330. }
  331. else if (handle->keySlot == kDCP_PayloadKey)
  332. {
  333. /* ECB does not have IV, so we can point payload directly to keyWord[] stored in handle. */
  334. dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0];
  335. dcpPacket->control0 |= (1u << 11); /* PAYLOAD_KEY */
  336. }
  337. else
  338. {
  339. dcpPacket->control1 = (handle->keySlot << 8); /* KEY_SELECT = keySlot */
  340. }
  341. return dcp_schedule_work(base, handle, dcpPacket);
  342. }
  343. status_t DCP_AES_DecryptEcb(
  344. DCP_Type *base, dcp_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size)
  345. {
  346. status_t completionStatus = kStatus_Fail;
  347. dcp_work_packet_t dcpWork = {0};
  348. do
  349. {
  350. completionStatus = DCP_AES_DecryptEcbNonBlocking(base, handle, &dcpWork, ciphertext, plaintext, size);
  351. } while (completionStatus == kStatus_DCP_Again);
  352. if (completionStatus != kStatus_Success)
  353. {
  354. return completionStatus;
  355. }
  356. return DCP_WaitForChannelComplete(base, handle);
  357. }
  358. status_t DCP_AES_DecryptEcbNonBlocking(DCP_Type *base,
  359. dcp_handle_t *handle,
  360. dcp_work_packet_t *dcpPacket,
  361. const uint8_t *ciphertext,
  362. uint8_t *plaintext,
  363. size_t size)
  364. {
  365. /* Size must be 16-byte multiple */
  366. if ((size < 16u) || (size % 16u))
  367. {
  368. return kStatus_InvalidArgument;
  369. }
  370. dcpPacket->control0 = 0x22u; /* ENABLE_CIPHER | DECR_SEMAPHORE */
  371. dcpPacket->sourceBufferAddress = (uint32_t)ciphertext;
  372. dcpPacket->destinationBufferAddress = (uint32_t)plaintext;
  373. dcpPacket->bufferSize = (uint32_t)size;
  374. if (handle->keySlot == kDCP_OtpKey)
  375. {
  376. dcpPacket->control0 |= (1u << 10); /* OTP_KEY */
  377. dcpPacket->control1 = (0xFFu << 8); /* KEY_SELECT = OTP_KEY */
  378. }
  379. else if (handle->keySlot == kDCP_OtpUniqueKey)
  380. {
  381. dcpPacket->control0 |= (1u << 10); /* OTP_KEY */
  382. dcpPacket->control1 = (0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */
  383. }
  384. else if (handle->keySlot == kDCP_PayloadKey)
  385. {
  386. /* ECB does not have IV, so we can point payload directly to keyWord[] stored in handle. */
  387. dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0];
  388. dcpPacket->control0 |= (1u << 11); /* PAYLOAD_KEY */
  389. }
  390. else
  391. {
  392. dcpPacket->control1 = (handle->keySlot << 8); /* KEY_SELECT = keySlot */
  393. }
  394. return dcp_schedule_work(base, handle, dcpPacket);
  395. }
  396. status_t DCP_AES_EncryptCbc(DCP_Type *base,
  397. dcp_handle_t *handle,
  398. const uint8_t *plaintext,
  399. uint8_t *ciphertext,
  400. size_t size,
  401. const uint8_t iv[16])
  402. {
  403. status_t completionStatus = kStatus_Fail;
  404. dcp_work_packet_t dcpWork = {0};
  405. do
  406. {
  407. completionStatus = DCP_AES_EncryptCbcNonBlocking(base, handle, &dcpWork, plaintext, ciphertext, size, iv);
  408. } while (completionStatus == kStatus_DCP_Again);
  409. if (completionStatus != kStatus_Success)
  410. {
  411. return completionStatus;
  412. }
  413. return DCP_WaitForChannelComplete(base, handle);
  414. }
  415. status_t DCP_AES_EncryptCbcNonBlocking(DCP_Type *base,
  416. dcp_handle_t *handle,
  417. dcp_work_packet_t *dcpPacket,
  418. const uint8_t *plaintext,
  419. uint8_t *ciphertext,
  420. size_t size,
  421. const uint8_t *iv)
  422. {
  423. /* Size must be 16-byte multiple */
  424. if ((size < 16u) || (size % 16u))
  425. {
  426. return kStatus_InvalidArgument;
  427. }
  428. dcpPacket->control0 = 0x322u; /* CIPHER_INIT | CIPHER_ENCRYPT | ENABLE_CIPHER | DECR_SEMAPHORE */
  429. dcpPacket->control1 = 0x10u; /* CBC */
  430. dcpPacket->sourceBufferAddress = (uint32_t)plaintext;
  431. dcpPacket->destinationBufferAddress = (uint32_t)ciphertext;
  432. dcpPacket->bufferSize = (uint32_t)size;
  433. if (handle->keySlot == kDCP_OtpKey)
  434. {
  435. dcpPacket->payloadPointer = (uint32_t)iv;
  436. dcpPacket->control0 |= (1u << 10); /* OTP_KEY */
  437. dcpPacket->control1 |= (0xFFu << 8); /* KEY_SELECT = OTP_KEY */
  438. }
  439. else if (handle->keySlot == kDCP_OtpUniqueKey)
  440. {
  441. dcpPacket->payloadPointer = (uint32_t)iv;
  442. dcpPacket->control0 |= (1u << 10); /* OTP_KEY */
  443. dcpPacket->control1 |= (0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */
  444. }
  445. else if (handle->keySlot == kDCP_PayloadKey)
  446. {
  447. /* In this case payload must contain key & iv in one array. */
  448. /* Copy iv into handle right behind the keyWord[] so we can point payload to keyWord[]. */
  449. dcp_memcpy(handle->iv, iv, 16);
  450. dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0];
  451. dcpPacket->control0 |= (1u << 11); /* PAYLOAD_KEY */
  452. }
  453. else
  454. {
  455. dcpPacket->payloadPointer = (uint32_t)iv;
  456. dcpPacket->control1 |= ((uint32_t)handle->keySlot << 8); /* KEY_SELECT = keySlot */
  457. }
  458. return dcp_schedule_work(base, handle, dcpPacket);
  459. }
  460. status_t DCP_AES_DecryptCbc(DCP_Type *base,
  461. dcp_handle_t *handle,
  462. const uint8_t *ciphertext,
  463. uint8_t *plaintext,
  464. size_t size,
  465. const uint8_t iv[16])
  466. {
  467. status_t completionStatus = kStatus_Fail;
  468. dcp_work_packet_t dcpWork = {0};
  469. do
  470. {
  471. completionStatus = DCP_AES_DecryptCbcNonBlocking(base, handle, &dcpWork, ciphertext, plaintext, size, iv);
  472. } while (completionStatus == kStatus_DCP_Again);
  473. if (completionStatus != kStatus_Success)
  474. {
  475. return completionStatus;
  476. }
  477. return DCP_WaitForChannelComplete(base, handle);
  478. }
  479. status_t DCP_AES_DecryptCbcNonBlocking(DCP_Type *base,
  480. dcp_handle_t *handle,
  481. dcp_work_packet_t *dcpPacket,
  482. const uint8_t *ciphertext,
  483. uint8_t *plaintext,
  484. size_t size,
  485. const uint8_t *iv)
  486. {
  487. /* Size must be 16-byte multiple */
  488. if ((size < 16u) || (size % 16u))
  489. {
  490. return kStatus_InvalidArgument;
  491. }
  492. dcpPacket->control0 = 0x222u; /* CIPHER_INIT | ENABLE_CIPHER | DECR_SEMAPHORE */
  493. dcpPacket->control1 = 0x10u; /* CBC */
  494. dcpPacket->sourceBufferAddress = (uint32_t)ciphertext;
  495. dcpPacket->destinationBufferAddress = (uint32_t)plaintext;
  496. dcpPacket->bufferSize = (uint32_t)size;
  497. if (handle->keySlot == kDCP_OtpKey)
  498. {
  499. dcpPacket->payloadPointer = (uint32_t)iv;
  500. dcpPacket->control0 |= (1u << 10); /* OTP_KEY */
  501. dcpPacket->control1 |= (0xFFu << 8); /* OTP_KEY */
  502. }
  503. else if (handle->keySlot == kDCP_OtpUniqueKey)
  504. {
  505. dcpPacket->payloadPointer = (uint32_t)iv;
  506. dcpPacket->control0 |= (1u << 10); /* OTP_KEY */
  507. dcpPacket->control1 |= (0xFEu << 8); /* UNIQUE_KEY */
  508. }
  509. else if (handle->keySlot == kDCP_PayloadKey)
  510. {
  511. /* in this case payload must contain KEY + IV together */
  512. /* copy iv into handle struct so we can point payload directly to keyWord[]. */
  513. dcp_memcpy(handle->iv, iv, 16);
  514. dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0];
  515. dcpPacket->control0 |= (1u << 11); /* PAYLOAD_KEY */
  516. }
  517. else
  518. {
  519. dcpPacket->payloadPointer = (uint32_t)iv;
  520. dcpPacket->control1 |= ((uint32_t)handle->keySlot << 8); /* KEY_SELECT */
  521. }
  522. return dcp_schedule_work(base, handle, dcpPacket);
  523. }
  524. void DCP_GetDefaultConfig(dcp_config_t *config)
  525. {
  526. /* ENABLE_CONTEXT_CACHING is disabled by default as the DCP Hash driver uses
  527. * dcp_hash_save_running_hash() and dcp_hash_restore_running_hash() to support
  528. * Hash context switch (different messages interleaved) on the same channel.
  529. */
  530. dcp_config_t userConfig = {
  531. true, false, true, kDCP_chEnableAll, kDCP_chIntDisable,
  532. };
  533. *config = userConfig;
  534. }
  535. void DCP_Init(DCP_Type *base, const dcp_config_t *config)
  536. {
  537. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  538. CLOCK_EnableClock(kCLOCK_Dcp);
  539. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  540. base->CTRL = 0xF0800000u; /* reset value */
  541. base->CTRL = 0x30800000u; /* default value */
  542. dcp_clear_status(base);
  543. dcp_clear_channel_status(base, kDCP_Channel0 | kDCP_Channel1 | kDCP_Channel2 | kDCP_Channel3);
  544. base->CTRL = DCP_CTRL_GATHER_RESIDUAL_WRITES(config->gatherResidualWrites) |
  545. DCP_CTRL_ENABLE_CONTEXT_CACHING(config->enableContextCaching) |
  546. DCP_CTRL_ENABLE_CONTEXT_SWITCHING(config->enableContextSwitching) |
  547. DCP_CTRL_CHANNEL_INTERRUPT_ENABLE(config->enableChannelInterrupt);
  548. /* enable DCP channels */
  549. base->CHANNELCTRL = DCP_CHANNELCTRL_ENABLE_CHANNEL(config->enableChannel);
  550. /* use context switching buffer */
  551. base->CONTEXT = (uint32_t)&s_dcpContextSwitchingBuffer;
  552. }
  553. void DCP_Deinit(DCP_Type *base)
  554. {
  555. base->CTRL = 0xF0800000u; /* reset value */
  556. memset(&s_dcpContextSwitchingBuffer, 0, sizeof(s_dcpContextSwitchingBuffer));
  557. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  558. CLOCK_DisableClock(kCLOCK_Dcp);
  559. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  560. }
  561. status_t DCP_WaitForChannelComplete(DCP_Type *base, dcp_handle_t *handle)
  562. {
  563. /* wait if our channel is still active */
  564. while ((base->STAT & (uint32_t)handle->channel) == handle->channel)
  565. {
  566. }
  567. if (dcp_get_channel_status(base, handle->channel) != kStatus_Success)
  568. {
  569. dcp_clear_status(base);
  570. dcp_clear_channel_status(base, handle->channel);
  571. return kStatus_Fail;
  572. }
  573. return kStatus_Success;
  574. }
  575. /*!
  576. * @brief Check validity of algoritm.
  577. *
  578. * This function checks the validity of input argument.
  579. *
  580. * @param algo Tested algorithm value.
  581. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
  582. */
  583. static status_t dcp_hash_check_input_alg(dcp_hash_algo_t algo)
  584. {
  585. if ((algo != kDCP_Sha256) && (algo != kDCP_Sha1) && (algo != kDCP_Crc32))
  586. {
  587. return kStatus_InvalidArgument;
  588. }
  589. return kStatus_Success;
  590. }
  591. /*!
  592. * @brief Check validity of input arguments.
  593. *
  594. * This function checks the validity of input arguments.
  595. *
  596. * @param base DCP peripheral base address.
  597. * @param ctx Memory buffer given by user application where the DCP_HASH_Init/DCP_HASH_Update/DCP_HASH_Finish store
  598. * context.
  599. * @param algo Tested algorithm value.
  600. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
  601. */
  602. static status_t dcp_hash_check_input_args(DCP_Type *base, dcp_hash_ctx_t *ctx, dcp_hash_algo_t algo)
  603. {
  604. /* Check validity of input algorithm */
  605. if (kStatus_Success != dcp_hash_check_input_alg(algo))
  606. {
  607. return kStatus_InvalidArgument;
  608. }
  609. if ((NULL == ctx) || (NULL == base))
  610. {
  611. return kStatus_InvalidArgument;
  612. }
  613. return kStatus_Success;
  614. }
  615. /*!
  616. * @brief Check validity of internal software context.
  617. *
  618. * This function checks if the internal context structure looks correct.
  619. *
  620. * @param ctxInternal Internal context.
  621. * @param message Input message address.
  622. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
  623. */
  624. static status_t dcp_hash_check_context(dcp_hash_ctx_internal_t *ctxInternal, const uint8_t *message)
  625. {
  626. if ((NULL == message) || (NULL == ctxInternal) || (kStatus_Success != dcp_hash_check_input_alg(ctxInternal->algo)))
  627. {
  628. return kStatus_InvalidArgument;
  629. }
  630. return kStatus_Success;
  631. }
  632. /*!
  633. * @brief Initialize the SHA engine for new hash.
  634. *
  635. * This function sets kDCP_CONTROL0_HASH_INIT for control0 in work packet to start a new hash.
  636. *
  637. * @param base SHA peripheral base address.
  638. * @param ctxInternal Internal context.
  639. */
  640. static status_t dcp_hash_engine_init(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal)
  641. {
  642. status_t status;
  643. status = kStatus_InvalidArgument;
  644. if ((kDCP_Sha256 == ctxInternal->algo) || (kDCP_Sha1 == ctxInternal->algo) || (kDCP_Crc32 == ctxInternal->algo))
  645. {
  646. ctxInternal->ctrl0 = kDCP_CONTROL0_HASH_INIT;
  647. status = kStatus_Success;
  648. }
  649. return status;
  650. }
  651. static status_t dcp_hash_update_non_blocking(
  652. DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal, dcp_work_packet_t *dcpPacket, const uint8_t *msg, size_t size)
  653. {
  654. dcpPacket->control0 = ctxInternal->ctrl0 | kDCP_CONTROL0_ENABLE_HASH | kDCP_CONTROL0_DECR_SEMAPHOR;
  655. if (ctxInternal->algo == kDCP_Sha256)
  656. {
  657. dcpPacket->control1 = kDCP_CONTROL1_HASH_SELECT_SHA256;
  658. }
  659. else if (ctxInternal->algo == kDCP_Sha1)
  660. {
  661. dcpPacket->control1 = kDCP_CONTROL1_HASH_SELECT_SHA1;
  662. }
  663. else if (ctxInternal->algo == kDCP_Crc32)
  664. {
  665. dcpPacket->control1 = kDCP_CONTROL1_HASH_SELECT_CRC32;
  666. }
  667. else
  668. {
  669. return kStatus_Fail;
  670. }
  671. dcpPacket->sourceBufferAddress = (uint32_t)msg;
  672. dcpPacket->destinationBufferAddress = 0;
  673. dcpPacket->bufferSize = size;
  674. dcpPacket->payloadPointer = (uint32_t)ctxInternal->runningHash;
  675. return dcp_schedule_work(base, ctxInternal->handle, dcpPacket);
  676. }
  677. static status_t dcp_hash_update(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal, const uint8_t *msg, size_t size)
  678. {
  679. status_t completionStatus = kStatus_Fail;
  680. dcp_work_packet_t dcpWork = {0};
  681. do
  682. {
  683. completionStatus = dcp_hash_update_non_blocking(base, ctxInternal, &dcpWork, msg, size);
  684. } while (completionStatus == kStatus_DCP_Again);
  685. completionStatus = DCP_WaitForChannelComplete(base, ctxInternal->handle);
  686. ctxInternal->ctrl0 = 0; /* clear kDCP_CONTROL0_HASH_INIT and kDCP_CONTROL0_HASH_TERM flags */
  687. return (completionStatus);
  688. }
  689. /*!
  690. * @brief Adds message to current hash.
  691. *
  692. * This function merges the message to fill the internal buffer, empties the internal buffer if
  693. * it becomes full, then process all remaining message data.
  694. *
  695. *
  696. * @param base DCP peripheral base address.
  697. * @param ctxInternal Internal context.
  698. * @param message Input message.
  699. * @param messageSize Size of input message in bytes.
  700. * @return kStatus_Success.
  701. */
  702. static status_t dcp_hash_process_message_data(DCP_Type *base,
  703. dcp_hash_ctx_internal_t *ctxInternal,
  704. const uint8_t *message,
  705. size_t messageSize)
  706. {
  707. status_t status = kStatus_Fail;
  708. /* if there is partially filled internal buffer, fill it to full block */
  709. if (ctxInternal->blksz > 0)
  710. {
  711. size_t toCopy = DCP_HASH_BLOCK_SIZE - ctxInternal->blksz;
  712. dcp_memcpy(&ctxInternal->blk.b[ctxInternal->blksz], message, toCopy);
  713. message += toCopy;
  714. messageSize -= toCopy;
  715. /* process full internal block */
  716. status = dcp_hash_update(base, ctxInternal, &ctxInternal->blk.b[0], DCP_HASH_BLOCK_SIZE);
  717. if (kStatus_Success != status)
  718. {
  719. return status;
  720. }
  721. }
  722. /* process all full blocks in message[] */
  723. uint32_t fullBlocksSize = ((messageSize >> 6) << 6); /* (X / 64) * 64 */
  724. if (fullBlocksSize > 0)
  725. {
  726. status = dcp_hash_update(base, ctxInternal, message, fullBlocksSize);
  727. if (kStatus_Success != status)
  728. {
  729. return status;
  730. }
  731. message += fullBlocksSize;
  732. messageSize -= fullBlocksSize;
  733. }
  734. /* copy last incomplete message bytes into internal block */
  735. dcp_memcpy(&ctxInternal->blk.b[0], message, messageSize);
  736. ctxInternal->blksz = messageSize;
  737. return status;
  738. }
  739. /*!
  740. * @brief Finalize the running hash to make digest.
  741. *
  742. * This function empties the internal buffer, adds padding bits, and generates final digest.
  743. *
  744. * @param base SHA peripheral base address.
  745. * @param ctxInternal Internal context.
  746. * @return kStatus_Success.
  747. */
  748. static status_t dcp_hash_finalize(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal)
  749. {
  750. status_t status;
  751. ctxInternal->ctrl0 |= kDCP_CONTROL0_HASH_TERM;
  752. status = dcp_hash_update(base, ctxInternal, &ctxInternal->blk.b[0], ctxInternal->blksz);
  753. return status;
  754. }
  755. static void dcp_hash_save_running_hash(dcp_hash_ctx_internal_t *ctxInternal)
  756. {
  757. uint32_t *srcAddr = NULL;
  758. switch (ctxInternal->handle->channel)
  759. {
  760. case kDCP_Channel0:
  761. srcAddr = &s_dcpContextSwitchingBuffer.x[43];
  762. break;
  763. case kDCP_Channel1:
  764. srcAddr = &s_dcpContextSwitchingBuffer.x[30];
  765. break;
  766. case kDCP_Channel2:
  767. srcAddr = &s_dcpContextSwitchingBuffer.x[17];
  768. break;
  769. case kDCP_Channel3:
  770. srcAddr = &s_dcpContextSwitchingBuffer.x[4];
  771. break;
  772. default:
  773. break;
  774. }
  775. if (srcAddr)
  776. {
  777. dcp_memcpy(ctxInternal->runningHash, srcAddr, sizeof(ctxInternal->runningHash));
  778. }
  779. }
  780. static void dcp_hash_restore_running_hash(dcp_hash_ctx_internal_t *ctxInternal)
  781. {
  782. uint32_t *destAddr = NULL;
  783. switch (ctxInternal->handle->channel)
  784. {
  785. case kDCP_Channel0:
  786. destAddr = &s_dcpContextSwitchingBuffer.x[43];
  787. break;
  788. case kDCP_Channel1:
  789. destAddr = &s_dcpContextSwitchingBuffer.x[30];
  790. break;
  791. case kDCP_Channel2:
  792. destAddr = &s_dcpContextSwitchingBuffer.x[17];
  793. break;
  794. case kDCP_Channel3:
  795. destAddr = &s_dcpContextSwitchingBuffer.x[4];
  796. break;
  797. default:
  798. break;
  799. }
  800. if (destAddr)
  801. {
  802. dcp_memcpy(destAddr, ctxInternal->runningHash, sizeof(ctxInternal->runningHash));
  803. }
  804. }
  805. status_t DCP_HASH_Init(DCP_Type *base, dcp_handle_t *handle, dcp_hash_ctx_t *ctx, dcp_hash_algo_t algo)
  806. {
  807. status_t status;
  808. dcp_hash_ctx_internal_t *ctxInternal;
  809. /* compile time check for the correct structure size */
  810. BUILD_ASSURE(sizeof(dcp_hash_ctx_t) >= sizeof(dcp_hash_ctx_internal_t), dcp_hash_ctx_t_size);
  811. uint32_t i;
  812. status = dcp_hash_check_input_args(base, ctx, algo);
  813. if (status != kStatus_Success)
  814. {
  815. return status;
  816. }
  817. /* set algorithm in context struct for later use */
  818. ctxInternal = (dcp_hash_ctx_internal_t *)ctx;
  819. ctxInternal->algo = algo;
  820. ctxInternal->blksz = 0u;
  821. for (i = 0; i < sizeof(ctxInternal->blk.w) / sizeof(ctxInternal->blk.w[0]); i++)
  822. {
  823. ctxInternal->blk.w[0] = 0u;
  824. }
  825. ctxInternal->state = kDCP_StateHashInit;
  826. ctxInternal->fullMessageSize = 0;
  827. ctxInternal->handle = handle;
  828. return status;
  829. }
  830. status_t DCP_HASH_Update(DCP_Type *base, dcp_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize)
  831. {
  832. bool isUpdateState;
  833. status_t status;
  834. dcp_hash_ctx_internal_t *ctxInternal;
  835. size_t blockSize;
  836. if (inputSize == 0)
  837. {
  838. return kStatus_Success;
  839. }
  840. ctxInternal = (dcp_hash_ctx_internal_t *)ctx;
  841. status = dcp_hash_check_context(ctxInternal, input);
  842. if (kStatus_Success != status)
  843. {
  844. return status;
  845. }
  846. ctxInternal->fullMessageSize += inputSize;
  847. blockSize = DCP_HASH_BLOCK_SIZE;
  848. /* if we are still less than DCP_HASH_BLOCK_SIZE bytes, keep only in context */
  849. if ((ctxInternal->blksz + inputSize) <= blockSize)
  850. {
  851. dcp_memcpy((&ctxInternal->blk.b[0]) + ctxInternal->blksz, input, inputSize);
  852. ctxInternal->blksz += inputSize;
  853. return status;
  854. }
  855. else
  856. {
  857. isUpdateState = ctxInternal->state == kDCP_StateHashUpdate;
  858. if (!isUpdateState)
  859. {
  860. /* start NEW hash */
  861. status = dcp_hash_engine_init(base, ctxInternal);
  862. if (status != kStatus_Success)
  863. {
  864. return status;
  865. }
  866. ctxInternal->state = kDCP_StateHashUpdate;
  867. }
  868. else
  869. {
  870. dcp_hash_restore_running_hash(ctxInternal);
  871. }
  872. }
  873. /* process input data */
  874. status = dcp_hash_process_message_data(base, ctxInternal, input, inputSize);
  875. dcp_hash_save_running_hash(ctxInternal);
  876. return status;
  877. }
  878. status_t DCP_HASH_Finish(DCP_Type *base, dcp_hash_ctx_t *ctx, uint8_t *output, size_t *outputSize)
  879. {
  880. size_t algOutSize = 0;
  881. status_t status;
  882. dcp_hash_ctx_internal_t *ctxInternal;
  883. ctxInternal = (dcp_hash_ctx_internal_t *)ctx;
  884. status = dcp_hash_check_context(ctxInternal, output);
  885. if (kStatus_Success != status)
  886. {
  887. return status;
  888. }
  889. if (ctxInternal->state == kDCP_StateHashInit)
  890. {
  891. status = dcp_hash_engine_init(base, ctxInternal);
  892. if (status != kStatus_Success)
  893. {
  894. return status;
  895. }
  896. }
  897. else
  898. {
  899. dcp_hash_restore_running_hash(ctxInternal);
  900. }
  901. size_t outSize = 0u;
  902. /* compute algorithm output length */
  903. switch (ctxInternal->algo)
  904. {
  905. case kDCP_Sha256:
  906. outSize = kDCP_OutLenSha256;
  907. break;
  908. case kDCP_Sha1:
  909. outSize = kDCP_OutLenSha1;
  910. break;
  911. case kDCP_Crc32:
  912. outSize = kDCP_OutLenCrc32;
  913. break;
  914. default:
  915. break;
  916. }
  917. algOutSize = outSize;
  918. #if defined(DCP_HASH_CAVP_COMPATIBLE)
  919. if (ctxInternal->fullMessageSize == 0)
  920. {
  921. switch (ctxInternal->algo)
  922. {
  923. case kDCP_Sha256:
  924. dcp_memcpy(&output[0], &s_nullSha256, 32);
  925. break;
  926. case kDCP_Sha1:
  927. dcp_memcpy(&output[0], &s_nullSha1, 20);
  928. break;
  929. default:
  930. break;
  931. }
  932. return kStatus_Success;
  933. }
  934. #endif /* DCP_HASH_CAVP_COMPATIBLE */
  935. /* flush message last incomplete block, if there is any, and add padding bits */
  936. status = dcp_hash_finalize(base, ctxInternal);
  937. if (outputSize)
  938. {
  939. if (algOutSize < *outputSize)
  940. {
  941. *outputSize = algOutSize;
  942. }
  943. else
  944. {
  945. algOutSize = *outputSize;
  946. }
  947. }
  948. /* Reverse and copy result to output[] */
  949. dcp_reverse_and_copy((uint8_t *)ctxInternal->runningHash, &output[0], algOutSize);
  950. memset(ctx, 0, sizeof(dcp_hash_ctx_t));
  951. return status;
  952. }
  953. status_t DCP_HASH(DCP_Type *base,
  954. dcp_handle_t *handle,
  955. dcp_hash_algo_t algo,
  956. const uint8_t *input,
  957. size_t inputSize,
  958. uint8_t *output,
  959. size_t *outputSize)
  960. {
  961. dcp_hash_ctx_t hashCtx;
  962. status_t status;
  963. status = DCP_HASH_Init(base, handle, &hashCtx, algo);
  964. if (status != kStatus_Success)
  965. {
  966. return status;
  967. }
  968. status = DCP_HASH_Update(base, &hashCtx, input, inputSize);
  969. if (status != kStatus_Success)
  970. {
  971. return status;
  972. }
  973. status = DCP_HASH_Finish(base, &hashCtx, output, outputSize);
  974. return status;
  975. }