sample_libcrypto.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. /*
  2. * Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. /*
  32. * This sample cryptopgraphy library was intended to be used in a limited
  33. * manner. Its cryptographic strength is very weak. It should not be
  34. * used by any production code. Its scope is limited to assist in the
  35. * development of the remote attestation sample application.
  36. **/
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <stdint.h>
  40. #include "ippcp.h"
  41. #include "sgx_memset_s.h"
  42. #include "se_memcpy.h"
  43. #include "sample_libcrypto.h"
  44. #include <errno.h>
  45. #ifdef __linux__
  46. /*
  47. * __memset_vp is a volatile pointer to a function.
  48. * It is initialised to point to memset, and should never be changed.
  49. */
  50. static void * (* const volatile __memset_vp)(void *, int, size_t)
  51. = (memset);
  52. #undef memset_s /* in case it was defined as a macro */
  53. extern "C" int memset_s(void *s, size_t smax, int c, size_t n)
  54. {
  55. int err = 0;
  56. if (s == NULL) {
  57. err = EINVAL;
  58. goto out;
  59. }
  60. if (n > smax) {
  61. err = EOVERFLOW;
  62. n = smax;
  63. }
  64. /* Calling through a volatile pointer should never be optimised away. */
  65. (*__memset_vp)(s, c, n);
  66. out:
  67. if (err == 0)
  68. return 0;
  69. else {
  70. errno = err;
  71. /* XXX call runtime-constraint handler */
  72. return err;
  73. }
  74. }
  75. #endif
  76. #ifndef ERROR_BREAK
  77. #define ERROR_BREAK(x) if(x){break;}
  78. #endif
  79. #ifndef SAFE_FREE
  80. #define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr) = NULL;}}
  81. #endif
  82. #ifndef ROUND_TO
  83. #define ROUND_TO(x, align) (((x) + (align-1)) & ~(align-1))
  84. #endif
  85. #ifndef UNUSED
  86. #define UNUSED(val) (void)(val)
  87. #endif
  88. // We are using this very non-random definition for reproducibility / debugging purposes.
  89. static uint32_t seed = (uint32_t)(9);
  90. static inline sample_status_t __do_get_rand32(uint32_t* rand_num)
  91. {
  92. // A better source of entropy would be the "time" function or something like that
  93. *rand_num = seed;
  94. return SAMPLE_SUCCESS;
  95. }
  96. static inline IppStatus check_copy_size(size_t target_size, size_t source_size)
  97. {
  98. if(target_size < source_size)
  99. return ippStsSizeErr;
  100. return ippStsNoErr;
  101. }
  102. /* The function should generate a random number properly, and the pseudo-rand
  103. implementation is only for demo purpose. */
  104. sample_status_t sample_read_rand(unsigned char *rand, size_t length_in_bytes)
  105. {
  106. // check parameters
  107. if(!rand || !length_in_bytes)
  108. {
  109. return SAMPLE_ERROR_INVALID_PARAMETER;
  110. }
  111. // loop to rdrand
  112. while(length_in_bytes > 0)
  113. {
  114. uint32_t rand_num = 0;
  115. sample_status_t status = __do_get_rand32(&rand_num);
  116. if(status != SAMPLE_SUCCESS)
  117. {
  118. return status;
  119. }
  120. size_t size = (length_in_bytes < sizeof(rand_num))
  121. ? length_in_bytes : sizeof(rand_num);
  122. if(memcpy_s(rand, size, &rand_num, size))
  123. {
  124. return status;
  125. }
  126. rand += size;
  127. length_in_bytes -= size;
  128. }
  129. return SAMPLE_SUCCESS;
  130. }
  131. static IppStatus sgx_ipp_newBN(const Ipp32u *p_data, int size_in_bytes, IppsBigNumState **p_new_BN)
  132. {
  133. IppsBigNumState *pBN=0;
  134. int bn_size = 0;
  135. if(p_new_BN == NULL || (size_in_bytes <= 0) || ((size_in_bytes % sizeof(Ipp32u)) != 0))
  136. return ippStsBadArgErr;
  137. // Get the size of the IppsBigNumState context in bytes
  138. IppStatus error_code = ippsBigNumGetSize(size_in_bytes/(int)sizeof(Ipp32u), &bn_size);
  139. if(error_code != ippStsNoErr)
  140. {
  141. *p_new_BN = 0;
  142. return error_code;
  143. }
  144. pBN = (IppsBigNumState *) malloc(bn_size);
  145. if(!pBN)
  146. {
  147. error_code = ippStsMemAllocErr;
  148. *p_new_BN = 0;
  149. return error_code;
  150. }
  151. // Initialize context and partition allocated buffer
  152. error_code = ippsBigNumInit(size_in_bytes/(int)sizeof(Ipp32u), pBN);
  153. if(error_code != ippStsNoErr)
  154. {
  155. free(pBN);
  156. *p_new_BN = 0;
  157. return error_code;
  158. }
  159. if(p_data)
  160. {
  161. error_code = ippsSet_BN(IppsBigNumPOS, size_in_bytes/(int)sizeof(Ipp32u), p_data, pBN);
  162. if(error_code != ippStsNoErr)
  163. {
  164. *p_new_BN = 0;
  165. free(pBN);
  166. return error_code;
  167. }
  168. }
  169. *p_new_BN = pBN;
  170. return error_code;
  171. }
  172. static void sample_ipp_secure_free_BN(IppsBigNumState *pBN, int size_in_bytes)
  173. {
  174. if(pBN == NULL || size_in_bytes <= 0 || size_in_bytes/sizeof(Ipp32u) <= 0)
  175. {
  176. if(pBN)
  177. {
  178. free(pBN);
  179. }
  180. return;
  181. }
  182. int bn_size = 0;
  183. // Get the size of the IppsBigNumState context in bytes
  184. // Since we have checked the size_in_bytes before and the &bn_size is not NULL, ippsBigNumGetSize never returns failure
  185. ippsBigNumGetSize(size_in_bytes/(int)sizeof(Ipp32u), &bn_size);
  186. if (bn_size <= 0)
  187. {
  188. free(pBN);
  189. return;
  190. }
  191. // Clear the buffer before free.
  192. memset_s(pBN, bn_size, 0, bn_size);
  193. free(pBN);
  194. return;
  195. }
  196. IppStatus __STDCALL sample_ipp_DRNGen(Ipp32u* pRandBNU, int nBits, void* pCtx_unused)
  197. {
  198. sample_status_t sample_ret;
  199. UNUSED(pCtx_unused);
  200. if(0 != nBits%8)
  201. {
  202. // Must be byte aligned
  203. return ippStsSizeErr;
  204. }
  205. if(!pRandBNU)
  206. {
  207. return ippStsNullPtrErr;
  208. }
  209. sample_ret = sample_read_rand((uint8_t*)pRandBNU, (uint32_t)nBits/8);
  210. if(SAMPLE_SUCCESS != sample_ret)
  211. {
  212. return ippStsErr;
  213. }
  214. return ippStsNoErr;
  215. }
  216. /* Rijndael AES-GCM
  217. * Parameters:
  218. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  219. * Inputs: sample_aes_gcm_128bit_key_t *p_key - Pointer to key used in encryption/decryption operation
  220. * uint8_t *p_src - Pointer to input stream to be encrypted/decrypted
  221. * uint32_t src_len - Length of input stream to be encrypted/decrypted
  222. * uint8_t *p_iv - Pointer to initialization vector to use
  223. * uint32_t iv_len - Length of initialization vector
  224. * uint8_t *p_aad - Pointer to input stream of additional authentication data
  225. * uint32_t aad_len - Length of additional authentication data stream
  226. * sample_aes_gcm_128bit_tag_t *p_in_mac - Pointer to expected MAC in decryption process
  227. * Output: uint8_t *p_dst - Pointer to cipher text. Size of buffer should be >= src_len.
  228. * sample_aes_gcm_128bit_tag_t *p_out_mac - Pointer to MAC generated from encryption process
  229. * NOTE: Wrapper is responsible for confirming decryption tag matches encryption tag */
  230. sample_status_t sample_rijndael128GCM_encrypt(const sample_aes_gcm_128bit_key_t *p_key, const uint8_t *p_src, uint32_t src_len,
  231. uint8_t *p_dst, const uint8_t *p_iv, uint32_t iv_len, const uint8_t *p_aad, uint32_t aad_len,
  232. sample_aes_gcm_128bit_tag_t *p_out_mac)
  233. {
  234. IppStatus error_code = ippStsNoErr;
  235. IppsAES_GCMState* pState = NULL;
  236. int ippStateSize = 0;
  237. if ((p_key == NULL) || ((src_len > 0) && (p_dst == NULL)) || ((src_len > 0) && (p_src == NULL))
  238. || (p_out_mac == NULL) || (iv_len != SAMPLE_AESGCM_IV_SIZE) || ((aad_len > 0) && (p_aad == NULL))
  239. || (p_iv == NULL) || ((p_src == NULL) && (p_aad == NULL)))
  240. {
  241. return SAMPLE_ERROR_INVALID_PARAMETER;
  242. }
  243. error_code = ippsAES_GCMGetSize(&ippStateSize);
  244. if (error_code != ippStsNoErr)
  245. {
  246. return SAMPLE_ERROR_UNEXPECTED;
  247. }
  248. pState = (IppsAES_GCMState*)malloc(ippStateSize);
  249. if(pState == NULL)
  250. {
  251. return SAMPLE_ERROR_OUT_OF_MEMORY;
  252. }
  253. error_code = ippsAES_GCMInit((const Ipp8u *)p_key, SAMPLE_AESGCM_KEY_SIZE, pState, ippStateSize);
  254. if (error_code != ippStsNoErr)
  255. {
  256. // Clear temp State before free.
  257. memset_s(pState, ippStateSize, 0, ippStateSize);
  258. free(pState);
  259. switch (error_code)
  260. {
  261. case ippStsMemAllocErr: return SAMPLE_ERROR_OUT_OF_MEMORY;
  262. case ippStsNullPtrErr:
  263. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  264. default: return SAMPLE_ERROR_UNEXPECTED;
  265. }
  266. }
  267. error_code = ippsAES_GCMStart(p_iv, SAMPLE_AESGCM_IV_SIZE, p_aad, aad_len, pState);
  268. if (error_code != ippStsNoErr)
  269. {
  270. // Clear temp State before free.
  271. memset_s(pState, ippStateSize, 0, ippStateSize);
  272. free(pState);
  273. switch (error_code)
  274. {
  275. case ippStsNullPtrErr:
  276. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  277. default: return SAMPLE_ERROR_UNEXPECTED;
  278. }
  279. }
  280. if (src_len > 0) {
  281. error_code = ippsAES_GCMEncrypt(p_src, p_dst, src_len, pState);
  282. if (error_code != ippStsNoErr)
  283. {
  284. // Clear temp State before free.
  285. memset_s(pState, ippStateSize, 0, ippStateSize);
  286. free(pState);
  287. switch (error_code)
  288. {
  289. case ippStsNullPtrErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  290. default: return SAMPLE_ERROR_UNEXPECTED;
  291. }
  292. }
  293. }
  294. error_code = ippsAES_GCMGetTag((Ipp8u *)p_out_mac, SAMPLE_AESGCM_MAC_SIZE, pState);
  295. if (error_code != ippStsNoErr)
  296. {
  297. // Clear temp State before free.
  298. memset_s(pState, ippStateSize, 0, ippStateSize);
  299. free(pState);
  300. switch (error_code)
  301. {
  302. case ippStsNullPtrErr:
  303. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  304. default: return SAMPLE_ERROR_UNEXPECTED;
  305. }
  306. }
  307. // Clear temp State before free.
  308. memset_s(pState, ippStateSize, 0, ippStateSize);
  309. free(pState);
  310. return SAMPLE_SUCCESS;
  311. }
  312. /* Message Authentication - Rijndael 128 CMAC
  313. * Parameters:
  314. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  315. * Inputs: sample_cmac_128bit_key_t *p_key - Pointer to key used in encryption/decryption operation
  316. * uint8_t *p_src - Pointer to input stream to be MACed
  317. * uint32_t src_len - Length of input stream to be MACed
  318. * Output: sample_cmac_gcm_128bit_tag_t *p_mac - Pointer to resultant MAC */
  319. sample_status_t sample_rijndael128_cmac_msg(const sample_cmac_128bit_key_t *p_key, const uint8_t *p_src,
  320. uint32_t src_len, sample_cmac_128bit_tag_t *p_mac)
  321. {
  322. IppsAES_CMACState* pState = NULL;
  323. int ippStateSize = 0;
  324. IppStatus error_code = ippStsNoErr;
  325. if ((p_key == NULL) || (p_src == NULL) || (p_mac == NULL))
  326. {
  327. return SAMPLE_ERROR_INVALID_PARAMETER;
  328. }
  329. error_code = ippsAES_CMACGetSize(&ippStateSize);
  330. if (error_code != ippStsNoErr)
  331. {
  332. return SAMPLE_ERROR_UNEXPECTED;
  333. }
  334. pState = (IppsAES_CMACState*)malloc(ippStateSize);
  335. if(pState == NULL)
  336. {
  337. return SAMPLE_ERROR_OUT_OF_MEMORY;
  338. }
  339. error_code = ippsAES_CMACInit((const Ipp8u *)p_key, SAMPLE_CMAC_KEY_SIZE, pState, ippStateSize);
  340. if (error_code != ippStsNoErr)
  341. {
  342. // Clear temp State before free.
  343. memset_s(pState, ippStateSize, 0, ippStateSize);
  344. free(pState);
  345. switch (error_code)
  346. {
  347. case ippStsMemAllocErr: return SAMPLE_ERROR_OUT_OF_MEMORY;
  348. case ippStsNullPtrErr:
  349. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  350. default: return SAMPLE_ERROR_UNEXPECTED;
  351. }
  352. }
  353. error_code = ippsAES_CMACUpdate((const Ipp8u *)p_src, src_len, pState);
  354. if (error_code != ippStsNoErr)
  355. {
  356. // Clear temp State before free.
  357. memset_s(pState, ippStateSize, 0, ippStateSize);
  358. free(pState);
  359. switch (error_code)
  360. {
  361. case ippStsNullPtrErr:
  362. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  363. default: return SAMPLE_ERROR_UNEXPECTED;
  364. }
  365. }
  366. error_code = ippsAES_CMACFinal((Ipp8u *)p_mac, SAMPLE_CMAC_MAC_SIZE, pState);
  367. if (error_code != ippStsNoErr)
  368. {
  369. // Clear temp State before free.
  370. memset_s(pState, ippStateSize, 0, ippStateSize);
  371. free(pState);
  372. switch (error_code)
  373. {
  374. case ippStsNullPtrErr:
  375. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  376. default: return SAMPLE_ERROR_UNEXPECTED;
  377. }
  378. }
  379. // Clear temp State before free.
  380. memset_s(pState, ippStateSize, 0, ippStateSize);
  381. free(pState);
  382. return SAMPLE_SUCCESS;
  383. }
  384. extern "C" int some_function()
  385. {
  386. return 1234;
  387. }
  388. /*
  389. * Elliptic Curve Crytpography - Based on GF(p), 256 bit
  390. */
  391. /* Allocates and initializes ecc context
  392. * Parameters:
  393. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  394. * Output: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system */
  395. sample_status_t sample_ecc256_open_context(sample_ecc_state_handle_t* ecc_handle)
  396. {
  397. IppStatus ipp_ret = ippStsNoErr;
  398. IppsECCPState* p_ecc_state = NULL;
  399. // default use 256r1 parameter
  400. int ctx_size = 0;
  401. if (ecc_handle == NULL)
  402. return SAMPLE_ERROR_INVALID_PARAMETER;
  403. ipp_ret = ippsECCPGetSize(256, &ctx_size);
  404. if (ipp_ret != ippStsNoErr)
  405. return SAMPLE_ERROR_UNEXPECTED;
  406. p_ecc_state = (IppsECCPState*)(malloc(ctx_size));
  407. if (p_ecc_state == NULL)
  408. return SAMPLE_ERROR_OUT_OF_MEMORY;
  409. ipp_ret = ippsECCPInit(256, p_ecc_state);
  410. if (ipp_ret != ippStsNoErr)
  411. {
  412. SAFE_FREE(p_ecc_state);
  413. *ecc_handle = NULL;
  414. return SAMPLE_ERROR_UNEXPECTED;
  415. }
  416. ipp_ret = ippsECCPSetStd(IppECCPStd256r1, p_ecc_state);
  417. if (ipp_ret != ippStsNoErr)
  418. {
  419. SAFE_FREE(p_ecc_state);
  420. *ecc_handle = NULL;
  421. return SAMPLE_ERROR_UNEXPECTED;
  422. }
  423. *ecc_handle = p_ecc_state;
  424. return SAMPLE_SUCCESS;
  425. }
  426. /* Cleans up ecc context
  427. * Parameters:
  428. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  429. * Output: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system */
  430. sample_status_t sample_ecc256_close_context(sample_ecc_state_handle_t ecc_handle)
  431. {
  432. if (ecc_handle == NULL)
  433. {
  434. return SAMPLE_ERROR_INVALID_PARAMETER;
  435. }
  436. IppsECCPState* p_ecc_state = (IppsECCPState*)ecc_handle;
  437. int ctx_size = 0;
  438. IppStatus ipp_ret = ippsECCPGetSize(256, &ctx_size);
  439. if (ipp_ret != ippStsNoErr)
  440. {
  441. free(p_ecc_state);
  442. return SAMPLE_SUCCESS;
  443. }
  444. memset_s(p_ecc_state, ctx_size, 0, ctx_size);
  445. free(p_ecc_state);
  446. return SAMPLE_SUCCESS;
  447. }
  448. /* Populates private/public key pair - caller code allocates memory
  449. * Parameters:
  450. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  451. * Inputs: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system
  452. * Outputs: sample_ec256_private_t *p_private - Pointer to the private key
  453. * sample_ec256_public_t *p_public - Pointer to the public key */
  454. sample_status_t sample_ecc256_create_key_pair(sample_ec256_private_t *p_private,
  455. sample_ec256_public_t *p_public,
  456. sample_ecc_state_handle_t ecc_handle)
  457. {
  458. if ((ecc_handle == NULL) || (p_private == NULL) || (p_public == NULL))
  459. {
  460. return SAMPLE_ERROR_INVALID_PARAMETER;
  461. }
  462. IppsBigNumState* dh_priv_BN = NULL;
  463. IppsECCPPointState* point_pub = NULL;
  464. IppsBigNumState* pub_gx = NULL;
  465. IppsBigNumState* pub_gy = NULL;
  466. IppStatus ipp_ret = ippStsNoErr;
  467. int ecPointSize = 0;
  468. IppsECCPState* p_ecc_state = (IppsECCPState*)ecc_handle;
  469. do
  470. {
  471. //init eccp point
  472. ipp_ret = ippsECCPPointGetSize(256, &ecPointSize);
  473. ERROR_BREAK(ipp_ret);
  474. point_pub = (IppsECCPPointState*)( malloc(ecPointSize) );
  475. if(!point_pub)
  476. {
  477. ipp_ret = ippStsNoMemErr;
  478. break;
  479. }
  480. ipp_ret = ippsECCPPointInit(256, point_pub);
  481. ERROR_BREAK(ipp_ret);
  482. ipp_ret = sgx_ipp_newBN(NULL, SAMPLE_ECP256_KEY_SIZE, &dh_priv_BN);
  483. ERROR_BREAK(ipp_ret);
  484. // Use the true random number (DRNG)
  485. ipp_ret = ippsECCPGenKeyPair(dh_priv_BN, point_pub, p_ecc_state, (IppBitSupplier)sample_ipp_DRNGen, NULL);
  486. ERROR_BREAK(ipp_ret);
  487. //convert point_result to oct string
  488. ipp_ret = sgx_ipp_newBN(NULL, SAMPLE_ECP256_KEY_SIZE, &pub_gx);
  489. ERROR_BREAK(ipp_ret);
  490. ipp_ret = sgx_ipp_newBN(NULL, SAMPLE_ECP256_KEY_SIZE, &pub_gy);
  491. ERROR_BREAK(ipp_ret);
  492. ipp_ret = ippsECCPGetPoint(pub_gx, pub_gy, point_pub, p_ecc_state);
  493. ERROR_BREAK(ipp_ret);
  494. IppsBigNumSGN sgn = IppsBigNumPOS;
  495. Ipp32u *pdata = NULL;
  496. // ippsRef_BN is in bits not bytes (versus old ippsGet_BN)
  497. int length = 0;
  498. ipp_ret = ippsRef_BN(&sgn, &length, &pdata, pub_gx);
  499. ERROR_BREAK(ipp_ret);
  500. memset(p_public->gx, 0, sizeof(p_public->gx));
  501. ipp_ret = check_copy_size(sizeof(p_public->gx), ROUND_TO(length, 8)/8);
  502. ERROR_BREAK(ipp_ret);
  503. memcpy(p_public->gx, pdata, ROUND_TO(length, 8)/8);
  504. ipp_ret = ippsRef_BN(&sgn, &length, &pdata, pub_gy);
  505. ERROR_BREAK(ipp_ret);
  506. memset(p_public->gy, 0, sizeof(p_public->gy));
  507. ipp_ret = check_copy_size(sizeof(p_public->gy), ROUND_TO(length, 8)/8);
  508. ERROR_BREAK(ipp_ret);
  509. memcpy(p_public->gy, pdata, ROUND_TO(length, 8)/8);
  510. ipp_ret = ippsRef_BN(&sgn, &length, &pdata, dh_priv_BN);
  511. ERROR_BREAK(ipp_ret);
  512. memset(p_private->r, 0, sizeof(p_private->r));
  513. ipp_ret = check_copy_size(sizeof(p_private->r), ROUND_TO(length, 8)/8);
  514. ERROR_BREAK(ipp_ret);
  515. memcpy(p_private->r, pdata, ROUND_TO(length, 8)/8);
  516. }while(0);
  517. //Clear temp buffer before free.
  518. if(point_pub) memset_s(point_pub, ecPointSize, 0, ecPointSize);
  519. SAFE_FREE(point_pub);
  520. sample_ipp_secure_free_BN(pub_gx, SAMPLE_ECP256_KEY_SIZE);
  521. sample_ipp_secure_free_BN(pub_gy, SAMPLE_ECP256_KEY_SIZE);
  522. sample_ipp_secure_free_BN(dh_priv_BN, SAMPLE_ECP256_KEY_SIZE);
  523. switch (ipp_ret)
  524. {
  525. case ippStsNoErr: return SAMPLE_SUCCESS;
  526. case ippStsNoMemErr:
  527. case ippStsMemAllocErr: return SAMPLE_ERROR_OUT_OF_MEMORY;
  528. case ippStsNullPtrErr:
  529. case ippStsLengthErr:
  530. case ippStsOutOfRangeErr:
  531. case ippStsSizeErr:
  532. case ippStsBadArgErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  533. default: return SAMPLE_ERROR_UNEXPECTED;
  534. }
  535. }
  536. /* Computes DH shared key based on private B key (local) and remote public Ga Key
  537. * Parameters:
  538. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  539. * Inputs: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system
  540. * sample_ec256_private_t *p_private_b - Pointer to the local private key - LITTLE ENDIAN
  541. * sample_ec256_public_t *p_public_ga - Pointer to the remote public key - LITTLE ENDIAN
  542. * Output: sample_ec256_dh_shared_t *p_shared_key - Pointer to the shared DH key - LITTLE ENDIAN
  543. *x-coordinate of (privKeyB - pubKeyA) */
  544. sample_status_t sample_ecc256_compute_shared_dhkey(sample_ec256_private_t *p_private_b,
  545. sample_ec256_public_t *p_public_ga,
  546. sample_ec256_dh_shared_t *p_shared_key,
  547. sample_ecc_state_handle_t ecc_handle)
  548. {
  549. if ((ecc_handle == NULL) || (p_private_b == NULL) || (p_public_ga == NULL) || (p_shared_key == NULL))
  550. {
  551. return SAMPLE_ERROR_INVALID_PARAMETER;
  552. }
  553. IppsBigNumState* BN_dh_privB = NULL;
  554. IppsBigNumState* BN_dh_share = NULL;
  555. IppsBigNumState* pubA_gx = NULL;
  556. IppsBigNumState* pubA_gy = NULL;
  557. IppsECCPPointState* point_pubA = NULL;
  558. IppStatus ipp_ret = ippStsNoErr;
  559. int ecPointSize = 0;
  560. IppsECCPState* p_ecc_state = (IppsECCPState*)ecc_handle;
  561. IppECResult ipp_result = ippECValid;
  562. do
  563. {
  564. ipp_ret = sgx_ipp_newBN((Ipp32u*)p_private_b->r, sizeof(sample_ec256_private_t), &BN_dh_privB);
  565. ERROR_BREAK(ipp_ret);
  566. ipp_ret = sgx_ipp_newBN((uint32_t*)p_public_ga->gx, sizeof(p_public_ga->gx), &pubA_gx);
  567. ERROR_BREAK(ipp_ret);
  568. ipp_ret = sgx_ipp_newBN((uint32_t*)p_public_ga->gy, sizeof(p_public_ga->gy), &pubA_gy);
  569. ERROR_BREAK(ipp_ret);
  570. ipp_ret = ippsECCPPointGetSize(256, &ecPointSize);
  571. ERROR_BREAK(ipp_ret);
  572. point_pubA = (IppsECCPPointState*)( malloc(ecPointSize) );
  573. if(!point_pubA)
  574. {
  575. ipp_ret = ippStsNoMemErr;
  576. break;
  577. }
  578. ipp_ret = ippsECCPPointInit(256, point_pubA);
  579. ERROR_BREAK(ipp_ret);
  580. ipp_ret = ippsECCPSetPoint(pubA_gx, pubA_gy, point_pubA, p_ecc_state);
  581. ERROR_BREAK(ipp_ret);
  582. // Check to see if the point is a valid point on the Elliptic curve and is not infinity
  583. ipp_ret = ippsECCPCheckPoint(point_pubA, &ipp_result, p_ecc_state);
  584. if (ipp_result != ippECValid)
  585. {
  586. break;
  587. }
  588. ERROR_BREAK(ipp_ret);
  589. ipp_ret = sgx_ipp_newBN(NULL, sizeof(sample_ec256_dh_shared_t), &BN_dh_share);
  590. ERROR_BREAK(ipp_ret);
  591. /* This API generates shareA = x-coordinate of (privKeyB - pubKeyA) */
  592. ipp_ret = ippsECCPSharedSecretDH(BN_dh_privB, point_pubA, BN_dh_share, p_ecc_state);
  593. ERROR_BREAK(ipp_ret);
  594. IppsBigNumSGN sgn = IppsBigNumPOS;
  595. int length = 0;
  596. Ipp32u * pdata = NULL;
  597. ipp_ret = ippsRef_BN(&sgn, &length, &pdata, BN_dh_share);
  598. ERROR_BREAK(ipp_ret);
  599. memset(p_shared_key->s, 0, sizeof(p_shared_key->s));
  600. ipp_ret = check_copy_size(sizeof(p_shared_key->s), ROUND_TO(length, 8)/8);
  601. ERROR_BREAK(ipp_ret);
  602. memcpy(p_shared_key->s, pdata, ROUND_TO(length, 8)/8);
  603. }while(0);
  604. // Clear temp buffer before free.
  605. if(point_pubA)
  606. memset_s(point_pubA, ecPointSize, 0, ecPointSize);
  607. SAFE_FREE(point_pubA);
  608. sample_ipp_secure_free_BN(pubA_gx, sizeof(p_public_ga->gx));
  609. sample_ipp_secure_free_BN(pubA_gy, sizeof(p_public_ga->gy));
  610. sample_ipp_secure_free_BN(BN_dh_privB, sizeof(sample_ec256_private_t));
  611. sample_ipp_secure_free_BN(BN_dh_share, sizeof(sample_ec256_dh_shared_t));
  612. if (ipp_result != ippECValid)
  613. {
  614. return SAMPLE_ERROR_INVALID_PARAMETER;
  615. }
  616. switch (ipp_ret)
  617. {
  618. case ippStsNoErr: return SAMPLE_SUCCESS;
  619. case ippStsNoMemErr:
  620. case ippStsMemAllocErr: return SAMPLE_ERROR_OUT_OF_MEMORY;
  621. case ippStsNullPtrErr:
  622. case ippStsLengthErr:
  623. case ippStsOutOfRangeErr:
  624. case ippStsSizeErr:
  625. case ippStsBadArgErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  626. default: return SAMPLE_ERROR_UNEXPECTED;
  627. }
  628. }
  629. const uint32_t sample_nistp256_r[] = {
  630. 0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, 0xFFFFFFFF, 0xFFFFFFFF,
  631. 0x00000000, 0xFFFFFFFF};
  632. #include <stdio.h>
  633. /* Computes signature for data based on private key
  634. * Parameters:
  635. * Return: sample_status_t - SAMPLE_SUCCESS, SAMPLE_SUCCESS on success, error code otherwise.
  636. * Inputs: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system
  637. * sample_ec256_private_t *p_private - Pointer to the private key - LITTLE ENDIAN
  638. * sample_uint8_t *p_data - Pointer to the data to be signed
  639. * uint32_t data_size - Size of the data to be signed
  640. * Output: sample_ec256_signature_t *p_signature - Pointer to the signature - LITTLE ENDIAN */
  641. sample_status_t sample_ecdsa_sign(const uint8_t *p_data,
  642. uint32_t data_size,
  643. sample_ec256_private_t *p_private,
  644. sample_ec256_signature_t *p_signature,
  645. sample_ecc_state_handle_t ecc_handle)
  646. {
  647. if ((ecc_handle == NULL) || (p_private == NULL) || (p_signature == NULL) || (p_data == NULL) || (data_size < 1))
  648. {
  649. return SAMPLE_ERROR_INVALID_PARAMETER;
  650. }
  651. IppStatus ipp_ret = ippStsNoErr;
  652. IppsECCPState* p_ecc_state = (IppsECCPState*)ecc_handle;
  653. IppsBigNumState* p_ecp_order = NULL;
  654. IppsBigNumState* p_hash_bn = NULL;
  655. IppsBigNumState* p_msg_bn = NULL;
  656. IppsBigNumState* p_eph_priv_bn = NULL;
  657. IppsECCPPointState* p_eph_pub = NULL;
  658. IppsBigNumState* p_reg_priv_bn = NULL;
  659. IppsBigNumState* p_signx_bn = NULL;
  660. IppsBigNumState* p_signy_bn = NULL;
  661. Ipp32u *p_sigx = NULL;
  662. Ipp32u *p_sigy = NULL;
  663. int ecp_size = 0;
  664. const int order_size = sizeof(sample_nistp256_r);
  665. uint32_t hash[8] = {0};
  666. do
  667. {
  668. ipp_ret = sgx_ipp_newBN(sample_nistp256_r, order_size, &p_ecp_order);
  669. ERROR_BREAK(ipp_ret);
  670. // Prepare the message used to sign.
  671. ipp_ret = ippsHashMessage(p_data, data_size, (Ipp8u*)hash, IPP_ALG_HASH_SHA256);
  672. ERROR_BREAK(ipp_ret);
  673. /* Byte swap in creation of Big Number from SHA256 hash output */
  674. ipp_ret = sgx_ipp_newBN(NULL, sizeof(hash), &p_hash_bn);
  675. ERROR_BREAK(ipp_ret);
  676. ipp_ret = ippsSetOctString_BN((Ipp8u*)hash, sizeof(hash), p_hash_bn);
  677. ERROR_BREAK(ipp_ret);
  678. ipp_ret = sgx_ipp_newBN(NULL, order_size, &p_msg_bn);
  679. ERROR_BREAK(ipp_ret);
  680. ipp_ret = ippsMod_BN(p_hash_bn, p_ecp_order, p_msg_bn);
  681. ERROR_BREAK(ipp_ret);
  682. // Get ephemeral key pair.
  683. ipp_ret = sgx_ipp_newBN(NULL, order_size, &p_eph_priv_bn);
  684. ERROR_BREAK(ipp_ret);
  685. //init eccp point
  686. ipp_ret = ippsECCPPointGetSize(256, &ecp_size);
  687. ERROR_BREAK(ipp_ret);
  688. p_eph_pub = (IppsECCPPointState*)(malloc(ecp_size));
  689. if(!p_eph_pub)
  690. {
  691. ipp_ret = ippStsNoMemErr;
  692. break;
  693. }
  694. ipp_ret = ippsECCPPointInit(256, p_eph_pub);
  695. ERROR_BREAK(ipp_ret);
  696. // generate ephemeral key pair for signing operation
  697. ipp_ret = ippsECCPGenKeyPair(p_eph_priv_bn, p_eph_pub, p_ecc_state,
  698. (IppBitSupplier)sample_ipp_DRNGen, NULL);
  699. ERROR_BREAK(ipp_ret);
  700. ipp_ret = ippsECCPSetKeyPair(p_eph_priv_bn, p_eph_pub, ippFalse, p_ecc_state);
  701. ERROR_BREAK(ipp_ret);
  702. // Set the regular private key.
  703. ipp_ret = sgx_ipp_newBN((uint32_t *)p_private->r, sizeof(p_private->r),
  704. &p_reg_priv_bn);
  705. ERROR_BREAK(ipp_ret);
  706. ipp_ret = sgx_ipp_newBN(NULL, order_size, &p_signx_bn);
  707. ERROR_BREAK(ipp_ret);
  708. ipp_ret = sgx_ipp_newBN(NULL, order_size, &p_signy_bn);
  709. ERROR_BREAK(ipp_ret);
  710. // Sign the message.
  711. ipp_ret = ippsECCPSignDSA(p_msg_bn, p_reg_priv_bn, p_signx_bn, p_signy_bn,
  712. p_ecc_state);
  713. ERROR_BREAK(ipp_ret);
  714. IppsBigNumSGN sign;
  715. int length;
  716. ipp_ret = ippsRef_BN(&sign, &length,(Ipp32u**) &p_sigx, p_signx_bn);
  717. ERROR_BREAK(ipp_ret);
  718. memset(p_signature->x, 0, sizeof(p_signature->x));
  719. ipp_ret = check_copy_size(sizeof(p_signature->x), ROUND_TO(length, 8)/8);
  720. ERROR_BREAK(ipp_ret);
  721. memcpy(p_signature->x, p_sigx, ROUND_TO(length, 8)/8);
  722. memset_s(p_sigx, sizeof(p_signature->x), 0, ROUND_TO(length, 8)/8);
  723. ipp_ret = ippsRef_BN(&sign, &length,(Ipp32u**) &p_sigy, p_signy_bn);
  724. ERROR_BREAK(ipp_ret);
  725. memset(p_signature->y, 0, sizeof(p_signature->y));
  726. ipp_ret = check_copy_size(sizeof(p_signature->y), ROUND_TO(length, 8)/8);
  727. ERROR_BREAK(ipp_ret);
  728. memcpy(p_signature->y, p_sigy, ROUND_TO(length, 8)/8);
  729. memset_s(p_sigy, sizeof(p_signature->y), 0, ROUND_TO(length, 8)/8);
  730. }while(0);
  731. // Clear buffer before free.
  732. if(p_eph_pub)
  733. memset_s(p_eph_pub, ecp_size, 0, ecp_size);
  734. SAFE_FREE(p_eph_pub);
  735. sample_ipp_secure_free_BN(p_ecp_order, order_size);
  736. sample_ipp_secure_free_BN(p_hash_bn, sizeof(hash));
  737. sample_ipp_secure_free_BN(p_msg_bn, order_size);
  738. sample_ipp_secure_free_BN(p_eph_priv_bn, order_size);
  739. sample_ipp_secure_free_BN(p_reg_priv_bn, sizeof(p_private->r));
  740. sample_ipp_secure_free_BN(p_signx_bn, order_size);
  741. sample_ipp_secure_free_BN(p_signy_bn, order_size);
  742. switch (ipp_ret)
  743. {
  744. case ippStsNoErr: return SAMPLE_SUCCESS;
  745. case ippStsNoMemErr:
  746. case ippStsMemAllocErr: return SAMPLE_ERROR_OUT_OF_MEMORY;
  747. case ippStsNullPtrErr:
  748. case ippStsLengthErr:
  749. case ippStsOutOfRangeErr:
  750. case ippStsSizeErr:
  751. case ippStsBadArgErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  752. default: return SAMPLE_ERROR_UNEXPECTED;
  753. }
  754. }
  755. /* Allocates and initializes sha256 state
  756. * Parameters:
  757. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  758. * Output: sample_sha_state_handle_t sha_handle - Handle to the SHA256 state */
  759. sample_status_t sample_sha256_init(sample_sha_state_handle_t* p_sha_handle)
  760. {
  761. IppStatus ipp_ret = ippStsNoErr;
  762. IppsHashState* p_temp_state = NULL;
  763. if (p_sha_handle == NULL)
  764. return SAMPLE_ERROR_INVALID_PARAMETER;
  765. int ctx_size = 0;
  766. ipp_ret = ippsHashGetSize(&ctx_size);
  767. if (ipp_ret != ippStsNoErr)
  768. return SAMPLE_ERROR_UNEXPECTED;
  769. p_temp_state = (IppsHashState*)(malloc(ctx_size));
  770. if (p_temp_state == NULL)
  771. return SAMPLE_ERROR_OUT_OF_MEMORY;
  772. ipp_ret = ippsHashInit(p_temp_state, IPP_ALG_HASH_SHA256);
  773. if (ipp_ret != ippStsNoErr)
  774. {
  775. SAFE_FREE(p_temp_state);
  776. *p_sha_handle = NULL;
  777. switch (ipp_ret)
  778. {
  779. case ippStsNullPtrErr:
  780. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  781. default: return SAMPLE_ERROR_UNEXPECTED;
  782. }
  783. }
  784. *p_sha_handle = p_temp_state;
  785. return SAMPLE_SUCCESS;
  786. }
  787. /* Updates sha256 has calculation based on the input message
  788. * Parameters:
  789. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  790. * Input: sample_sha_state_handle_t sha_handle - Handle to the SHA256 state
  791. * uint8_t *p_src - Pointer to the input stream to be hashed
  792. * uint32_t src_len - Length of the input stream to be hashed */
  793. sample_status_t sample_sha256_update(const uint8_t *p_src, uint32_t src_len, sample_sha_state_handle_t sha_handle)
  794. {
  795. if ((p_src == NULL) || (sha_handle == NULL))
  796. {
  797. return SAMPLE_ERROR_INVALID_PARAMETER;
  798. }
  799. IppStatus ipp_ret = ippStsNoErr;
  800. ipp_ret = ippsHashUpdate(p_src, src_len, (IppsHashState*)sha_handle);
  801. switch (ipp_ret)
  802. {
  803. case ippStsNoErr: return SAMPLE_SUCCESS;
  804. case ippStsNullPtrErr:
  805. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  806. default: return SAMPLE_ERROR_UNEXPECTED;
  807. }
  808. }
  809. /* Returns Hash calculation
  810. * Parameters:
  811. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  812. * Input: sample_sha_state_handle_t sha_handle - Handle to the SHA256 state
  813. * Output: sample_sha256_hash_t *p_hash - Resultant hash from operation */
  814. sample_status_t sample_sha256_get_hash(sample_sha_state_handle_t sha_handle, sample_sha256_hash_t *p_hash)
  815. {
  816. if ((sha_handle == NULL) || (p_hash == NULL))
  817. {
  818. return SAMPLE_ERROR_INVALID_PARAMETER;
  819. }
  820. IppStatus ipp_ret = ippStsNoErr;
  821. ipp_ret = ippsHashGetTag((Ipp8u*)p_hash, SAMPLE_SHA256_HASH_SIZE, (IppsHashState*)sha_handle);
  822. switch (ipp_ret)
  823. {
  824. case ippStsNoErr: return SAMPLE_SUCCESS;
  825. case ippStsNullPtrErr:
  826. case ippStsLengthErr: return SAMPLE_ERROR_INVALID_PARAMETER;
  827. default: return SAMPLE_ERROR_UNEXPECTED;
  828. }
  829. }
  830. /* Cleans up sha state
  831. * Parameters:
  832. * Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise.
  833. * Input: sample_sha_state_handle_t sha_handle - Handle to the SHA256 state */
  834. sample_status_t sample_sha256_close(sample_sha_state_handle_t sha_handle)
  835. {
  836. if (sha_handle == NULL)
  837. {
  838. return SAMPLE_ERROR_INVALID_PARAMETER;
  839. }
  840. SAFE_FREE(sha_handle);
  841. return SAMPLE_SUCCESS;
  842. }