pce_helper.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * Copyright (C) 2011-2018 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 "arch.h"
  32. #include "pce_cert.h"
  33. #include "aeerror.h"
  34. #include "sgx_utils.h"
  35. #include "ipp_wrapper.h"
  36. #include <assert.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. //Function to get provisioning key using the provided PSVN
  40. //If the psvn is NULL, both CPUSVN and ISVSVN is set to 0 (used for PPID generation only)
  41. //Input: psvn, the psvn used to generate provisioning key
  42. //Output: key, the provisioning key to return
  43. // return PVEC_SUCCESS on success
  44. static ae_error_t get_provision_key(sgx_key_128bit_t *key, const psvn_t *psvn)
  45. {
  46. sgx_status_t se_ret = SGX_SUCCESS;
  47. sgx_key_request_t wrap_key_req;
  48. //memset here will also set cpusvn isvsvn to 0 for the case when psvn==NULL
  49. memset(&wrap_key_req, 0, sizeof(sgx_key_request_t));
  50. if(psvn==NULL){
  51. }else{
  52. memcpy(&wrap_key_req.cpu_svn, &psvn->cpu_svn, sizeof(wrap_key_req.cpu_svn));
  53. memcpy(&wrap_key_req.isv_svn, &psvn->isv_svn, sizeof(wrap_key_req.isv_svn));
  54. }
  55. wrap_key_req.key_name = SGX_KEYSELECT_PROVISION; //provisioning key
  56. wrap_key_req.attribute_mask.xfrm = 0;
  57. wrap_key_req.misc_mask = 0xFFFFFFFF;
  58. wrap_key_req.attribute_mask.flags = ~SGX_FLAGS_MODE64BIT; //set all bits except the SGX_FLAGS_MODE64BIT
  59. se_ret = sgx_get_key(&wrap_key_req, key);
  60. if(SGX_SUCCESS != se_ret)
  61. {
  62. return AE_FAILURE;
  63. }
  64. return AE_SUCCESS;
  65. }
  66. ae_error_t get_ppid(ppid_t* ppid)
  67. {
  68. sgx_key_128bit_t key_tmp;
  69. sgx_status_t sgx_status = SGX_SUCCESS;
  70. memset(&key_tmp, 0, sizeof(key_tmp));
  71. //get Provisioning Key with both CPUSVN and ISVSVN set to 0
  72. ae_error_t status = get_provision_key(&key_tmp, NULL);
  73. if(status != AE_SUCCESS){
  74. (void)memset_s(&key_tmp,sizeof(key_tmp), 0, sizeof(key_tmp));
  75. return status;
  76. }
  77. uint8_t content[16];
  78. memset(&content, 0, sizeof(content));
  79. //generate the mac as PPID
  80. se_static_assert(sizeof(sgx_cmac_128bit_key_t) == sizeof(sgx_key_128bit_t));
  81. se_static_assert(sizeof(sgx_cmac_128bit_tag_t) == sizeof(*ppid));
  82. if((sgx_status=sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(&key_tmp),
  83. content, sizeof(content), reinterpret_cast<sgx_cmac_128bit_tag_t *>(ppid)))!=SGX_SUCCESS){
  84. if(sgx_status == SGX_ERROR_OUT_OF_MEMORY){
  85. status = AE_OUT_OF_MEMORY_ERROR;
  86. }else{
  87. status = AE_FAILURE;
  88. }
  89. }else{
  90. status = AE_SUCCESS;
  91. }
  92. (void)memset_s(&key_tmp,sizeof(key_tmp), 0, sizeof(key_tmp));//clear provisioning key in stack
  93. return status;
  94. }
  95. const uint32_t sgx_nistp256_r_m1[] = {//hard-coded value for n-1 where n is order of the ECC group used
  96. 0xFC632550, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, 0xFFFFFFFF, 0xFFFFFFFF,
  97. 0x00000000, 0xFFFFFFFF};
  98. #define HASH_DRBG_OUT_LEN 40 //320 bits
  99. const char PAK_STRING[] = "PAK_KEY_DER";
  100. ae_error_t get_pce_priv_key(
  101. const psvn_t* psvn,
  102. sgx_ec256_private_t* wrap_key)
  103. {
  104. if( psvn == NULL)
  105. return AE_FAILURE;
  106. uint8_t content[16];
  107. sgx_cmac_128bit_tag_t block;
  108. sgx_status_t sgx_status = SGX_SUCCESS;
  109. ae_error_t status = AE_SUCCESS;
  110. sgx_key_128bit_t key_tmp;
  111. IppStatus ipp_status = ippStsNoErr;
  112. IppsBigNumState *bn_d=NULL;
  113. IppsBigNumState *bn_m=NULL;
  114. IppsBigNumState *bn_o=NULL;
  115. IppsBigNumState *bn_one=NULL;
  116. uint8_t hash_drg_output[HASH_DRBG_OUT_LEN];
  117. memset(&content, 0, sizeof(content));
  118. memset(&block, 0, sizeof(block));
  119. memset(&key_tmp, 0, sizeof(key_tmp));
  120. //1-11bytes: "PAK_KEY_DER"(ascii encoded)
  121. memcpy(content+1, PAK_STRING, 11);
  122. //14-15bytes: 0x0140 (Big Endian)
  123. content[14]=0x01;
  124. content[15]=0x40;
  125. status = get_provision_key(&key_tmp, psvn); //Generate Provisioning Key with respect to the psvn
  126. if(status != AE_SUCCESS){
  127. goto ret_point;
  128. }
  129. se_static_assert(sizeof(sgx_cmac_128bit_key_t) == sizeof(sgx_key_128bit_t));
  130. se_static_assert(2*sizeof(sgx_cmac_128bit_tag_t) <= HASH_DRBG_OUT_LEN && 3*sizeof(sgx_cmac_128bit_tag_t) >= HASH_DRBG_OUT_LEN);
  131. //Block 1 = AES-CMAC(Provisioning Key, PAK string with Counter = 0x01)
  132. content[0] = 0x01;
  133. if((sgx_status=sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(key_tmp),
  134. content, sizeof(content), &block))!=SGX_SUCCESS){
  135. if(sgx_status == SGX_ERROR_OUT_OF_MEMORY){
  136. status = AE_OUT_OF_MEMORY_ERROR;
  137. }else{
  138. status = AE_FAILURE;
  139. }
  140. goto ret_point;
  141. }
  142. memcpy(hash_drg_output, block, sizeof(sgx_cmac_128bit_tag_t));
  143. //Block 2 = AES-CMAC(Provisioning Key, PAK string with Counter = 0x02)
  144. content[0] = 0x02;
  145. if((sgx_status=sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(key_tmp),
  146. content, sizeof(content), &block))!=SGX_SUCCESS){
  147. if(sgx_status == SGX_ERROR_OUT_OF_MEMORY){
  148. status = AE_OUT_OF_MEMORY_ERROR;
  149. }else{
  150. status = AE_FAILURE;
  151. }
  152. goto ret_point;
  153. }
  154. memcpy(hash_drg_output + sizeof(sgx_cmac_128bit_tag_t), block, sizeof(sgx_cmac_128bit_tag_t));
  155. //Block 3 = AES-CMAC(Provisioning Key, PAK string with Counter = 0x03)
  156. content[0] = 0x03;
  157. if((sgx_status=sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(key_tmp),
  158. content, sizeof(content), &block))!=SGX_SUCCESS){
  159. if(sgx_status == SGX_ERROR_OUT_OF_MEMORY){
  160. status = AE_OUT_OF_MEMORY_ERROR;
  161. }else{
  162. status = AE_FAILURE;
  163. }
  164. goto ret_point;
  165. }
  166. //PAK Seed = most significant 320 bits of (Block 1 || Block 2 || Block 3).
  167. memcpy(hash_drg_output + 2*sizeof(sgx_cmac_128bit_tag_t), block, HASH_DRBG_OUT_LEN - 2*sizeof(sgx_cmac_128bit_tag_t));
  168. Ipp32u i;
  169. for (i = 0; i<HASH_DRBG_OUT_LEN / 2; i++){//big endian to little endian
  170. hash_drg_output[i] ^= hash_drg_output[HASH_DRBG_OUT_LEN - 1 - i];
  171. hash_drg_output[HASH_DRBG_OUT_LEN-1-i] ^= hash_drg_output[i];
  172. hash_drg_output[i] ^= hash_drg_output[HASH_DRBG_OUT_LEN - 1 - i];
  173. }
  174. #define IPP_ERROR_TRANS(ipp_status) \
  175. if ( ippStsMemAllocErr == ipp_status) \
  176. { \
  177. status = AE_OUT_OF_MEMORY_ERROR; \
  178. goto ret_point; \
  179. } \
  180. else if(ippStsNoErr != ipp_status){ \
  181. status = PCE_UNEXPECTED_ERROR; \
  182. goto ret_point; \
  183. }
  184. ipp_status = newBN(reinterpret_cast<Ipp32u *>(hash_drg_output), HASH_DRBG_OUT_LEN, &bn_d);
  185. IPP_ERROR_TRANS(ipp_status);
  186. ipp_status = newBN(reinterpret_cast<const Ipp32u *>(sgx_nistp256_r_m1), sizeof(sgx_nistp256_r_m1), &bn_m);//generate mod to be n-1 where n is order of ECC Group
  187. IPP_ERROR_TRANS(ipp_status);
  188. ipp_status = newBN(NULL, sizeof(sgx_nistp256_r_m1), &bn_o);//alloc memory for output
  189. IPP_ERROR_TRANS(ipp_status);
  190. ipp_status = ippsMod_BN(bn_d, bn_m, bn_o);
  191. IPP_ERROR_TRANS(ipp_status);
  192. i=1;
  193. ipp_status = newBN(&i, sizeof(uint32_t), &bn_one);//create big number 1
  194. IPP_ERROR_TRANS(ipp_status);
  195. ipp_status = ippsAdd_BN(bn_o, bn_one, bn_o);//added by 1
  196. IPP_ERROR_TRANS(ipp_status);
  197. se_static_assert(sizeof(sgx_nistp256_r_m1)==sizeof(sgx_ec256_private_t)); /*Unmatched size*/
  198. ipp_status = ippsGetOctString_BN(reinterpret_cast<Ipp8u *>(wrap_key), sizeof(sgx_nistp256_r_m1), bn_o);//output data in bigendian order
  199. IPP_ERROR_TRANS(ipp_status);
  200. ret_point:
  201. if(NULL!=bn_d){
  202. secure_free_BN(bn_d, HASH_DRBG_OUT_LEN);
  203. }
  204. if(NULL!=bn_m){
  205. secure_free_BN(bn_m, sizeof(sgx_nistp256_r_m1));
  206. }
  207. if(NULL!=bn_o){
  208. secure_free_BN(bn_o, sizeof(sgx_nistp256_r_m1));
  209. }
  210. if(NULL!=bn_one){
  211. secure_free_BN(bn_one, sizeof(uint32_t));
  212. }
  213. (void)memset_s(&key_tmp, sizeof(key_tmp), 0, sizeof(key_tmp));
  214. (void)memset_s(&hash_drg_output, sizeof(hash_drg_output), 0, sizeof(hash_drg_output));
  215. (void)memset_s(&block, sizeof(block), 0, sizeof(block));
  216. if(status!=AE_SUCCESS){
  217. (void)memset_s(wrap_key,sizeof(sgx_ec256_private_t), 0 ,sizeof(sgx_ec256_private_t)); //clear private key in stack
  218. }
  219. return status;
  220. }