dcp_port.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /* dcp_port.c
  2. *
  3. * Copyright (C) 2006-2023 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <wolfssl/wolfcrypt/settings.h>
  25. #ifdef WOLFSSL_IMXRT_DCP
  26. #include <wolfssl/wolfcrypt/aes.h>
  27. #include <wolfssl/wolfcrypt/sha.h>
  28. #include <wolfssl/wolfcrypt/sha256.h>
  29. #include <wolfssl/wolfcrypt/error-crypt.h>
  30. #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U)
  31. #error "DCACHE not supported by this driver. Please undefine DCP_USE_DCACHE."
  32. #endif
  33. #ifndef DCP_USE_OTP_KEY
  34. #define DCP_USE_OTP_KEY 0 /* Set to 1 to select OTP key for AES encryption/decryption. */
  35. #endif
  36. #include "fsl_dcp.h"
  37. #ifndef SINGLE_THREADED
  38. #define dcp_lock_init() wolfSSL_CryptHwMutexInit()
  39. #define dcp_lock() wolfSSL_CryptHwMutexLock()
  40. #define dcp_unlock() wolfSSL_CryptHwMutexUnLock()
  41. #else
  42. #define dcp_lock_init() WC_DO_NOTHING
  43. #define dcp_lock() WC_DO_NOTHING
  44. #define dcp_unlock() WC_DO_NOTHING
  45. #endif
  46. #if DCP_USE_OTP_KEY
  47. typedef enum _dcp_otp_key_select
  48. {
  49. kDCP_OTPMKKeyLow = 1U, /* Use [127:0] from snvs key as dcp key */
  50. kDCP_OTPMKKeyHigh = 2U, /* Use [255:128] from snvs key as dcp key */
  51. kDCP_OCOTPKeyLow = 3U, /* Use [127:0] from ocotp key as dcp key */
  52. kDCP_OCOTPKeyHigh = 4U /* Use [255:128] from ocotp key as dcp key */
  53. } dcp_otp_key_select;
  54. #endif
  55. #if DCP_USE_OTP_KEY
  56. static status_t DCP_OTPKeySelect(dcp_otp_key_select keySelect)
  57. {
  58. status_t retval = kStatus_Success;
  59. if (keySelect == kDCP_OTPMKKeyLow)
  60. {
  61. IOMUXC_GPR->GPR3 &= ~(1 << IOMUXC_GPR_GPR3_DCP_KEY_SEL_SHIFT);
  62. IOMUXC_GPR->GPR10 &= ~(1 << IOMUXC_GPR_GPR10_DCPKEY_OCOTP_OR_KEYMUX_SHIFT);
  63. }
  64. else if (keySelect == kDCP_OTPMKKeyHigh)
  65. {
  66. IOMUXC_GPR->GPR3 |= (1 << IOMUXC_GPR_GPR3_DCP_KEY_SEL_SHIFT);
  67. IOMUXC_GPR->GPR10 &= ~(1 << IOMUXC_GPR_GPR10_DCPKEY_OCOTP_OR_KEYMUX_SHIFT);
  68. }
  69. else if (keySelect == kDCP_OCOTPKeyLow)
  70. {
  71. IOMUXC_GPR->GPR3 &= ~(1 << IOMUXC_GPR_GPR3_DCP_KEY_SEL_SHIFT);
  72. IOMUXC_GPR->GPR10 |= (1 << IOMUXC_GPR_GPR10_DCPKEY_OCOTP_OR_KEYMUX_SHIFT);
  73. }
  74. else if (keySelect == kDCP_OCOTPKeyHigh)
  75. {
  76. IOMUXC_GPR->GPR3 |= (1 << IOMUXC_GPR_GPR3_DCP_KEY_SEL_SHIFT);
  77. IOMUXC_GPR->GPR10 |= (1 << IOMUXC_GPR_GPR10_DCPKEY_OCOTP_OR_KEYMUX_SHIFT);
  78. }
  79. else
  80. {
  81. retval = kStatus_InvalidArgument;
  82. }
  83. return retval;
  84. }
  85. #endif
  86. static const int dcp_channels[4] = {
  87. kDCP_Channel0,
  88. kDCP_Channel1,
  89. kDCP_Channel2,
  90. kDCP_Channel3
  91. };
  92. #ifndef SINGLE_THREADED
  93. static int dcp_status[4] = {0, 0, 0, 0};
  94. #endif
  95. static int dcp_get_channel(void)
  96. {
  97. #ifdef SINGLE_THREADED
  98. return dcp_channels[0];
  99. #else
  100. int i;
  101. int ret = 0;
  102. dcp_lock();
  103. for (i = 0; i < 4; i++) {
  104. if (dcp_status[i] == 0) {
  105. dcp_status[i]++;
  106. ret = dcp_channels[i];
  107. break;
  108. }
  109. }
  110. dcp_unlock();
  111. return ret;
  112. #endif
  113. }
  114. static int dcp_key_slot(int ch)
  115. {
  116. int ret = -1;
  117. #if DCP_USE_OTP_KEY
  118. return kDCP_OtpKey;
  119. #endif
  120. #ifndef SINGLE_THREADED
  121. int i;
  122. dcp_lock();
  123. for (i = 0; i < 4; i++) {
  124. if (ch == dcp_channels[i]) {
  125. ret = i;
  126. break;
  127. }
  128. }
  129. dcp_unlock();
  130. #else
  131. ret = 0;
  132. #endif
  133. return ret;
  134. }
  135. int wc_dcp_init(void)
  136. {
  137. dcp_config_t dcpConfig;
  138. dcp_lock_init();
  139. dcp_lock();
  140. DCP_GetDefaultConfig(&dcpConfig);
  141. /* Reset and initialize DCP */
  142. DCP_Init(DCP, &dcpConfig);
  143. #if DCP_USE_OTP_KEY
  144. /* Set OTP key type in IOMUX registers before initializing DCP. */
  145. /* Software reset of DCP must be issued after changing the OTP key type. */
  146. DCP_OTPKeySelect(kDCP_OTPMKKeyLow);
  147. #endif
  148. /* Release mutex */
  149. dcp_unlock();
  150. return 0;
  151. }
  152. static void dcp_free(int ch)
  153. {
  154. #ifndef SINGLE_THREADED
  155. int i;
  156. dcp_lock();
  157. for (i = 0; i < 4; i++) {
  158. if (ch == dcp_channels[i]) {
  159. dcp_status[i] = 0;
  160. break;
  161. }
  162. }
  163. dcp_unlock();
  164. #endif
  165. }
  166. #ifndef NO_AES
  167. int DCPAesInit(Aes *aes)
  168. {
  169. int ch;
  170. if (!aes)
  171. return BAD_FUNC_ARG;
  172. ch = dcp_get_channel();
  173. if (ch == 0)
  174. return WC_PENDING_E;
  175. XMEMSET(&aes->handle, 0, sizeof(aes->handle));
  176. aes->handle.channel = (dcp_channel_t)ch;
  177. aes->handle.keySlot = (dcp_key_slot_t)dcp_key_slot(aes->handle.channel);
  178. aes->handle.swapConfig = kDCP_NoSwap;
  179. return 0;
  180. }
  181. void DCPAesFree(Aes *aes)
  182. {
  183. dcp_free(aes->handle.channel);
  184. aes->handle.channel = 0;
  185. }
  186. static unsigned char aes_key_aligned[16] __attribute__((aligned(0x10)));
  187. int DCPAesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv,
  188. int dir)
  189. {
  190. #if DCP_USE_OTP_KEY
  191. #warning Please update cipherAes128 variables to match expected AES ciphertext for your OTP key.
  192. #endif
  193. status_t status;
  194. if (!aes || !key)
  195. return BAD_FUNC_ARG;
  196. if (len != 16)
  197. return BAD_FUNC_ARG;
  198. if (aes->handle.channel == 0) {
  199. if (DCPAesInit(aes) != 0)
  200. return WC_HW_E;
  201. }
  202. dcp_lock();
  203. memcpy(aes_key_aligned, key, 16);
  204. status = DCP_AES_SetKey(DCP, &aes->handle, aes_key_aligned, 16);
  205. if (status != kStatus_Success)
  206. status = WC_HW_E;
  207. else {
  208. if (iv)
  209. XMEMCPY(aes->reg, iv, 16);
  210. else
  211. XMEMSET(aes->reg, 0, 16);
  212. }
  213. dcp_unlock();
  214. return status;
  215. }
  216. int DCPAesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
  217. {
  218. int ret;
  219. if (sz % 16)
  220. return BAD_FUNC_ARG;
  221. dcp_lock();
  222. ret = DCP_AES_EncryptCbc(DCP, &aes->handle, in, out, sz, (const byte *)aes->reg);
  223. if (ret)
  224. ret = WC_HW_E;
  225. else
  226. XMEMCPY(aes->reg, out, AES_BLOCK_SIZE);
  227. dcp_unlock();
  228. return ret;
  229. }
  230. int DCPAesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
  231. {
  232. int ret;
  233. if (sz % 16)
  234. return BAD_FUNC_ARG;
  235. dcp_lock();
  236. ret = DCP_AES_DecryptCbc(DCP, &aes->handle, in, out, sz, (const byte *)aes->reg);
  237. if (ret)
  238. ret = WC_HW_E;
  239. else
  240. XMEMCPY(aes->reg, in, AES_BLOCK_SIZE);
  241. dcp_unlock();
  242. return ret;
  243. }
  244. int DCPAesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
  245. {
  246. int ret;
  247. if (sz % 16)
  248. return BAD_FUNC_ARG;
  249. dcp_lock();
  250. ret = DCP_AES_EncryptEcb(DCP, &aes->handle, in, out, sz);
  251. if (ret)
  252. ret = WC_HW_E;
  253. dcp_unlock();
  254. return ret;
  255. }
  256. int DCPAesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
  257. {
  258. int ret;
  259. if (sz % 16)
  260. return BAD_FUNC_ARG;
  261. dcp_lock();
  262. ret = DCP_AES_DecryptEcb(DCP, &aes->handle, in, out, sz);
  263. if (ret)
  264. ret = WC_HW_E;
  265. dcp_unlock();
  266. return ret;
  267. }
  268. #endif
  269. #ifndef NO_SHA256
  270. int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
  271. {
  272. int ret;
  273. int ch;
  274. int keyslot;
  275. if (sha256 == NULL)
  276. return BAD_FUNC_ARG;
  277. ch = dcp_get_channel();
  278. if (ch == 0)
  279. return WC_PENDING_E;
  280. keyslot = dcp_key_slot(ch);
  281. dcp_lock();
  282. (void)devId;
  283. XMEMSET(sha256, 0, sizeof(wc_Sha256));
  284. sha256->handle.channel = (dcp_channel_t)ch;
  285. sha256->handle.keySlot = (dcp_key_slot_t)keyslot;
  286. sha256->handle.swapConfig = kDCP_NoSwap;
  287. ret = DCP_HASH_Init(DCP, &sha256->handle, &sha256->ctx, kDCP_Sha256);
  288. if (ret != kStatus_Success)
  289. ret = WC_HW_E;
  290. dcp_unlock();
  291. return ret;
  292. }
  293. void DCPSha256Free(wc_Sha256* sha256)
  294. {
  295. if (sha256)
  296. dcp_free(sha256->handle.channel);
  297. }
  298. int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
  299. {
  300. int ret;
  301. if (sha256 == NULL || (data == NULL && len != 0)) {
  302. return BAD_FUNC_ARG;
  303. }
  304. dcp_lock();
  305. ret = DCP_HASH_Update(DCP, &sha256->ctx, data, len);
  306. if (ret != kStatus_Success)
  307. ret = WC_HW_E;
  308. dcp_unlock();
  309. return ret;
  310. }
  311. int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
  312. {
  313. int ret;
  314. size_t outlen = WC_SHA256_DIGEST_SIZE;
  315. dcp_hash_ctx_t saved_ctx;
  316. if (sha256 == NULL || hash == NULL)
  317. return BAD_FUNC_ARG;
  318. dcp_lock();
  319. XMEMCPY(&saved_ctx, &sha256->ctx, sizeof(dcp_hash_ctx_t));
  320. XMEMSET(hash, 0, WC_SHA256_DIGEST_SIZE);
  321. ret = DCP_HASH_Finish(DCP, &sha256->ctx, hash, &outlen);
  322. if ((ret != kStatus_Success) || (outlen != SHA256_DIGEST_SIZE))
  323. ret = WC_HW_E;
  324. else
  325. XMEMCPY(&sha256->ctx, &saved_ctx, sizeof(dcp_hash_ctx_t));
  326. dcp_unlock();
  327. return 0;
  328. }
  329. int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
  330. {
  331. int ret;
  332. size_t outlen = WC_SHA256_DIGEST_SIZE;
  333. dcp_lock();
  334. ret = DCP_HASH_Finish(DCP, &sha256->ctx, hash, &outlen);
  335. if ((ret != kStatus_Success) || (outlen != SHA256_DIGEST_SIZE))
  336. ret = WC_HW_E;
  337. else {
  338. ret = DCP_HASH_Init(DCP, &sha256->handle, &sha256->ctx, kDCP_Sha256);
  339. if (ret < 0)
  340. ret = WC_HW_E;
  341. }
  342. dcp_unlock();
  343. return ret;
  344. }
  345. #ifdef WOLFSSL_HASH_FLAGS
  346. int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags)
  347. {
  348. if (sha256) {
  349. sha256->flags = flags;
  350. }
  351. return 0;
  352. }
  353. int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags)
  354. {
  355. if (sha256 && flags) {
  356. *flags = sha256->flags;
  357. }
  358. return 0;
  359. }
  360. #endif /* WOLFSSL_HASH_FLAGS */
  361. int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
  362. {
  363. if (src == NULL || dst == NULL)
  364. return BAD_FUNC_ARG;
  365. dcp_lock();
  366. XMEMCPY(&dst->ctx, &src->ctx, sizeof(dcp_hash_ctx_t));
  367. dcp_unlock();
  368. return 0;
  369. }
  370. #endif /* !NO_SHA256 */
  371. #ifndef NO_SHA
  372. int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
  373. {
  374. int ret;
  375. int ch;
  376. int keyslot;
  377. if (sha == NULL)
  378. return BAD_FUNC_ARG;
  379. ch = dcp_get_channel();
  380. if (ch == 0)
  381. return WC_PENDING_E;
  382. keyslot = dcp_key_slot(ch);
  383. dcp_lock();
  384. (void)devId;
  385. XMEMSET(sha, 0, sizeof(wc_Sha));
  386. sha->handle.channel = (dcp_channel_t)ch;
  387. sha->handle.keySlot = (dcp_key_slot_t)keyslot;
  388. sha->handle.swapConfig = kDCP_NoSwap;
  389. ret = DCP_HASH_Init(DCP, &sha->handle, &sha->ctx, kDCP_Sha1);
  390. if (ret != kStatus_Success)
  391. ret = WC_HW_E;
  392. dcp_unlock();
  393. return ret;
  394. }
  395. void DCPShaFree(wc_Sha* sha)
  396. {
  397. if (sha)
  398. dcp_free(sha->handle.channel);
  399. }
  400. int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
  401. {
  402. int ret;
  403. if (sha == NULL || (data == NULL && len != 0)) {
  404. return BAD_FUNC_ARG;
  405. }
  406. dcp_lock();
  407. ret = DCP_HASH_Update(DCP, &sha->ctx, data, len);
  408. if (ret != kStatus_Success)
  409. ret = WC_HW_E;
  410. dcp_unlock();
  411. return ret;
  412. }
  413. int wc_ShaGetHash(wc_Sha* sha, byte* hash)
  414. {
  415. int ret;
  416. size_t outlen = WC_SHA_DIGEST_SIZE;
  417. dcp_hash_ctx_t saved_ctx;
  418. if (sha == NULL || hash == NULL)
  419. return BAD_FUNC_ARG;
  420. dcp_lock();
  421. XMEMCPY(&saved_ctx, &sha->ctx, sizeof(dcp_hash_ctx_t));
  422. XMEMSET(hash, 0, WC_SHA_DIGEST_SIZE);
  423. ret = DCP_HASH_Finish(DCP, &sha->ctx, hash, &outlen);
  424. if ((ret != kStatus_Success) || (outlen != WC_SHA_DIGEST_SIZE))
  425. ret = WC_HW_E;
  426. else
  427. XMEMCPY(&sha->ctx, &saved_ctx, sizeof(dcp_hash_ctx_t));
  428. dcp_unlock();
  429. return 0;
  430. }
  431. int wc_ShaFinal(wc_Sha* sha, byte* hash)
  432. {
  433. int ret;
  434. size_t outlen = WC_SHA_DIGEST_SIZE;
  435. dcp_lock();
  436. ret = DCP_HASH_Finish(DCP, &sha->ctx, hash, &outlen);
  437. if ((ret != kStatus_Success) || (outlen != SHA_DIGEST_SIZE)) {
  438. ret = WC_HW_E;
  439. } else {
  440. ret = DCP_HASH_Init(DCP, &sha->handle, &sha->ctx, kDCP_Sha1);
  441. if (ret < 0)
  442. ret = WC_HW_E;
  443. }
  444. dcp_unlock();
  445. return ret;
  446. }
  447. #ifdef WOLFSSL_HASH_FLAGS
  448. int wc_ShaSetFlags(wc_Sha* sha, word32 flags)
  449. {
  450. if (sha) {
  451. sha->flags = flags;
  452. }
  453. return 0;
  454. }
  455. int wc_ShaGetFlags(wc_Sha* sha, word32* flags)
  456. {
  457. if (sha && flags) {
  458. *flags = sha->flags;
  459. }
  460. return 0;
  461. }
  462. #endif /* WOLFSSL_HASH_FLAGS */
  463. int wc_ShaCopy(wc_Sha* src, wc_Sha* dst)
  464. {
  465. if (src == NULL || dst == NULL)
  466. return BAD_FUNC_ARG;
  467. dcp_lock();
  468. XMEMCPY(&dst->ctx, &src->ctx, sizeof(dcp_hash_ctx_t));
  469. dcp_unlock();
  470. return 0;
  471. }
  472. #endif /* !NO_SHA */
  473. #endif /* WOLFSSL_IMXRT_DCP */