ecp.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. #include <stdlib.h>
  32. #include <string.h>
  33. #include "ecp.h"
  34. #include "sample_libcrypto.h"
  35. #define MAC_KEY_SIZE 16
  36. errno_t memcpy_s(
  37. void *dest,
  38. size_t numberOfElements,
  39. const void *src,
  40. size_t count)
  41. {
  42. if(numberOfElements<count)
  43. return -1;
  44. memcpy(dest, src, count);
  45. return 0;
  46. }
  47. bool verify_cmac128(
  48. sample_ec_key_128bit_t mac_key,
  49. const uint8_t *p_data_buf,
  50. uint32_t buf_size,
  51. const uint8_t *p_mac_buf)
  52. {
  53. uint8_t data_mac[SAMPLE_EC_MAC_SIZE];
  54. sample_status_t sample_ret;
  55. sample_ret = sample_rijndael128_cmac_msg((sample_cmac_128bit_key_t*)mac_key,
  56. p_data_buf,
  57. buf_size,
  58. (sample_cmac_128bit_tag_t *)data_mac);
  59. if(sample_ret != SAMPLE_SUCCESS)
  60. return false;
  61. // In real implementation, should use a time safe version of memcmp here,
  62. // in order to avoid side channel attack.
  63. if(!memcmp(p_mac_buf, data_mac, SAMPLE_EC_MAC_SIZE))
  64. return true;
  65. return false;
  66. }
  67. #ifdef SUPPLIED_KEY_DERIVATION
  68. #pragma message ("Supplied key derivation function is used.")
  69. typedef struct _hash_buffer_t
  70. {
  71. uint8_t counter[4];
  72. sample_ec_dh_shared_t shared_secret;
  73. uint8_t algorithm_id[4];
  74. } hash_buffer_t;
  75. const char ID_U[] = "SGXRAENCLAVE";
  76. const char ID_V[] = "SGXRASERVER";
  77. // Derive two keys from shared key and key id.
  78. bool derive_key(
  79. const sample_ec_dh_shared_t *p_shared_key,
  80. uint8_t key_id,
  81. sample_ec_key_128bit_t *first_derived_key,
  82. sample_ec_key_128bit_t *second_derived_key)
  83. {
  84. sample_status_t sample_ret = SAMPLE_SUCCESS;
  85. hash_buffer_t hash_buffer;
  86. sample_sha_state_handle_t sha_context;
  87. sample_sha256_hash_t key_material;
  88. memset(&hash_buffer, 0, sizeof(hash_buffer_t));
  89. /* counter in big endian */
  90. hash_buffer.counter[3] = key_id;
  91. /*convert from little endian to big endian */
  92. for (size_t i = 0; i < sizeof(sample_ec_dh_shared_t) ; i++)
  93. {
  94. hash_buffer.shared_secret.s[i] = p_shared_key->s[sizeof(p_shared_key->s) - 1 - i];
  95. }
  96. sample_ret = sample_sha256_init(&sha_context);
  97. if (sample_ret != SAMPLE_SUCCESS)
  98. {
  99. return false;
  100. }
  101. sample_ret = sample_sha256_update((uint8_t*)&hash_buffer, sizeof(hash_buffer_t), sha_context);
  102. if (sample_ret != SAMPLE_SUCCESS)
  103. {
  104. sample_sha256_close(sha_context);
  105. return false;
  106. }
  107. sample_ret = sample_sha256_update((uint8_t*)ID_U, sizeof(ID_U), sha_context);
  108. if (sample_ret != SAMPLE_SUCCESS)
  109. {
  110. sample_sha256_close(sha_context);
  111. return false;
  112. }
  113. sample_ret = sample_sha256_update((uint8_t*)ID_V, sizeof(ID_V), sha_context);
  114. if (sample_ret != SAMPLE_SUCCESS)
  115. {
  116. sample_sha256_close(sha_context);
  117. return false;
  118. }
  119. sample_ret = sample_sha256_get_hash(sha_context, &key_material);
  120. if (sample_ret != SAMPLE_SUCCESS)
  121. {
  122. sample_sha256_close(sha_context);
  123. return false;
  124. }
  125. sample_ret = sample_sha256_close(sha_context);
  126. static_assert(sizeof(sample_ec_key_128bit_t)* 2 == sizeof(sample_sha256_hash_t), "structure size mismatch.");
  127. memcpy(first_derived_key, &key_material, sizeof(sample_ec_key_128bit_t));
  128. memcpy(second_derived_key, (uint8_t*)&key_material + sizeof(sample_ec_key_128bit_t), sizeof(sample_ec_key_128bit_t));
  129. // memset here can be optimized away by compiler, so please use memset_s on
  130. // windows for production code and similar functions on other OSes.
  131. memset(&key_material, 0, sizeof(sample_sha256_hash_t));
  132. return true;
  133. }
  134. #else
  135. #pragma message ("Default key derivation function is used.")
  136. #define EC_DERIVATION_BUFFER_SIZE(label_length) ((label_length) +4)
  137. const char str_SMK[] = "SMK";
  138. const char str_SK[] = "SK";
  139. const char str_MK[] = "MK";
  140. const char str_VK[] = "VK";
  141. // Derive key from shared key and key id.
  142. // key id should be sample_derive_key_type_t.
  143. bool derive_key(
  144. const sample_ec_dh_shared_t *p_shared_key,
  145. uint8_t key_id,
  146. sample_ec_key_128bit_t* derived_key)
  147. {
  148. sample_status_t sample_ret = SAMPLE_SUCCESS;
  149. uint8_t cmac_key[MAC_KEY_SIZE];
  150. sample_ec_key_128bit_t key_derive_key;
  151. memset(&cmac_key, 0, MAC_KEY_SIZE);
  152. sample_ret = sample_rijndael128_cmac_msg(
  153. (sample_cmac_128bit_key_t *)&cmac_key,
  154. (uint8_t*)p_shared_key,
  155. sizeof(sample_ec_dh_shared_t),
  156. (sample_cmac_128bit_tag_t *)&key_derive_key);
  157. if (sample_ret != SAMPLE_SUCCESS)
  158. {
  159. // memset here can be optimized away by compiler, so please use memset_s on
  160. // windows for production code and similar functions on other OSes.
  161. memset(&key_derive_key, 0, sizeof(key_derive_key));
  162. return false;
  163. }
  164. const char *label = NULL;
  165. uint32_t label_length = 0;
  166. switch (key_id)
  167. {
  168. case SAMPLE_DERIVE_KEY_SMK:
  169. label = str_SMK;
  170. label_length = sizeof(str_SMK) -1;
  171. break;
  172. case SAMPLE_DERIVE_KEY_SK:
  173. label = str_SK;
  174. label_length = sizeof(str_SK) -1;
  175. break;
  176. case SAMPLE_DERIVE_KEY_MK:
  177. label = str_MK;
  178. label_length = sizeof(str_MK) -1;
  179. break;
  180. case SAMPLE_DERIVE_KEY_VK:
  181. label = str_VK;
  182. label_length = sizeof(str_VK) -1;
  183. break;
  184. default:
  185. // memset here can be optimized away by compiler, so please use memset_s on
  186. // windows for production code and similar functions on other OSes.
  187. memset(&key_derive_key, 0, sizeof(key_derive_key));
  188. return false;
  189. break;
  190. }
  191. /* derivation_buffer = counter(0x01) || label || 0x00 || output_key_len(0x0080) */
  192. uint32_t derivation_buffer_length = EC_DERIVATION_BUFFER_SIZE(label_length);
  193. uint8_t *p_derivation_buffer = (uint8_t *)malloc(derivation_buffer_length);
  194. if (p_derivation_buffer == NULL)
  195. {
  196. // memset here can be optimized away by compiler, so please use memset_s on
  197. // windows for production code and similar functions on other OSes.
  198. memset(&key_derive_key, 0, sizeof(key_derive_key));
  199. return false;
  200. }
  201. memset(p_derivation_buffer, 0, derivation_buffer_length);
  202. /*counter = 0x01 */
  203. p_derivation_buffer[0] = 0x01;
  204. /*label*/
  205. memcpy(&p_derivation_buffer[1], label, label_length);
  206. /*output_key_len=0x0080*/
  207. uint16_t *key_len = (uint16_t *)(&(p_derivation_buffer[derivation_buffer_length - 2]));
  208. *key_len = 0x0080;
  209. sample_ret = sample_rijndael128_cmac_msg(
  210. (sample_cmac_128bit_key_t *)&key_derive_key,
  211. p_derivation_buffer,
  212. derivation_buffer_length,
  213. (sample_cmac_128bit_tag_t *)derived_key);
  214. free(p_derivation_buffer);
  215. // memset here can be optimized away by compiler, so please use memset_s on
  216. // windows for production code and similar functions on other OSes.
  217. memset(&key_derive_key, 0, sizeof(key_derive_key));
  218. if (sample_ret != SAMPLE_SUCCESS)
  219. {
  220. return false;
  221. }
  222. return true;
  223. }
  224. #endif