fsl_dcp.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461
  1. /*
  2. * Copyright 2017-2019 NXP
  3. * All rights reserved.
  4. *
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_dcp.h"
  9. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
  10. #include "fsl_cache.h"
  11. #endif
  12. /*******************************************************************************
  13. * Definitions
  14. ******************************************************************************/
  15. /* Component ID definition, used by tools. */
  16. #ifndef FSL_COMPONENT_ID
  17. #define FSL_COMPONENT_ID "platform.drivers.dcp"
  18. #endif
  19. /*! Compile time sizeof() check */
  20. #define BUILD_ASSURE(condition, msg) extern int msg[1 - 2 * (!(condition))] __attribute__((unused))
  21. #define dcp_memcpy memcpy
  22. /*! Internal states of the HASH creation process */
  23. typedef enum _dcp_hash_algo_state
  24. {
  25. kDCP_StateHashInit = 1u, /*!< Init state. */
  26. kDCP_StateHashUpdate, /*!< Update state. */
  27. } dcp_hash_algo_state_t;
  28. /*! multiple of 64-byte block represented as byte array of 32-bit words */
  29. typedef union _dcp_hash_block
  30. {
  31. uint32_t w[DCP_HASH_BLOCK_SIZE / 4]; /*!< array of 32-bit words */
  32. uint8_t b[DCP_HASH_BLOCK_SIZE]; /*!< byte array */
  33. } dcp_hash_block_t;
  34. /*! internal dcp_hash context structure */
  35. typedef struct _dcp_hash_ctx_internal
  36. {
  37. dcp_hash_block_t blk; /*!< memory buffer. only full blocks are written to DCP during hash updates */
  38. size_t blksz; /*!< number of valid bytes in memory buffer */
  39. dcp_hash_algo_t algo; /*!< selected algorithm from the set of supported algorithms */
  40. dcp_hash_algo_state_t state; /*!< finite machine state of the hash software process */
  41. uint32_t fullMessageSize; /*!< track message size */
  42. uint32_t ctrl0; /*!< HASH_INIT and HASH_TERM flags */
  43. uint32_t runningHash[9]; /*!< running hash. up to SHA-256 plus size, that is 36 bytes. */
  44. dcp_handle_t *handle;
  45. } dcp_hash_ctx_internal_t;
  46. /*!< SHA-1/SHA-2 digest length in bytes */
  47. enum _dcp_hash_digest_len
  48. {
  49. kDCP_OutLenSha1 = 20u,
  50. kDCP_OutLenSha256 = 32u,
  51. kDCP_OutLenCrc32 = 4u,
  52. };
  53. enum _dcp_work_packet_bit_definitions
  54. {
  55. kDCP_CONTROL0_DECR_SEMAPHOR = 1u << 1, /* DECR_SEMAPHOR */
  56. kDCP_CONTROL0_ENABLE_HASH = 1u << 6, /* ENABLE_HASH */
  57. kDCP_CONTROL0_HASH_INIT = 1u << 12, /* HASH_INIT */
  58. kDCP_CONTROL0_HASH_TERM = 1u << 13, /* HASH_TERM */
  59. kDCP_CONTROL1_HASH_SELECT_SHA256 = 2u << 16,
  60. kDCP_CONTROL1_HASH_SELECT_SHA1 = 0u << 16,
  61. kDCP_CONTROL1_HASH_SELECT_CRC32 = 1u << 16,
  62. };
  63. /*! 64-byte block represented as byte array of 16 32-bit words */
  64. typedef union _dcp_sha_block
  65. {
  66. uint32_t w[64 / 4]; /*!< array of 32-bit words */
  67. uint8_t b[64]; /*!< byte array */
  68. } dcp_sha_block_t;
  69. #if defined(DCP_HASH_CAVP_COMPATIBLE)
  70. /* result of sha1 hash for message with zero size */
  71. static uint8_t s_nullSha1[] = {0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
  72. 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09};
  73. /* result of sha256 hash for message with zero size */
  74. static uint8_t s_nullSha256[] = {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4,
  75. 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b,
  76. 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55};
  77. #endif /* DCP_HASH_CAVP_COMPATIBLE */
  78. /*******************************************************************************
  79. * Variables
  80. ******************************************************************************/
  81. AT_NONCACHEABLE_SECTION_INIT(static dcp_context_t s_dcpContextSwitchingBuffer);
  82. /*******************************************************************************
  83. * Code
  84. ******************************************************************************/
  85. static void dcp_reverse_and_copy(uint8_t *src, uint8_t *dest, size_t src_len)
  86. {
  87. for (uint32_t i = 0; i < src_len; i++)
  88. {
  89. dest[i] = src[src_len - 1U - i];
  90. }
  91. }
  92. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  93. static inline uint32_t *DCP_FindCacheLine(uint8_t *dcpWorkExt)
  94. {
  95. while (0U != ((uint32_t)dcpWorkExt & ((uint32_t)FSL_FEATURE_L1DCACHE_LINESIZE_BYTE - 1U)))
  96. {
  97. dcpWorkExt++;
  98. }
  99. return (uint32_t *)(uint32_t)dcpWorkExt;
  100. }
  101. #endif
  102. static status_t dcp_get_channel_status(DCP_Type *base, dcp_channel_t channel)
  103. {
  104. uint32_t statReg = 0;
  105. uint32_t semaReg = 0;
  106. status_t status = kStatus_Fail;
  107. switch (channel)
  108. {
  109. case kDCP_Channel0:
  110. statReg = base->CH0STAT;
  111. semaReg = base->CH0SEMA;
  112. break;
  113. case kDCP_Channel1:
  114. statReg = base->CH1STAT;
  115. semaReg = base->CH1SEMA;
  116. break;
  117. case kDCP_Channel2:
  118. statReg = base->CH2STAT;
  119. semaReg = base->CH2SEMA;
  120. break;
  121. case kDCP_Channel3:
  122. statReg = base->CH3STAT;
  123. semaReg = base->CH3SEMA;
  124. break;
  125. default:
  126. /* All the cases have been listed above, the default clause should not be reached. */
  127. break;
  128. }
  129. if (!((0U != (semaReg & DCP_CH0SEMA_VALUE_MASK)) || (0U != (statReg & DCP_CH0STAT_ERROR_CODE_MASK))))
  130. {
  131. status = kStatus_Success;
  132. }
  133. return status;
  134. }
  135. static void dcp_clear_status(DCP_Type *base)
  136. {
  137. volatile uint32_t *dcpStatClrPtr = (volatile uint32_t *)&base->STAT + 2u;
  138. *dcpStatClrPtr = 0xFFu;
  139. while ((base->STAT & 0xffu) != 0U)
  140. {
  141. }
  142. }
  143. static void dcp_clear_channel_status(DCP_Type *base, uint32_t mask)
  144. {
  145. volatile uint32_t *chStatClrPtr;
  146. if (0U != (mask & (uint32_t)kDCP_Channel0))
  147. {
  148. chStatClrPtr = &base->CH0STAT_CLR;
  149. *chStatClrPtr = 0xFFu;
  150. }
  151. if (0U != (mask & (uint32_t)kDCP_Channel1))
  152. {
  153. chStatClrPtr = &base->CH1STAT_CLR;
  154. *chStatClrPtr = 0xFFu;
  155. }
  156. if (0U != (mask & (uint32_t)kDCP_Channel2))
  157. {
  158. chStatClrPtr = &base->CH2STAT_CLR;
  159. *chStatClrPtr = 0xFFu;
  160. }
  161. if (0U != (mask & (uint32_t)kDCP_Channel3))
  162. {
  163. chStatClrPtr = &base->CH3STAT_CLR;
  164. *chStatClrPtr = 0xFFu;
  165. }
  166. }
  167. static status_t dcp_aes_set_sram_based_key(DCP_Type *base, dcp_handle_t *handle, const uint8_t *key)
  168. {
  169. base->KEY = DCP_KEY_INDEX(handle->keySlot) | DCP_KEY_SUBWORD(0);
  170. /* move the key by 32-bit words */
  171. int i = 0;
  172. size_t keySize = 16u;
  173. while (keySize != 0U)
  174. {
  175. keySize -= sizeof(uint32_t);
  176. base->KEYDATA = ((uint32_t *)(uintptr_t)key)[i];
  177. i++;
  178. }
  179. return kStatus_Success;
  180. }
  181. /* Disable optimizations for GCC to prevent instruction reordering */
  182. #if defined(__GNUC__)
  183. #pragma GCC push_options
  184. #pragma GCC optimize("O0")
  185. #endif
  186. static status_t dcp_schedule_work(DCP_Type *base, dcp_handle_t *handle, dcp_work_packet_t *dcpPacket)
  187. {
  188. status_t status;
  189. /* check if our channel is active */
  190. if ((base->STAT & (uint32_t)handle->channel) != (uint32_t)handle->channel)
  191. {
  192. /* disable global interrupt */
  193. uint32_t currPriMask = DisableGlobalIRQ();
  194. /* re-check if our channel is still available */
  195. if ((base->STAT & (uint32_t)handle->channel) == 0U)
  196. {
  197. volatile uint32_t *cmdptr = NULL;
  198. volatile uint32_t *chsema = NULL;
  199. switch (handle->channel)
  200. {
  201. case kDCP_Channel0:
  202. cmdptr = &base->CH0CMDPTR;
  203. chsema = &base->CH0SEMA;
  204. break;
  205. case kDCP_Channel1:
  206. cmdptr = &base->CH1CMDPTR;
  207. chsema = &base->CH1SEMA;
  208. break;
  209. case kDCP_Channel2:
  210. cmdptr = &base->CH2CMDPTR;
  211. chsema = &base->CH2SEMA;
  212. break;
  213. case kDCP_Channel3:
  214. cmdptr = &base->CH3CMDPTR;
  215. chsema = &base->CH3SEMA;
  216. break;
  217. default:
  218. /* All the cases have been listed above, the default clause should not be reached. */
  219. break;
  220. }
  221. if ((NULL != cmdptr) && (NULL != chsema))
  222. {
  223. /* set out packet to DCP CMDPTR */
  224. *cmdptr = (uint32_t)dcpPacket;
  225. #if defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  226. /* Clean DCACHE before sending DCP packet to engine */
  227. DCACHE_CleanByRange((uint32_t)dcpPacket, sizeof(dcp_work_packet_t));
  228. #endif
  229. /* Make sure that all data memory accesses are completed before starting of the job */
  230. __DSB();
  231. __ISB();
  232. /* set the channel semaphore to start the job */
  233. *chsema = 1u;
  234. }
  235. status = kStatus_Success;
  236. }
  237. else
  238. {
  239. status = (int32_t)kStatus_DCP_Again;
  240. }
  241. /* global interrupt enable */
  242. EnableGlobalIRQ(currPriMask);
  243. }
  244. else
  245. {
  246. return (int32_t)kStatus_DCP_Again;
  247. }
  248. return status;
  249. }
  250. #if defined(__GNUC__)
  251. #pragma GCC pop_options
  252. #endif
  253. /*!
  254. * brief Set AES key to dcp_handle_t struct and optionally to DCP.
  255. *
  256. * Sets the AES key for encryption/decryption with the dcp_handle_t structure.
  257. * The dcp_handle_t input argument specifies keySlot.
  258. * If the keySlot is kDCP_OtpKey, the function will check the OTP_KEY_READY bit and will return it's ready to use
  259. * status.
  260. * For other keySlot selections, the function will copy and hold the key in dcp_handle_t struct.
  261. * If the keySlot is one of the four DCP SRAM-based keys (one of kDCP_KeySlot0, kDCP_KeySlot1, kDCP_KeySlot2,
  262. * kDCP_KeySlot3),
  263. * this function will also load the supplied key to the specified keySlot in DCP.
  264. *
  265. * param base DCP peripheral base address.
  266. * param handle Handle used for the request.
  267. * param key 0-mod-4 aligned pointer to AES key.
  268. * param keySize AES key size in bytes. Shall equal 16.
  269. * return status from set key operation
  270. */
  271. status_t DCP_AES_SetKey(DCP_Type *base, dcp_handle_t *handle, const uint8_t *key, size_t keySize)
  272. {
  273. status_t status = kStatus_Fail;
  274. if ((kDCP_OtpKey == handle->keySlot) || (kDCP_OtpUniqueKey == handle->keySlot))
  275. {
  276. /* for AES OTP and unique key, check and return read from fuses status */
  277. if ((base->STAT & DCP_STAT_OTP_KEY_READY_MASK) == DCP_STAT_OTP_KEY_READY_MASK)
  278. {
  279. status = kStatus_Success;
  280. }
  281. }
  282. else
  283. {
  284. /* only work with aligned key[] */
  285. if ((0x3U & (uintptr_t)key) != 0U)
  286. {
  287. return kStatus_InvalidArgument;
  288. }
  289. /* keySize must be 16. */
  290. if (keySize != 16U)
  291. {
  292. return kStatus_InvalidArgument;
  293. }
  294. /* move the key by 32-bit words */
  295. int i = 0;
  296. while (keySize != 0U)
  297. {
  298. keySize -= sizeof(uint32_t);
  299. handle->keyWord[i] = ((uint32_t *)(uintptr_t)key)[i];
  300. i++;
  301. }
  302. if (kDCP_PayloadKey != handle->keySlot)
  303. {
  304. /* move the key by 32-bit words to DCP SRAM-based key storage */
  305. status = dcp_aes_set_sram_based_key(base, handle, key);
  306. }
  307. else
  308. {
  309. /* for PAYLOAD_KEY, just return Ok status now */
  310. status = kStatus_Success;
  311. }
  312. }
  313. return status;
  314. }
  315. /*!
  316. * brief Encrypts AES on one or multiple 128-bit block(s).
  317. *
  318. * Encrypts AES.
  319. * The source plaintext and destination ciphertext can overlap in system memory.
  320. *
  321. * param base DCP peripheral base address
  322. * param handle Handle used for this request.
  323. * param plaintext Input plain text to encrypt
  324. * param[out] ciphertext Output cipher text
  325. * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
  326. * return Status from encrypt operation
  327. */
  328. status_t DCP_AES_EncryptEcb(
  329. DCP_Type *base, dcp_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size)
  330. {
  331. status_t completionStatus = kStatus_Fail;
  332. /* Use extended DCACHE line size aligned structure */
  333. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  334. dcp_work_packet_t *dcpWork;
  335. uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U};
  336. dcpWork = (dcp_work_packet_t *)(uint32_t)DCP_FindCacheLine(dcpWorkExt);
  337. #else
  338. dcp_work_packet_t dcpWorkPacket = {0};
  339. dcp_work_packet_t *dcpWork = &dcpWorkPacket;
  340. #endif
  341. do
  342. {
  343. completionStatus = DCP_AES_EncryptEcbNonBlocking(base, handle, dcpWork, plaintext, ciphertext, size);
  344. } while (completionStatus == (int32_t)kStatus_DCP_Again);
  345. if (completionStatus != kStatus_Success)
  346. {
  347. return completionStatus;
  348. }
  349. return DCP_WaitForChannelComplete(base, handle);
  350. }
  351. /*!
  352. * brief Encrypts AES using the ECB block mode.
  353. *
  354. * Puts AES ECB encrypt work packet to DCP channel.
  355. *
  356. * param base DCP peripheral base address
  357. * param handle Handle used for this request.
  358. * param[out] dcpPacket Memory for the DCP work packet.
  359. * param plaintext Input plain text to encrypt.
  360. * param[out] ciphertext Output cipher text
  361. * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
  362. * return kStatus_Success The work packet has been scheduled at DCP channel.
  363. * return kStatus_DCP_Again The DCP channel is busy processing previous request.
  364. */
  365. status_t DCP_AES_EncryptEcbNonBlocking(DCP_Type *base,
  366. dcp_handle_t *handle,
  367. dcp_work_packet_t *dcpPacket,
  368. const uint8_t *plaintext,
  369. uint8_t *ciphertext,
  370. size_t size)
  371. {
  372. /* Size must be 16-byte multiple */
  373. if ((size < 16u) || (0U != (size % 16u)))
  374. {
  375. return kStatus_InvalidArgument;
  376. }
  377. dcpPacket->control0 =
  378. 0x122u | (handle->swapConfig & 0xFC0000u); /* CIPHER_ENCRYPT | ENABLE_CIPHER | DECR_SEMAPHORE */
  379. dcpPacket->sourceBufferAddress = (uint32_t)plaintext;
  380. dcpPacket->destinationBufferAddress = (uint32_t)ciphertext;
  381. dcpPacket->bufferSize = (uint32_t)size;
  382. if (handle->keySlot == kDCP_OtpKey)
  383. {
  384. dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */
  385. dcpPacket->control1 = ((uint32_t)0xFFu << 8); /* KEY_SELECT = OTP_KEY */
  386. }
  387. else if (handle->keySlot == kDCP_OtpUniqueKey)
  388. {
  389. dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */
  390. dcpPacket->control1 = ((uint32_t)0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */
  391. }
  392. else if (handle->keySlot == kDCP_PayloadKey)
  393. {
  394. /* ECB does not have IV, so we can point payload directly to keyWord[] stored in handle. */
  395. dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0];
  396. dcpPacket->control0 |= ((uint32_t)1u << 11); /* PAYLOAD_KEY */
  397. }
  398. else
  399. {
  400. dcpPacket->control1 = ((uint32_t)handle->keySlot << 8); /* KEY_SELECT = keySlot */
  401. }
  402. return dcp_schedule_work(base, handle, dcpPacket);
  403. }
  404. /*!
  405. * brief Decrypts AES on one or multiple 128-bit block(s).
  406. *
  407. * Decrypts AES.
  408. * The source ciphertext and destination plaintext can overlap in system memory.
  409. *
  410. * param base DCP peripheral base address
  411. * param handle Handle used for this request.
  412. * param ciphertext Input plain text to encrypt
  413. * param[out] plaintext Output cipher text
  414. * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
  415. * return Status from decrypt operation
  416. */
  417. status_t DCP_AES_DecryptEcb(
  418. DCP_Type *base, dcp_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size)
  419. {
  420. status_t completionStatus = kStatus_Fail;
  421. /* Use extended DCACHE line size aligned structure */
  422. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  423. dcp_work_packet_t *dcpWork;
  424. uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U};
  425. dcpWork = (dcp_work_packet_t *)(uint32_t)DCP_FindCacheLine(dcpWorkExt);
  426. #else
  427. dcp_work_packet_t dcpWorkPacket = {0};
  428. dcp_work_packet_t *dcpWork = &dcpWorkPacket;
  429. #endif
  430. do
  431. {
  432. completionStatus = DCP_AES_DecryptEcbNonBlocking(base, handle, dcpWork, ciphertext, plaintext, size);
  433. } while (completionStatus == (int32_t)(kStatus_DCP_Again));
  434. if (completionStatus != kStatus_Success)
  435. {
  436. return completionStatus;
  437. }
  438. return DCP_WaitForChannelComplete(base, handle);
  439. }
  440. /*!
  441. * brief Decrypts AES using ECB block mode.
  442. *
  443. * Puts AES ECB decrypt dcpPacket to DCP input job ring.
  444. *
  445. * param base DCP peripheral base address
  446. * param handle Handle used for this request.
  447. * param[out] dcpPacket Memory for the DCP work packet.
  448. * param ciphertext Input cipher text to decrypt
  449. * param[out] plaintext Output plain text
  450. * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
  451. * return kStatus_Success The work packet has been scheduled at DCP channel.
  452. * return kStatus_DCP_Again The DCP channel is busy processing previous request.
  453. */
  454. status_t DCP_AES_DecryptEcbNonBlocking(DCP_Type *base,
  455. dcp_handle_t *handle,
  456. dcp_work_packet_t *dcpPacket,
  457. const uint8_t *ciphertext,
  458. uint8_t *plaintext,
  459. size_t size)
  460. {
  461. /* Size must be 16-byte multiple */
  462. if ((size < 16u) || (0U != (size % 16u)))
  463. {
  464. return kStatus_InvalidArgument;
  465. }
  466. dcpPacket->control0 = 0x22u | (handle->swapConfig & 0xFC0000u); /* ENABLE_CIPHER | DECR_SEMAPHORE */
  467. dcpPacket->sourceBufferAddress = (uint32_t)ciphertext;
  468. dcpPacket->destinationBufferAddress = (uint32_t)plaintext;
  469. dcpPacket->bufferSize = (uint32_t)size;
  470. if (handle->keySlot == kDCP_OtpKey)
  471. {
  472. dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */
  473. dcpPacket->control1 = ((uint32_t)0xFFu << 8); /* KEY_SELECT = OTP_KEY */
  474. }
  475. else if (handle->keySlot == kDCP_OtpUniqueKey)
  476. {
  477. dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */
  478. dcpPacket->control1 = ((uint32_t)0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */
  479. }
  480. else if (handle->keySlot == kDCP_PayloadKey)
  481. {
  482. /* ECB does not have IV, so we can point payload directly to keyWord[] stored in handle. */
  483. dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0];
  484. dcpPacket->control0 |= ((uint32_t)1u << 11); /* PAYLOAD_KEY */
  485. }
  486. else
  487. {
  488. dcpPacket->control1 = ((uint32_t)handle->keySlot << 8); /* KEY_SELECT = keySlot */
  489. }
  490. return dcp_schedule_work(base, handle, dcpPacket);
  491. }
  492. /*!
  493. * brief Encrypts AES using CBC block mode.
  494. *
  495. * Encrypts AES using CBC block mode.
  496. * The source plaintext and destination ciphertext can overlap in system memory.
  497. *
  498. * param base DCP peripheral base address
  499. * param handle Handle used for this request.
  500. * param plaintext Input plain text to encrypt
  501. * param[out] ciphertext Output cipher text
  502. * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
  503. * param iv Input initial vector to combine with the first input block.
  504. * return Status from encrypt operation
  505. */
  506. status_t DCP_AES_EncryptCbc(DCP_Type *base,
  507. dcp_handle_t *handle,
  508. const uint8_t *plaintext,
  509. uint8_t *ciphertext,
  510. size_t size,
  511. const uint8_t iv[16])
  512. {
  513. status_t completionStatus = kStatus_Fail;
  514. /* Use extended DCACHE line size aligned structure */
  515. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  516. dcp_work_packet_t *dcpWork;
  517. uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U};
  518. dcpWork = (dcp_work_packet_t *)(uint32_t)DCP_FindCacheLine(dcpWorkExt);
  519. #else
  520. dcp_work_packet_t dcpWorkPacket = {0};
  521. dcp_work_packet_t *dcpWork = &dcpWorkPacket;
  522. #endif
  523. do
  524. {
  525. completionStatus = DCP_AES_EncryptCbcNonBlocking(base, handle, dcpWork, plaintext, ciphertext, size, iv);
  526. } while (completionStatus == (int32_t)kStatus_DCP_Again);
  527. if (completionStatus != kStatus_Success)
  528. {
  529. return completionStatus;
  530. }
  531. return DCP_WaitForChannelComplete(base, handle);
  532. }
  533. /*!
  534. * brief Encrypts AES using CBC block mode.
  535. *
  536. * Puts AES CBC encrypt dcpPacket to DCP input job ring.
  537. *
  538. * param base DCP peripheral base address
  539. * param handle Handle used for this request. Specifies jobRing.
  540. * param[out] dcpPacket Memory for the DCP work packet.
  541. * param plaintext Input plain text to encrypt
  542. * param[out] ciphertext Output cipher text
  543. * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
  544. * param iv Input initial vector to combine with the first input block.
  545. * return kStatus_Success The work packet has been scheduled at DCP channel.
  546. * return kStatus_DCP_Again The DCP channel is busy processing previous request.
  547. */
  548. status_t DCP_AES_EncryptCbcNonBlocking(DCP_Type *base,
  549. dcp_handle_t *handle,
  550. dcp_work_packet_t *dcpPacket,
  551. const uint8_t *plaintext,
  552. uint8_t *ciphertext,
  553. size_t size,
  554. const uint8_t *iv)
  555. {
  556. /* Size must be 16-byte multiple */
  557. if ((size < 16u) || (0U != (size % 16u)))
  558. {
  559. return kStatus_InvalidArgument;
  560. }
  561. dcpPacket->control0 =
  562. 0x322u | (handle->swapConfig & 0xFC0000u); /* CIPHER_INIT | CIPHER_ENCRYPT | ENABLE_CIPHER | DECR_SEMAPHORE */
  563. dcpPacket->control1 = 0x10u; /* CBC */
  564. dcpPacket->sourceBufferAddress = (uint32_t)plaintext;
  565. dcpPacket->destinationBufferAddress = (uint32_t)ciphertext;
  566. dcpPacket->bufferSize = (uint32_t)size;
  567. if (handle->keySlot == kDCP_OtpKey)
  568. {
  569. dcpPacket->payloadPointer = (uint32_t)iv;
  570. dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */
  571. dcpPacket->control1 |= ((uint32_t)0xFFu << 8); /* KEY_SELECT = OTP_KEY */
  572. }
  573. else if (handle->keySlot == kDCP_OtpUniqueKey)
  574. {
  575. dcpPacket->payloadPointer = (uint32_t)iv;
  576. dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */
  577. dcpPacket->control1 |= ((uint32_t)0xFEu << 8); /* KEY_SELECT = UNIQUE_KEY */
  578. }
  579. else if (handle->keySlot == kDCP_PayloadKey)
  580. {
  581. /* In this case payload must contain key & iv in one array. */
  582. /* Copy iv into handle right behind the keyWord[] so we can point payload to keyWord[]. */
  583. (void)dcp_memcpy(handle->iv, (const uint32_t *)(uintptr_t)iv, 16);
  584. dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0];
  585. dcpPacket->control0 |= ((uint32_t)1u << 11); /* PAYLOAD_KEY */
  586. }
  587. else
  588. {
  589. dcpPacket->payloadPointer = (uint32_t)iv;
  590. dcpPacket->control1 |= ((uint32_t)handle->keySlot << 8); /* KEY_SELECT = keySlot */
  591. }
  592. return dcp_schedule_work(base, handle, dcpPacket);
  593. }
  594. /*!
  595. * brief Decrypts AES using CBC block mode.
  596. *
  597. * Decrypts AES using CBC block mode.
  598. * The source ciphertext and destination plaintext can overlap in system memory.
  599. *
  600. * param base DCP peripheral base address
  601. * param handle Handle used for this request.
  602. * param ciphertext Input cipher text to decrypt
  603. * param[out] plaintext Output plain text
  604. * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
  605. * param iv Input initial vector to combine with the first input block.
  606. * return Status from decrypt operation
  607. */
  608. status_t DCP_AES_DecryptCbc(DCP_Type *base,
  609. dcp_handle_t *handle,
  610. const uint8_t *ciphertext,
  611. uint8_t *plaintext,
  612. size_t size,
  613. const uint8_t iv[16])
  614. {
  615. status_t completionStatus = kStatus_Fail;
  616. /* Use extended DCACHE line size aligned structure */
  617. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  618. dcp_work_packet_t *dcpWork;
  619. uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U};
  620. dcpWork = (dcp_work_packet_t *)(uint32_t)DCP_FindCacheLine(dcpWorkExt);
  621. #else
  622. dcp_work_packet_t dcpWorkPacket = {0};
  623. dcp_work_packet_t *dcpWork = &dcpWorkPacket;
  624. #endif
  625. do
  626. {
  627. completionStatus = DCP_AES_DecryptCbcNonBlocking(base, handle, dcpWork, ciphertext, plaintext, size, iv);
  628. } while (completionStatus == (int32_t)kStatus_DCP_Again);
  629. if (completionStatus != (int32_t)kStatus_Success)
  630. {
  631. return completionStatus;
  632. }
  633. return DCP_WaitForChannelComplete(base, handle);
  634. }
  635. /*!
  636. * brief Decrypts AES using CBC block mode.
  637. *
  638. * Puts AES CBC decrypt dcpPacket to DCP input job ring.
  639. *
  640. * param base DCP peripheral base address
  641. * param handle Handle used for this request. Specifies jobRing.
  642. * param[out] dcpPacket Memory for the DCP work packet.
  643. * param ciphertext Input cipher text to decrypt
  644. * param[out] plaintext Output plain text
  645. * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
  646. * param iv Input initial vector to combine with the first input block.
  647. * return kStatus_Success The work packet has been scheduled at DCP channel.
  648. * return kStatus_DCP_Again The DCP channel is busy processing previous request.
  649. */
  650. status_t DCP_AES_DecryptCbcNonBlocking(DCP_Type *base,
  651. dcp_handle_t *handle,
  652. dcp_work_packet_t *dcpPacket,
  653. const uint8_t *ciphertext,
  654. uint8_t *plaintext,
  655. size_t size,
  656. const uint8_t *iv)
  657. {
  658. /* Size must be 16-byte multiple */
  659. if ((size < 16u) || (0U != (size % 16u)))
  660. {
  661. return kStatus_InvalidArgument;
  662. }
  663. dcpPacket->control0 = 0x222u | (handle->swapConfig & 0xFC0000u); /* CIPHER_INIT | ENABLE_CIPHER | DECR_SEMAPHORE */
  664. dcpPacket->control1 = 0x10u; /* CBC */
  665. dcpPacket->sourceBufferAddress = (uint32_t)ciphertext;
  666. dcpPacket->destinationBufferAddress = (uint32_t)plaintext;
  667. dcpPacket->bufferSize = (uint32_t)size;
  668. if (handle->keySlot == kDCP_OtpKey)
  669. {
  670. dcpPacket->payloadPointer = (uint32_t)iv;
  671. dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */
  672. dcpPacket->control1 |= ((uint32_t)0xFFu << 8); /* OTP_KEY */
  673. }
  674. else if (handle->keySlot == kDCP_OtpUniqueKey)
  675. {
  676. dcpPacket->payloadPointer = (uint32_t)iv;
  677. dcpPacket->control0 |= ((uint32_t)1u << 10); /* OTP_KEY */
  678. dcpPacket->control1 |= ((uint32_t)0xFEu << 8); /* UNIQUE_KEY */
  679. }
  680. else if (handle->keySlot == kDCP_PayloadKey)
  681. {
  682. /* in this case payload must contain KEY + IV together */
  683. /* copy iv into handle struct so we can point payload directly to keyWord[]. */
  684. (void)dcp_memcpy(handle->iv, (const uint32_t *)(uintptr_t)iv, 16);
  685. dcpPacket->payloadPointer = (uint32_t)&handle->keyWord[0];
  686. dcpPacket->control0 |= ((uint32_t)1u << 11); /* PAYLOAD_KEY */
  687. }
  688. else
  689. {
  690. dcpPacket->payloadPointer = (uint32_t)iv;
  691. dcpPacket->control1 |= ((uint32_t)handle->keySlot << 8); /* KEY_SELECT */
  692. }
  693. return dcp_schedule_work(base, handle, dcpPacket);
  694. }
  695. /*!
  696. * brief Gets the default configuration structure.
  697. *
  698. * This function initializes the DCP configuration structure to a default value. The default
  699. * values are as follows.
  700. * dcpConfig->gatherResidualWrites = true;
  701. * dcpConfig->enableContextCaching = true;
  702. * dcpConfig->enableContextSwitching = true;
  703. * dcpConfig->enableChannnel = kDCP_chEnableAll;
  704. * dcpConfig->enableChannelInterrupt = kDCP_chIntDisable;
  705. *
  706. * param[out] config Pointer to configuration structure.
  707. */
  708. void DCP_GetDefaultConfig(dcp_config_t *config)
  709. {
  710. /* ENABLE_CONTEXT_CACHING is disabled by default as the DCP Hash driver uses
  711. * dcp_hash_save_running_hash() and dcp_hash_restore_running_hash() to support
  712. * Hash context switch (different messages interleaved) on the same channel.
  713. */
  714. /* Initializes the configure structure to zero. */
  715. (void)memset(config, 0, sizeof(*config));
  716. dcp_config_t userConfig = {
  717. true, false, true, (uint8_t)kDCP_chEnableAll, (uint8_t)kDCP_chIntDisable,
  718. };
  719. *config = userConfig;
  720. }
  721. /*!
  722. * brief Enables clock to and enables DCP
  723. *
  724. * Enable DCP clock and configure DCP.
  725. *
  726. * param base DCP base address
  727. * param config Pointer to configuration structure.
  728. */
  729. void DCP_Init(DCP_Type *base, const dcp_config_t *config)
  730. {
  731. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  732. CLOCK_EnableClock(kCLOCK_Dcp);
  733. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  734. base->CTRL = 0xF0800000u; /* reset value */
  735. base->CTRL = 0x30800000u; /* default value */
  736. dcp_clear_status(base);
  737. dcp_clear_channel_status(
  738. base, (uint32_t)kDCP_Channel0 | (uint32_t)kDCP_Channel1 | (uint32_t)kDCP_Channel2 | (uint32_t)kDCP_Channel3);
  739. base->CTRL = DCP_CTRL_GATHER_RESIDUAL_WRITES(config->gatherResidualWrites) |
  740. DCP_CTRL_ENABLE_CONTEXT_CACHING(config->enableContextCaching) |
  741. DCP_CTRL_ENABLE_CONTEXT_SWITCHING(config->enableContextSwitching) |
  742. DCP_CTRL_CHANNEL_INTERRUPT_ENABLE(config->enableChannelInterrupt);
  743. /* enable DCP channels */
  744. base->CHANNELCTRL = DCP_CHANNELCTRL_ENABLE_CHANNEL(config->enableChannel);
  745. /* use context switching buffer */
  746. base->CONTEXT = (uint32_t)&s_dcpContextSwitchingBuffer;
  747. }
  748. /*!
  749. * brief Disable DCP clock
  750. *
  751. * Reset DCP and Disable DCP clock.
  752. *
  753. * param base DCP base address
  754. */
  755. void DCP_Deinit(DCP_Type *base)
  756. {
  757. base->CTRL = 0xF0800000u; /* reset value */
  758. (void)memset(&s_dcpContextSwitchingBuffer, 0, sizeof(s_dcpContextSwitchingBuffer));
  759. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  760. CLOCK_DisableClock(kCLOCK_Dcp);
  761. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  762. }
  763. /*!
  764. * brief Poll and wait on DCP channel.
  765. *
  766. * Polls the specified DCP channel until current it completes activity.
  767. *
  768. * param base DCP peripheral base address.
  769. * param handle Specifies DCP channel.
  770. * return kStatus_Success When data processing completes without error.
  771. * return kStatus_Fail When error occurs.
  772. */
  773. status_t DCP_WaitForChannelComplete(DCP_Type *base, dcp_handle_t *handle)
  774. {
  775. /* wait if our channel is still active */
  776. while ((base->STAT & (uint32_t)handle->channel) == (uint32_t)handle->channel)
  777. {
  778. }
  779. if (dcp_get_channel_status(base, handle->channel) != kStatus_Success)
  780. {
  781. dcp_clear_status(base);
  782. dcp_clear_channel_status(base, (uint32_t)handle->channel);
  783. return kStatus_Fail;
  784. }
  785. dcp_clear_status(base);
  786. return kStatus_Success;
  787. }
  788. /*!
  789. * @brief Check validity of algoritm.
  790. *
  791. * This function checks the validity of input argument.
  792. *
  793. * @param algo Tested algorithm value.
  794. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
  795. */
  796. static status_t dcp_hash_check_input_alg(dcp_hash_algo_t algo)
  797. {
  798. if ((algo != kDCP_Sha256) && (algo != kDCP_Sha1) && (algo != kDCP_Crc32))
  799. {
  800. return kStatus_InvalidArgument;
  801. }
  802. return kStatus_Success;
  803. }
  804. /*!
  805. * @brief Check validity of input arguments.
  806. *
  807. * This function checks the validity of input arguments.
  808. *
  809. * @param base DCP peripheral base address.
  810. * @param ctx Memory buffer given by user application where the DCP_HASH_Init/DCP_HASH_Update/DCP_HASH_Finish store
  811. * context.
  812. * @param algo Tested algorithm value.
  813. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
  814. */
  815. static status_t dcp_hash_check_input_args(DCP_Type *base, dcp_hash_ctx_t *ctx, dcp_hash_algo_t algo)
  816. {
  817. /* Check validity of input algorithm */
  818. if (kStatus_Success != dcp_hash_check_input_alg(algo))
  819. {
  820. return kStatus_InvalidArgument;
  821. }
  822. if ((NULL == ctx) || (NULL == base))
  823. {
  824. return kStatus_InvalidArgument;
  825. }
  826. return kStatus_Success;
  827. }
  828. /*!
  829. * @brief Check validity of internal software context.
  830. *
  831. * This function checks if the internal context structure looks correct.
  832. *
  833. * @param ctxInternal Internal context.
  834. * @param message Input message address.
  835. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
  836. */
  837. static status_t dcp_hash_check_context(dcp_hash_ctx_internal_t *ctxInternal, const uint8_t *message)
  838. {
  839. if ((NULL == message) || (NULL == ctxInternal) || (kStatus_Success != dcp_hash_check_input_alg(ctxInternal->algo)))
  840. {
  841. return kStatus_InvalidArgument;
  842. }
  843. return kStatus_Success;
  844. }
  845. /*!
  846. * @brief Initialize the SHA engine for new hash.
  847. *
  848. * This function sets kDCP_CONTROL0_HASH_INIT for control0 in work packet to start a new hash.
  849. *
  850. * @param base SHA peripheral base address.
  851. * @param ctxInternal Internal context.
  852. */
  853. static status_t dcp_hash_engine_init(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal)
  854. {
  855. status_t status;
  856. status = kStatus_InvalidArgument;
  857. if ((kDCP_Sha256 == ctxInternal->algo) || (kDCP_Sha1 == ctxInternal->algo) || (kDCP_Crc32 == ctxInternal->algo))
  858. {
  859. ctxInternal->ctrl0 = (uint32_t)kDCP_CONTROL0_HASH_INIT;
  860. status = kStatus_Success;
  861. }
  862. return status;
  863. }
  864. static status_t dcp_hash_update_non_blocking(
  865. DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal, dcp_work_packet_t *dcpPacket, const uint8_t *msg, size_t size)
  866. {
  867. dcpPacket->control0 = ctxInternal->ctrl0 | (ctxInternal->handle->swapConfig & 0xFC0000u) |
  868. (uint32_t)kDCP_CONTROL0_ENABLE_HASH | (uint32_t)kDCP_CONTROL0_DECR_SEMAPHOR;
  869. if (ctxInternal->algo == kDCP_Sha256)
  870. {
  871. dcpPacket->control1 = (uint32_t)kDCP_CONTROL1_HASH_SELECT_SHA256;
  872. }
  873. else if (ctxInternal->algo == kDCP_Sha1)
  874. {
  875. dcpPacket->control1 = (uint32_t)kDCP_CONTROL1_HASH_SELECT_SHA1;
  876. }
  877. else if (ctxInternal->algo == kDCP_Crc32)
  878. {
  879. /* In CRC-32 case if size is zero, do not schedule other computing */
  880. if (size == 0U)
  881. {
  882. #if defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  883. /* Clear DCACHE memory before starting the engine */
  884. DCACHE_CleanByRange((uint32_t)ctxInternal, sizeof(dcp_hash_ctx_internal_t));
  885. #endif
  886. /* Make sure that all data memory accesses are completed before starting of the job */
  887. __DSB();
  888. __ISB();
  889. return kStatus_Success;
  890. }
  891. dcpPacket->control1 = (uint32_t)kDCP_CONTROL1_HASH_SELECT_CRC32;
  892. }
  893. else
  894. {
  895. return kStatus_Fail;
  896. }
  897. dcpPacket->sourceBufferAddress = (uint32_t)msg;
  898. dcpPacket->destinationBufferAddress = 0;
  899. dcpPacket->bufferSize = size;
  900. dcpPacket->payloadPointer = (uint32_t)ctxInternal->runningHash;
  901. #if defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  902. /* Clear DCACHE memory before starting the engine */
  903. DCACHE_CleanByRange((uint32_t)ctxInternal, sizeof(dcp_hash_ctx_internal_t));
  904. #endif
  905. /* Make sure that all data memory accesses are completed before starting of the job */
  906. __DSB();
  907. __ISB();
  908. return dcp_schedule_work(base, ctxInternal->handle, dcpPacket);
  909. }
  910. static status_t dcp_hash_update(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal, const uint8_t *msg, size_t size)
  911. {
  912. status_t completionStatus = kStatus_Fail;
  913. /* Use extended DCACHE line size aligned structure */
  914. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  915. dcp_work_packet_t *dcpWork;
  916. uint8_t dcpWorkExt[sizeof(dcp_work_packet_t) + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE] = {0U};
  917. dcpWork = (dcp_work_packet_t *)(uint32_t)DCP_FindCacheLine(dcpWorkExt);
  918. #else
  919. dcp_work_packet_t dcpWorkPacket = {0};
  920. dcp_work_packet_t *dcpWork = &dcpWorkPacket;
  921. #endif
  922. do
  923. {
  924. completionStatus = dcp_hash_update_non_blocking(base, ctxInternal, dcpWork, msg, size);
  925. } while (completionStatus == (int32_t)kStatus_DCP_Again);
  926. completionStatus = DCP_WaitForChannelComplete(base, ctxInternal->handle);
  927. ctxInternal->ctrl0 = 0; /* clear kDCP_CONTROL0_HASH_INIT and kDCP_CONTROL0_HASH_TERM flags */
  928. return (completionStatus);
  929. }
  930. /*!
  931. * @brief Adds message to current hash.
  932. *
  933. * This function merges the message to fill the internal buffer, empties the internal buffer if
  934. * it becomes full, then process all remaining message data.
  935. *
  936. *
  937. * @param base DCP peripheral base address.
  938. * @param ctxInternal Internal context.
  939. * @param message Input message.
  940. * @param messageSize Size of input message in bytes.
  941. * @return kStatus_Success.
  942. */
  943. static status_t dcp_hash_process_message_data(DCP_Type *base,
  944. dcp_hash_ctx_internal_t *ctxInternal,
  945. const uint8_t *message,
  946. size_t messageSize)
  947. {
  948. status_t status = kStatus_Fail;
  949. /* if there is partially filled internal buffer, fill it to full block */
  950. if (ctxInternal->blksz > 0U)
  951. {
  952. size_t toCopy = DCP_HASH_BLOCK_SIZE - ctxInternal->blksz;
  953. (void)dcp_memcpy(&ctxInternal->blk.b[ctxInternal->blksz], message, toCopy);
  954. message += toCopy;
  955. messageSize -= toCopy;
  956. /* process full internal block */
  957. status = dcp_hash_update(base, ctxInternal, &ctxInternal->blk.b[0], DCP_HASH_BLOCK_SIZE);
  958. if (kStatus_Success != status)
  959. {
  960. return status;
  961. }
  962. }
  963. /* process all full blocks in message[] */
  964. uint32_t fullBlocksSize = ((messageSize >> 6) << 6); /* (X / 64) * 64 */
  965. if (fullBlocksSize > 0U)
  966. {
  967. status = dcp_hash_update(base, ctxInternal, message, fullBlocksSize);
  968. if (kStatus_Success != status)
  969. {
  970. return status;
  971. }
  972. message += fullBlocksSize;
  973. messageSize -= fullBlocksSize;
  974. }
  975. /* copy last incomplete message bytes into internal block */
  976. (void)dcp_memcpy(&ctxInternal->blk.b[0], message, messageSize);
  977. ctxInternal->blksz = messageSize;
  978. return status;
  979. }
  980. /*!
  981. * @brief Finalize the running hash to make digest.
  982. *
  983. * This function empties the internal buffer, adds padding bits, and generates final digest.
  984. *
  985. * @param base SHA peripheral base address.
  986. * @param ctxInternal Internal context.
  987. * @return kStatus_Success.
  988. */
  989. static status_t dcp_hash_finalize(DCP_Type *base, dcp_hash_ctx_internal_t *ctxInternal)
  990. {
  991. status_t status;
  992. ctxInternal->ctrl0 |= (uint32_t)kDCP_CONTROL0_HASH_TERM;
  993. status = dcp_hash_update(base, ctxInternal, &ctxInternal->blk.b[0], ctxInternal->blksz);
  994. return status;
  995. }
  996. static void dcp_hash_save_running_hash(dcp_hash_ctx_internal_t *ctxInternal)
  997. {
  998. uint32_t *srcAddr = NULL;
  999. switch (ctxInternal->handle->channel)
  1000. {
  1001. case kDCP_Channel0:
  1002. srcAddr = &s_dcpContextSwitchingBuffer.x[43];
  1003. break;
  1004. case kDCP_Channel1:
  1005. srcAddr = &s_dcpContextSwitchingBuffer.x[30];
  1006. break;
  1007. case kDCP_Channel2:
  1008. srcAddr = &s_dcpContextSwitchingBuffer.x[17];
  1009. break;
  1010. case kDCP_Channel3:
  1011. srcAddr = &s_dcpContextSwitchingBuffer.x[4];
  1012. break;
  1013. default:
  1014. /* All the cases have been listed above, the default clause should not be reached. */
  1015. break;
  1016. }
  1017. if (srcAddr != NULL)
  1018. {
  1019. DCACHE_InvalidateByRange((uint32_t)srcAddr, sizeof(ctxInternal->runningHash));
  1020. (void)dcp_memcpy(ctxInternal->runningHash, srcAddr, sizeof(ctxInternal->runningHash));
  1021. }
  1022. }
  1023. static void dcp_hash_restore_running_hash(dcp_hash_ctx_internal_t *ctxInternal)
  1024. {
  1025. uint32_t *destAddr = NULL;
  1026. switch (ctxInternal->handle->channel)
  1027. {
  1028. case kDCP_Channel0:
  1029. destAddr = &s_dcpContextSwitchingBuffer.x[43];
  1030. break;
  1031. case kDCP_Channel1:
  1032. destAddr = &s_dcpContextSwitchingBuffer.x[30];
  1033. break;
  1034. case kDCP_Channel2:
  1035. destAddr = &s_dcpContextSwitchingBuffer.x[17];
  1036. break;
  1037. case kDCP_Channel3:
  1038. destAddr = &s_dcpContextSwitchingBuffer.x[4];
  1039. break;
  1040. default:
  1041. /* No valid channel */
  1042. break;
  1043. }
  1044. if (destAddr != NULL)
  1045. {
  1046. (void)dcp_memcpy(destAddr, ctxInternal->runningHash, sizeof(ctxInternal->runningHash));
  1047. }
  1048. }
  1049. /*!
  1050. * brief Initialize HASH context
  1051. *
  1052. * This function initializes the HASH.
  1053. *
  1054. * param base DCP peripheral base address
  1055. * param handle Specifies the DCP channel used for hashing.
  1056. * param[out] ctx Output hash context
  1057. * param algo Underlaying algorithm to use for hash computation.
  1058. * return Status of initialization
  1059. */
  1060. status_t DCP_HASH_Init(DCP_Type *base, dcp_handle_t *handle, dcp_hash_ctx_t *ctx, dcp_hash_algo_t algo)
  1061. {
  1062. status_t status;
  1063. dcp_hash_ctx_internal_t *ctxInternal;
  1064. /* Align structure on DCACHE line*/
  1065. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  1066. ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)((uint8_t *)ctx + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE);
  1067. #else
  1068. ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)ctx;
  1069. #endif
  1070. /* compile time check for the correct structure size */
  1071. BUILD_ASSURE(sizeof(dcp_hash_ctx_t) >= sizeof(dcp_hash_ctx_internal_t), dcp_hash_ctx_t_size);
  1072. uint32_t i;
  1073. status = dcp_hash_check_input_args(base, ctx, algo);
  1074. if (status != kStatus_Success)
  1075. {
  1076. return status;
  1077. }
  1078. /* set algorithm in context struct for later use */
  1079. ctxInternal->algo = algo;
  1080. ctxInternal->blksz = 0u;
  1081. const uint32_t j = sizeof(ctxInternal->blk.w) / sizeof(ctxInternal->blk.w[0]);
  1082. for (i = 0; i < j; i++)
  1083. {
  1084. ctxInternal->blk.w[i] = 0u;
  1085. }
  1086. ctxInternal->state = kDCP_StateHashInit;
  1087. ctxInternal->fullMessageSize = 0;
  1088. ctxInternal->handle = handle;
  1089. return status;
  1090. }
  1091. /*!
  1092. * brief Add data to current HASH
  1093. *
  1094. * Add data to current HASH. This can be called repeatedly with an arbitrary amount of data to be
  1095. * hashed. The functions blocks. If it returns kStatus_Success, the running hash
  1096. * has been updated (DCP has processed the input data), so the memory at ref input pointer
  1097. * can be released back to system. The DCP context buffer is updated with the running hash
  1098. * and with all necessary information to support possible context switch.
  1099. *
  1100. * param base DCP peripheral base address
  1101. * param[in,out] ctx HASH context
  1102. * param input Input data
  1103. * param inputSize Size of input data in bytes
  1104. * return Status of the hash update operation
  1105. */
  1106. status_t DCP_HASH_Update(DCP_Type *base, dcp_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize)
  1107. {
  1108. bool isUpdateState;
  1109. status_t status;
  1110. dcp_hash_ctx_internal_t *ctxInternal;
  1111. size_t blockSize;
  1112. /* Align structure on DCACHE line*/
  1113. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  1114. ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)((uint8_t *)ctx + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE);
  1115. #else
  1116. ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)ctx;
  1117. #endif
  1118. if (inputSize == 0U)
  1119. {
  1120. return kStatus_Success;
  1121. }
  1122. status = dcp_hash_check_context(ctxInternal, input);
  1123. if (kStatus_Success != status)
  1124. {
  1125. return status;
  1126. }
  1127. ctxInternal->fullMessageSize += inputSize;
  1128. blockSize = DCP_HASH_BLOCK_SIZE;
  1129. /* if we are still less than DCP_HASH_BLOCK_SIZE bytes, keep only in context */
  1130. if ((ctxInternal->blksz + inputSize) <= blockSize)
  1131. {
  1132. (void)dcp_memcpy((&ctxInternal->blk.b[0]) + ctxInternal->blksz, input, inputSize);
  1133. ctxInternal->blksz += inputSize;
  1134. return status;
  1135. }
  1136. else
  1137. {
  1138. isUpdateState = ctxInternal->state == kDCP_StateHashUpdate;
  1139. if (!isUpdateState)
  1140. {
  1141. /* start NEW hash */
  1142. status = dcp_hash_engine_init(base, ctxInternal);
  1143. if (status != kStatus_Success)
  1144. {
  1145. return status;
  1146. }
  1147. ctxInternal->state = kDCP_StateHashUpdate;
  1148. }
  1149. else
  1150. {
  1151. dcp_hash_restore_running_hash(ctxInternal);
  1152. }
  1153. }
  1154. /* process input data */
  1155. status = dcp_hash_process_message_data(base, ctxInternal, input, inputSize);
  1156. dcp_hash_save_running_hash(ctxInternal);
  1157. return status;
  1158. }
  1159. /*!
  1160. * brief Finalize hashing
  1161. *
  1162. * Outputs the final hash (computed by DCP_HASH_Update()) and erases the context.
  1163. *
  1164. * param[in,out] ctx Input hash context
  1165. * param[out] output Output hash data
  1166. * param[in,out] outputSize Optional parameter (can be passed as NULL). On function entry, it specifies the size of
  1167. * output[] buffer. On function return, it stores the number of updated output bytes.
  1168. * return Status of the hash finish operation
  1169. */
  1170. status_t DCP_HASH_Finish(DCP_Type *base, dcp_hash_ctx_t *ctx, uint8_t *output, size_t *outputSize)
  1171. {
  1172. size_t algOutSize = 0;
  1173. status_t status;
  1174. dcp_hash_ctx_internal_t *ctxInternal;
  1175. /* Align structure on DCACHE line*/
  1176. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  1177. ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)((uint8_t *)ctx + FSL_FEATURE_L1DCACHE_LINESIZE_BYTE);
  1178. #else
  1179. ctxInternal = (dcp_hash_ctx_internal_t *)(uint32_t)ctx;
  1180. #endif
  1181. status = dcp_hash_check_context(ctxInternal, output);
  1182. if (kStatus_Success != status)
  1183. {
  1184. return status;
  1185. }
  1186. if (ctxInternal->state == kDCP_StateHashInit)
  1187. {
  1188. status = dcp_hash_engine_init(base, ctxInternal);
  1189. if (status != kStatus_Success)
  1190. {
  1191. return status;
  1192. }
  1193. }
  1194. else
  1195. {
  1196. dcp_hash_restore_running_hash(ctxInternal);
  1197. }
  1198. size_t outSize = 0u;
  1199. /* compute algorithm output length */
  1200. switch (ctxInternal->algo)
  1201. {
  1202. case kDCP_Sha256:
  1203. outSize = (uint32_t)kDCP_OutLenSha256;
  1204. break;
  1205. case kDCP_Sha1:
  1206. outSize = (uint32_t)kDCP_OutLenSha1;
  1207. break;
  1208. case kDCP_Crc32:
  1209. outSize = (uint32_t)kDCP_OutLenCrc32;
  1210. break;
  1211. default:
  1212. /* All the cases have been listed above, the default clause should not be reached. */
  1213. break;
  1214. }
  1215. algOutSize = outSize;
  1216. #if defined(DCP_HASH_CAVP_COMPATIBLE)
  1217. if (ctxInternal->fullMessageSize == 0U)
  1218. {
  1219. switch (ctxInternal->algo)
  1220. {
  1221. case kDCP_Sha256:
  1222. (void)dcp_memcpy(&output[0], &s_nullSha256, 32);
  1223. break;
  1224. case kDCP_Sha1:
  1225. (void)dcp_memcpy(&output[0], &s_nullSha1, 20);
  1226. break;
  1227. default:
  1228. /* All the cases have been listed above, the default clause should not be reached. */
  1229. break;
  1230. }
  1231. return kStatus_Success;
  1232. }
  1233. #endif /* DCP_HASH_CAVP_COMPATIBLE */
  1234. /* flush message last incomplete block, if there is any, and add padding bits */
  1235. status = dcp_hash_finalize(base, ctxInternal);
  1236. if (outputSize != NULL)
  1237. {
  1238. if (algOutSize < *outputSize)
  1239. {
  1240. *outputSize = algOutSize;
  1241. }
  1242. else
  1243. {
  1244. algOutSize = *outputSize;
  1245. }
  1246. }
  1247. #if defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  1248. DCACHE_InvalidateByRange((uint32_t)ctxInternal->runningHash, sizeof(ctxInternal->runningHash));
  1249. #endif
  1250. /* Reverse and copy result to output[] */
  1251. dcp_reverse_and_copy((uint8_t *)ctxInternal->runningHash, &output[0], algOutSize);
  1252. (void)memset(ctx, 0, sizeof(dcp_hash_ctx_t));
  1253. return status;
  1254. }
  1255. /*!
  1256. * brief Create HASH on given data
  1257. *
  1258. * Perform the full SHA or CRC32 in one function call. The function is blocking.
  1259. *
  1260. * param base DCP peripheral base address
  1261. * param handle Handle used for the request.
  1262. * param algo Underlaying algorithm to use for hash computation.
  1263. * param input Input data
  1264. * param inputSize Size of input data in bytes
  1265. * param[out] output Output hash data
  1266. * param[out] outputSize Output parameter storing the size of the output hash in bytes
  1267. * return Status of the one call hash operation.
  1268. */
  1269. status_t DCP_HASH(DCP_Type *base,
  1270. dcp_handle_t *handle,
  1271. dcp_hash_algo_t algo,
  1272. const uint8_t *input,
  1273. size_t inputSize,
  1274. uint8_t *output,
  1275. size_t *outputSize)
  1276. {
  1277. dcp_hash_ctx_t hashCtx = {0};
  1278. status_t status;
  1279. status = DCP_HASH_Init(base, handle, &hashCtx, algo);
  1280. if (status != kStatus_Success)
  1281. {
  1282. return status;
  1283. }
  1284. status = DCP_HASH_Update(base, &hashCtx, input, inputSize);
  1285. if (status != kStatus_Success)
  1286. {
  1287. return status;
  1288. }
  1289. status = DCP_HASH_Finish(base, &hashCtx, output, outputSize);
  1290. return status;
  1291. }