fsl_dcp.c 34 KB

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