cry.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /**
  2. * \file cry.c
  3. *
  4. * Interface implementation file for cryptographic functions that will be used
  5. * from other IP modules
  6. */
  7. /*
  8. * Copyright (C) 2013. Mindtree Limited.
  9. * All rights reserved.
  10. */
  11. /* --------------------------------------------- Header File Inclusion */
  12. #include "cry.h"
  13. #include "ll.h"
  14. /* Platform and Internal Crypto Includes */
  15. #include "aes_cmac.h"
  16. #include "crypto.h"
  17. /* Third Party Crypto Includes TODO: Temporary */
  18. #include "aes.h"
  19. #include "P256-cortex-ecdh.h"
  20. /* --------------------------------------------- Global Defines */
  21. /* --------------------------------------------- External Global Variables */
  22. /* --------------------------------------------- Exported Global Variables */
  23. /* --------------------------------------------- Static Global Variables */
  24. /** Context for AES-CMAC */
  25. DECL_STATIC AES_CMAC_CONTEXT cry_aescmac;
  26. #ifndef PHYPLUS_ECDH_ENABLE
  27. DECL_STATIC ssp_prkey_t cry_ecpvtkey;
  28. DECL_STATIC ssp_pukey_t cry_ecpubkey;
  29. DECL_STATIC ssp_pukey_t cry_prpubkey;
  30. DECL_STATIC ssp_dhkey_t cry_ecdhkey;
  31. DECL_STATIC void (*cry_ecdh_cb)(UCHAR *);
  32. #endif
  33. /* --------------------------------------------- Functions */
  34. void cry_reverse_bytestream_endianness(UCHAR * src, UCHAR * dst, UINT16 len)
  35. {
  36. UINT16 i;
  37. for (i = 0; i < len; i++)
  38. {
  39. dst[i] = src[(len - 1) - i];
  40. }
  41. }
  42. void cry_reverse_bytestream_in_place(UCHAR * src, UINT16 len)
  43. {
  44. UINT16 i;
  45. UCHAR temp;
  46. for (i = 0; i < len/2; i++)
  47. {
  48. temp = src[i];
  49. src[i] = src[(len - 1) - i];
  50. src[(len - 1) - i] = temp;
  51. }
  52. }
  53. INT32 cry_rand_generate(UCHAR * prand, UINT16 randlen)
  54. {
  55. LL_Rand(prand, randlen);
  56. return 0;
  57. }
  58. INT32 cry_aes_128_encrypt
  59. (
  60. UCHAR * pdata,
  61. UCHAR * pkey,
  62. UCHAR * pencdata
  63. )
  64. {
  65. LL_Encrypt (pkey, pdata, pencdata);
  66. return CRY_AES128_DATALEN;
  67. }
  68. INT32 cry_aes_128_decrypt
  69. (
  70. UCHAR * pencdata,
  71. UCHAR * pkey,
  72. UCHAR * pdata
  73. )
  74. {
  75. return -1;
  76. }
  77. INT32 cry_aes_128_ccm_encrypt
  78. (
  79. UCHAR * pkey,
  80. UCHAR * pnonce,
  81. UINT16 noncelen,
  82. UCHAR * pdata,
  83. UINT16 datalen,
  84. UCHAR * paddata,
  85. UINT16 addatalen,
  86. UCHAR * pencdata,
  87. UCHAR * pmac,
  88. UINT16 maclen
  89. )
  90. {
  91. UCHAR mac[CRY_AES128CMAC_MACLEN];
  92. INT32 ciphertext_len;
  93. int ret;
  94. (void)noncelen;
  95. /* Validate input length check */
  96. ciphertext_len = -1;
  97. ret = aes_ccm_ae
  98. (
  99. pkey,
  100. CRY_AES128_KEYLEN,
  101. pnonce,
  102. maclen,
  103. pdata,
  104. datalen,
  105. paddata,
  106. addatalen,
  107. pencdata,
  108. mac
  109. );
  110. /* TODO: Check if this is the success return */
  111. if (0 == ret)
  112. {
  113. ciphertext_len = datalen;
  114. if (NULL != pmac)
  115. {
  116. EM_mem_copy (pmac, mac, maclen);
  117. }
  118. }
  119. return ciphertext_len;
  120. }
  121. INT32 cry_aes_128_ccm_decrypt
  122. (
  123. UCHAR * pkey,
  124. UCHAR * pnonce,
  125. UINT16 noncelen,
  126. UCHAR * pencdata,
  127. UINT16 encdatalen,
  128. UCHAR * paddata,
  129. UINT16 addatalen,
  130. UCHAR * pdata,
  131. UCHAR * pmac,
  132. UINT16 maclen
  133. )
  134. {
  135. int plaintext_len;
  136. int ret;
  137. (void)noncelen;
  138. /* Validate input length check */
  139. plaintext_len = -1;
  140. ret = aes_ccm_ad
  141. (
  142. pkey,
  143. CRY_AES128_KEYLEN,
  144. pnonce,
  145. maclen,
  146. pencdata,
  147. encdatalen,
  148. paddata,
  149. addatalen,
  150. pmac,
  151. pdata
  152. );
  153. if (0 == ret)
  154. {
  155. plaintext_len = encdatalen;
  156. }
  157. return plaintext_len;
  158. }
  159. INT32 cry_aes_128_cmac
  160. (
  161. UCHAR op,
  162. UCHAR * pdata,
  163. UINT16 datalen,
  164. UCHAR * pkey,
  165. UCHAR * pmac,
  166. UINT16 maclen
  167. )
  168. {
  169. INT32 ret;
  170. UCHAR mac[CRY_AES128_KEYLEN];
  171. EM_RESULT retval;
  172. UCHAR lkey[CRY_AES128_KEYLEN];
  173. UCHAR * ldata;
  174. /* Allocate local data memory */
  175. ldata = EM_alloc_mem (datalen);
  176. if (NULL == ldata)
  177. {
  178. return -1;
  179. }
  180. /* Form the data for our required endianness */
  181. cry_reverse_bytestream_endianness (pdata, ldata, datalen);
  182. cry_reverse_bytestream_endianness (pkey, lkey, CRY_AES128_KEYLEN);
  183. /* Initialize the AES-CMAC context */
  184. aes_cmac_context_init (&cry_aescmac);
  185. ret = -1;
  186. /* Populate the context for operation */
  187. cry_aescmac.key = lkey;
  188. cry_aescmac.data = ldata;
  189. cry_aescmac.datalen = datalen;
  190. cry_aescmac.mac = mac;
  191. cry_aescmac.maclen = sizeof(mac);
  192. cry_aescmac.action = (CRY_AES_128_CMAC_SIGN == op)?
  193. AES_CMAC_MAC_GENERATE: AES_CMAC_MAC_VERIFY;
  194. /* Call to perform the operation */
  195. retval = aes_cmac (&cry_aescmac);
  196. if (EM_SUCCESS == retval)
  197. {
  198. ret = 0;
  199. /* Get back the input endianness */
  200. cry_reverse_bytestream_in_place (mac, CRY_AES128_KEYLEN);
  201. if (CRY_AES_128_CMAC_SIGN == op)
  202. {
  203. EM_mem_copy(pmac, mac, maclen);
  204. }
  205. else if (CRY_AES_128_CMAC_VERIFY == op)
  206. {
  207. if (0 != EM_mem_cmp(pmac, mac, maclen))
  208. {
  209. ret = -1;
  210. }
  211. }
  212. }
  213. /* Free the local data memory allocated */
  214. EM_free_mem (ldata);
  215. return ret;
  216. }
  217. INT32 cry_ecdh_init(void)
  218. {
  219. #ifdef PHYPLUS_ECDH_ENABLE
  220. return (phyplus_ecdh_init());
  221. #else
  222. UINT8 ret;
  223. ssp_init();
  224. do
  225. {
  226. ret = ssp_get_ecdh_keypair(&cry_ecpvtkey, &cry_ecpubkey);
  227. }while (0 == ret);
  228. ssp_shutdown();
  229. return 0;
  230. #endif
  231. }
  232. INT32 cry_ecdh_get_public_key(UCHAR * pubkey)
  233. {
  234. #ifdef PHYPLUS_ECDH_ENABLE
  235. return (phyplus_ecdh_get_public_key(pubkey));
  236. #else
  237. /* TODO: Check Endianness */
  238. cry_reverse_bytestream_endianness(cry_ecpubkey.x, pubkey, DHKEY_LEN);
  239. cry_reverse_bytestream_endianness(cry_ecpubkey.y, (pubkey + DHKEY_LEN), DHKEY_LEN);
  240. return 0;
  241. #endif
  242. }
  243. INT32 cry_ecdh_generate_secret
  244. (
  245. UCHAR * peer_pubkey,
  246. UCHAR * secret,
  247. UINT16 secret_len,
  248. void (*ecdh_cb)(UCHAR *)
  249. )
  250. {
  251. #ifdef PHYPLUS_ECDH_ENABLE
  252. return (phyplus_ecdh_generate_secret(peer_pubkey,secret,secret_len));
  253. #else
  254. UINT8 ret;
  255. INT32 retval;
  256. #ifdef CRY_ECDH_TIMESLICE
  257. /* Validate if block is idle */
  258. if (NULL != cry_ecdh_cb)
  259. {
  260. return -1;
  261. }
  262. #endif /* CRY_ECDH_TIMESLICE */
  263. /* Reverse Endianness */
  264. cry_reverse_bytestream_endianness(peer_pubkey, cry_prpubkey.x, DHKEY_LEN);
  265. cry_reverse_bytestream_endianness((peer_pubkey + DHKEY_LEN), cry_prpubkey.y, DHKEY_LEN);
  266. ssp_init();
  267. #ifndef CRY_ECDH_TIMESLICE
  268. do {
  269. #endif /* CRY_ECDH_TIMESLICE */
  270. ret = ssp_get_dhkey
  271. (
  272. &cry_ecpvtkey,
  273. &cry_prpubkey,
  274. &cry_ecdhkey
  275. );
  276. #ifndef CRY_ECDH_TIMESLICE
  277. } while (0 == ret);
  278. #endif /* CRY_ECDH_TIMESLICE */
  279. /* Check if valid dhkey */
  280. if (2 == ret)
  281. {
  282. /* Invalid DHKey. Return Failure */
  283. retval = -1;
  284. }
  285. #ifdef CRY_ECDH_TIMESLICE
  286. else if (0 == ret)
  287. {
  288. if (NULL == ecdh_cb)
  289. {
  290. /* Procedure cannot be completed */
  291. retval = -2;
  292. }
  293. else
  294. {
  295. /* Save the callback */
  296. cry_ecdh_cb = ecdh_cb;
  297. /* DHKey calculation pending. */
  298. retval = 1;
  299. /* Schedule at platform for sliced processing */
  300. BLE_ecdh_yield();
  301. }
  302. }
  303. #endif /* CRY_ECDH_TIMESLICE */
  304. else
  305. {
  306. /* Reverse Endianness */
  307. cry_reverse_bytestream_endianness(cry_ecdhkey, secret, DHKEY_LEN);
  308. ssp_shutdown();
  309. /* Valid DHKey. Return Success */
  310. retval = 0;
  311. }
  312. return retval;
  313. #endif
  314. }
  315. #ifdef CRY_ECDH_TIMESLICE
  316. INT32 cry_ecdh_process_secret(void)
  317. {
  318. UCHAR secret[DHKEY_LEN];
  319. UINT8 ret;
  320. INT32 retval;
  321. void (*ecdh_cb)(UCHAR *);
  322. /* Validate if block is idle */
  323. if (NULL == cry_ecdh_cb)
  324. {
  325. return -1;
  326. }
  327. ret = ssp_get_dhkey
  328. (
  329. &cry_ecpvtkey,
  330. &cry_prpubkey,
  331. &cry_ecdhkey
  332. );
  333. if (0 == ret)
  334. {
  335. /* DHKey calculation pending. */
  336. retval = 1;
  337. /* Schedule at platform for sliced processing */
  338. BLE_ecdh_yield();
  339. }
  340. else
  341. {
  342. /* Reverse Endianness */
  343. cry_reverse_bytestream_endianness(cry_ecdhkey, secret, DHKEY_LEN);
  344. ssp_shutdown();
  345. /* Valid DHKey. Return Success */
  346. retval = 0;
  347. /* Invoke the corresponding callback */
  348. ecdh_cb = cry_ecdh_cb;
  349. cry_ecdh_cb = NULL;
  350. ecdh_cb (secret);
  351. }
  352. return retval;
  353. }
  354. #endif /* CRY_ECDH_TIMESLICE */
  355. INT32 cry_set_ecdh_debug_keypair(UCHAR * pvtkey, UCHAR * pubkey)
  356. {
  357. (void)pvtkey;
  358. (void)pubkey;
  359. return -1;
  360. }
  361. #define PHY_PLUS_ECDH_KEYGEN_RETRY_LIMT 64
  362. int cry_generate_random_bytes(uint8 *p, uint32_t size)
  363. {
  364. LL_Rand(p,(uint8)size);
  365. return 0;
  366. }
  367. DECL_STATIC ssp_prkey_t phy_ecpvtkey;
  368. DECL_STATIC ssp_pukey_t phy_ecpubkey;
  369. DECL_STATIC uCrypto_RNG_Function g_rng_function = 0;
  370. void uCrypto_set_rng(uCrypto_RNG_Function rng_function)
  371. {
  372. g_rng_function = rng_function;
  373. }
  374. uCrypto_RNG_Function uCrypto_get_rng(void)
  375. {
  376. return g_rng_function;
  377. }
  378. INT32 phyplus_ecdh_init(void)
  379. {
  380. // uint32 T1;
  381. uint8 my_public_point0[64], my_private_key0[32];
  382. uint32 cnt=0;
  383. uCrypto_RNG_Function gen_rng;
  384. if(uCrypto_get_rng()==0)
  385. uCrypto_set_rng(cry_generate_random_bytes);
  386. gen_rng =uCrypto_get_rng();
  387. do {
  388. gen_rng(my_public_point0, 32);
  389. if(++cnt>PHY_PLUS_ECDH_KEYGEN_RETRY_LIMT)
  390. return cnt;
  391. } while (!P256_ecdh_keygen(my_public_point0, my_private_key0));
  392. //
  393. EM_mem_copy(phy_ecpvtkey,my_private_key0,DHKEY_LEN);
  394. EM_mem_copy(phy_ecpubkey.x,my_public_point0,DHKEY_LEN);
  395. EM_mem_copy(phy_ecpubkey.y,my_public_point0+DHKEY_LEN,DHKEY_LEN);
  396. // cry_reverse_bytestream_endianness(my_private_key0,cry_ecpvtkey,DHKEY_LEN);
  397. //
  398. // cry_reverse_bytestream_endianness(my_public_point0,cry_ecpubkey.x,DHKEY_LEN);
  399. // cry_reverse_bytestream_endianness(my_public_point0+DHKEY_LEN,cry_ecpubkey.y,DHKEY_LEN);
  400. return 0;
  401. }
  402. INT32 phyplus_ecdh_generate_secret(UCHAR * peer_pubkey, UCHAR * secret, UINT16 secret_len)
  403. {
  404. uint8 pubkey[64];
  405. uint8 dhkey[32];
  406. /* TODO: Check Endianness */
  407. cry_reverse_bytestream_endianness(peer_pubkey, pubkey, DHKEY_LEN);
  408. cry_reverse_bytestream_endianness((peer_pubkey + DHKEY_LEN), (pubkey+DHKEY_LEN), DHKEY_LEN);
  409. if (!P256_ecdh_shared_secret(dhkey, pubkey, phy_ecpvtkey))
  410. {
  411. // The other part sent an invalid public point, so abort
  412. return 1;
  413. }
  414. else
  415. {
  416. cry_reverse_bytestream_endianness(dhkey, secret, DHKEY_LEN);
  417. // The shared_secret is now the same for both parts and may be used for cryptographic purposes
  418. return 0;
  419. }
  420. }
  421. INT32 phyplus_ecdh_get_public_key(UCHAR * pubkey)
  422. {
  423. /* TODO: Check Endianness */
  424. cry_reverse_bytestream_endianness(phy_ecpubkey.x, pubkey, DHKEY_LEN);
  425. cry_reverse_bytestream_endianness(phy_ecpubkey.y, (pubkey + DHKEY_LEN), DHKEY_LEN);
  426. // EM_mem_copy(pubkey, phy_ecpubkey.x,DHKEY_LEN);
  427. // EM_mem_copy(pubkey+DHKEY_LEN,phy_ecpubkey.y,DHKEY_LEN);
  428. return 0;
  429. }
  430. //#define cry_dump_key(a,b,c) do{cry_printf(a);for(int i=0;i<b;i++){cry_printf("%02x ",c[i]);}cry_printf("\n");}while(0)
  431. #if 0
  432. void test_verify_phyplus_ecdh(void)
  433. {
  434. UCHAR pubkey0[64];
  435. UCHAR pubkey1[64];
  436. UCHAR pubKeyT[64];
  437. UCHAR sec0[32];
  438. UCHAR sec1[32];
  439. int ret;
  440. ret=cry_ecdh_init();
  441. //cry_printf(" cry ini %d\n",ret);
  442. ret=phyplus_ecdh_init();
  443. //cry_printf(" phy ini %d\n",ret);
  444. ret=cry_ecdh_get_public_key(pubKeyT);
  445. cry_reverse_bytestream_endianness(pubKeyT,pubkey0,DHKEY_LEN);
  446. cry_reverse_bytestream_endianness(pubKeyT+DHKEY_LEN,pubkey0+DHKEY_LEN,DHKEY_LEN);
  447. ret=phyplus_ecdh_get_public_key(pubKeyT);
  448. cry_reverse_bytestream_endianness(pubKeyT,pubkey1,DHKEY_LEN);
  449. cry_reverse_bytestream_endianness(pubKeyT+DHKEY_LEN,pubkey1+DHKEY_LEN,DHKEY_LEN);
  450. ret=cry_ecdh_generate_secret(pubkey1, sec0, 32, NULL);
  451. //cry_printf(" cry sec %d\n",ret);
  452. ret=phyplus_ecdh_generate_secret(pubkey0, sec1, 32);
  453. //cry_printf(" phy sec %d\n",ret);
  454. // cry_dump_key("[cry_pvt]\n",32,cry_ecpvtkey);
  455. // cry_dump_key("[cry_pub_x]\n",32,cry_ecpubkey.x);
  456. // cry_dump_key("[cry_pub_y]\n",32,cry_ecpubkey.y);
  457. //
  458. // cry_dump_key("[phy_pvt]\n",32,phy_ecpvtkey);
  459. // cry_dump_key("[phy_pub_x]\n",32,phy_ecpubkey.x);
  460. // cry_dump_key("[phy_pub_y]\n",32,phy_ecpubkey.y);
  461. //
  462. // cry_dump_key("[pubKey0]\n",64,pubkey0);
  463. // cry_dump_key("[pubKey1]\n",64,pubkey1);
  464. //
  465. // cry_dump_key("[sec0]\n",32,sec0);
  466. // cry_dump_key("[sec1]\n",32,sec1);
  467. // cry_printf("[sec0] \n");
  468. // for(int i=0;i<DHKEY_LEN;i++)
  469. // {
  470. // cry_printf("%02x ",sec0[i]);
  471. // }
  472. // cry_printf("[sec1] \n");
  473. // for(int i=0;i<DHKEY_LEN;i++)
  474. // {
  475. // cry_printf("%02x ",sec1[i]);
  476. // }
  477. }
  478. #endif