sigma_helper.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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 "sigma_helper.h"
  32. #include "uecall_bridge.h"
  33. #include "helper.h"
  34. #include <Buffer.h>
  35. #include "pse_pr_sigma_common_defs.h"
  36. #include "se_time.h"
  37. #include "endpoint_select_info.h"
  38. #pragma GCC diagnostic push
  39. #pragma GCC diagnostic ignored "-Wredundant-decls"
  40. #include "openssl/ocsp.h"
  41. #include "openssl/ssl.h"
  42. #pragma GCC diagnostic pop
  43. #include "interface_ocsp.h"
  44. #include <limits.h>
  45. #include <stdint.h>
  46. #include <stdlib.h>
  47. #include <stdio.h>
  48. #include <string>
  49. #include <memory.h>
  50. #include "provision_msg.h"
  51. #include "aesm_logic.h"
  52. #include "oal/oal.h"
  53. #include "network_encoding_wrapper.h"
  54. #ifndef UINT16_MAX
  55. #define UINT16_MAX 0xFFFF
  56. #endif
  57. #define MAX_OCSP_BUSY_RETRIES (3)
  58. #define OCSP_BUSY_RETRY_SLEEP_MILLISECONDS (50)
  59. upse::Buffer SigmaHelper::m_gid;
  60. #include "ivk_ca_root_der.hh"
  61. ae_error_t SigmaHelper::SetGID(upse::Buffer& gid)
  62. {
  63. return m_gid.Clone(gid);
  64. }
  65. ae_error_t SigmaHelper::GetRLsFromServer
  66. ( /*out*/ upse::Buffer& sigRlOut,
  67. /*out*/ upse::Buffer& privRlOut
  68. )
  69. {
  70. //
  71. // iKGF serves up binary (legacy) versions of EPID 1.1 RLs
  72. // all we need to do is convey the GID in the URL itself
  73. // for example, https://trustedservices.intel.com/content/crl/Signature_<GID>.crl
  74. // so, we get url out of config file and concatenate with filename that's
  75. // specific to the type of RL
  76. ae_error_t sigRetValue = AE_FAILURE;
  77. ae_error_t privRetValue = AE_FAILURE;
  78. const char *url = EndpointSelectionInfo::instance().get_server_url(REVOCATION_LIST_RETRIEVAL);
  79. if (url == NULL)
  80. {
  81. return OAL_CONFIG_FILE_ERROR;
  82. }
  83. uint8_t* p1 = const_cast<uint8_t*>(m_gid.getData());
  84. do {
  85. if ((m_gid.getSize() < 1) || (m_gid.getSize() > 4)) break;
  86. char msg[9];
  87. for (unsigned i = 0; i < m_gid.getSize(); i++)
  88. {
  89. sprintf_s((char*) msg+2*i, 3, "%02X", *(p1+m_gid.getSize()-1-i));
  90. }
  91. std::string gidString(msg);
  92. unsigned numLeading0s = 8 - static_cast<unsigned>(gidString.length());
  93. for (unsigned i = 0; i < numLeading0s; i++)
  94. {
  95. gidString = '0' + gidString;
  96. }
  97. //if config file entry doesn't have trailing "/" , add it.
  98. std::string s_url = url;
  99. if(s_url.size()>0&&s_url[s_url.size()-1]!='/')
  100. s_url+='/';
  101. std::string stringUrl = s_url + "Signature_" + gidString + ".crl";
  102. uint8_t *recv=NULL;
  103. uint32_t recv_size = 0;
  104. sigRetValue = AESMNetworkEncoding::aesm_send_recv_msg(stringUrl.c_str(), NULL, 0, recv, recv_size, GET, false);
  105. if (AE_SUCCESS != sigRetValue)
  106. {
  107. sigRlOut.Alloc(0);
  108. }
  109. else
  110. {
  111. sigRlOut.Alloc(recv_size);
  112. upse::BufferWriter bw(sigRlOut);
  113. bw.writeRaw(recv, recv_size);
  114. AESMNetworkEncoding::aesm_free_response_msg(recv);
  115. }
  116. stringUrl = s_url + "Product_" + gidString + ".crl";
  117. recv=NULL;
  118. recv_size = 0;
  119. privRetValue = AESMNetworkEncoding::aesm_send_recv_msg(stringUrl.c_str(), NULL, 0, recv, recv_size, GET, false);
  120. if (AE_SUCCESS != privRetValue)
  121. {
  122. privRlOut.Alloc(0);
  123. }
  124. else
  125. {
  126. privRlOut.Alloc(recv_size);
  127. upse::BufferWriter bw(privRlOut);
  128. bw.writeRaw(recv, recv_size);
  129. aesm_free_network_response_buffer(recv);
  130. }
  131. } while (0);
  132. if (AE_FAILED(privRetValue))
  133. {
  134. SGX_DBGPRINT_PRINT_STRING_LTP("PrivRL not retrieved: continuing without PrivRL");
  135. }
  136. if (AE_FAILED(sigRetValue))
  137. {
  138. SGX_DBGPRINT_PRINT_STRING_LTP("SigRL not retrieved: continuing without SigRL");
  139. }
  140. if ((privRetValue == AE_SUCCESS) && (sigRetValue == AE_SUCCESS)) {
  141. return AE_SUCCESS;
  142. }
  143. else if (sigRetValue != AE_SUCCESS) {
  144. return AESM_PSE_PR_GET_SIGRL_ERROR;
  145. }
  146. else {
  147. return AESM_PSE_PR_GET_PRIVRL_ERROR;
  148. }
  149. }
  150. void SigmaHelper::GetRootCA(upse::Buffer& b)
  151. {
  152. b.Alloc(sizeof(caRootDER));
  153. upse::BufferWriter bw(b);
  154. bw.writeRaw(caRootDER, sizeof(caRootDER));
  155. }
  156. ae_error_t SigmaHelper::GetOcspResponseFromServer
  157. (
  158. /*in */ const std::list<upse::Buffer>& certChain,
  159. /*in */ const OCSP_REQ& ocspReq,
  160. /*out*/ upse::Buffer& ocspResp
  161. )
  162. {
  163. ae_error_t status = AE_FAILURE;
  164. int nPaddedBytes = 0;
  165. int nTotalOcspBytes = 0;
  166. do
  167. {
  168. if (ocspReq.ReqType == NO_OCSP)
  169. {
  170. status = AE_SUCCESS;
  171. break;
  172. }
  173. const char *url = EndpointSelectionInfo::instance().get_server_url( PSE_OCSP);
  174. if (url == NULL){
  175. return OAL_CONFIG_FILE_ERROR;
  176. }
  177. // Load the root certificate into a local buffer
  178. upse::Buffer rootCert;
  179. SigmaHelper::GetRootCA(rootCert);
  180. std::list<upse::Buffer> ocspResponseList;
  181. // loop through chain and get an OCSP Response for each certificate/issuer pair
  182. bool fDone = false;
  183. //
  184. // certs were added leaf to root direction (assuming server functions according to spec)
  185. //
  186. std::list<upse::Buffer>::const_iterator itCertificate = certChain.begin();
  187. do
  188. {
  189. if (itCertificate == certChain.end())
  190. {
  191. status = AE_FAILURE;
  192. break;
  193. }
  194. upse::Buffer ocspResponse;
  195. const upse::Buffer& verifierCertificate = *itCertificate;
  196. ++itCertificate;
  197. int busy_loop = 0;
  198. do
  199. {
  200. if (itCertificate != certChain.end())
  201. {
  202. const upse::Buffer& issuerCertificate = *itCertificate;
  203. status = Get_OCSPResponse(url, &ocspReq.OcspNonce, verifierCertificate, issuerCertificate, ocspResponse);
  204. }
  205. else
  206. {
  207. fDone = true;
  208. const upse::Buffer& issuerCertificate = rootCert;
  209. status = Get_OCSPResponse(url, &ocspReq.OcspNonce, verifierCertificate, issuerCertificate, ocspResponse);
  210. }
  211. if (AESM_PSE_PR_OCSP_RESPONSE_STATUS_TRYLATER != status)
  212. break;
  213. se_sleep(OCSP_BUSY_RETRY_SLEEP_MILLISECONDS);
  214. } while (busy_loop++ < MAX_OCSP_BUSY_RETRIES);
  215. if (AE_FAILED(status))
  216. break;
  217. nPaddedBytes += REQUIRED_PADDING_DWORD_ALIGNMENT(ocspResponse.getSize());
  218. nTotalOcspBytes += ocspResponse.getSize();
  219. ocspResponseList.push_back(ocspResponse);
  220. } while (!fDone);
  221. if (AE_FAILED(status))
  222. break;
  223. if (0 == ocspResponseList.size())
  224. {
  225. status = AE_FAILURE;
  226. break;
  227. }
  228. nPaddedBytes = REQUIRED_PADDING_DWORD_ALIGNMENT(nTotalOcspBytes);
  229. if(UINT16_MAX-((int)sizeof(SIGMA_VLR_HEADER) + nPaddedBytes) < nTotalOcspBytes){
  230. status = AE_FAILURE;
  231. break;
  232. }
  233. int nLength = static_cast<int>(sizeof(SIGMA_VLR_HEADER)) + nPaddedBytes + nTotalOcspBytes;
  234. ocspResp.Alloc(nLength);
  235. upse::BufferWriter bw(ocspResp);
  236. uint8_t* p;
  237. status = bw.reserve(nLength, &p);
  238. if (AE_FAILED(status))
  239. break;
  240. OCSP_RESPONSE_VLR* pVLR = (OCSP_RESPONSE_VLR*)p;
  241. pVLR->VlrHeader.ID = OCSP_RESPONSE_VLR_ID;
  242. pVLR->VlrHeader.PaddedBytes = (UINT8)nPaddedBytes;
  243. pVLR->VlrHeader.Length = (UINT16)nLength;
  244. memset(pVLR->OcspResponse, 0, nPaddedBytes + nTotalOcspBytes);
  245. int nNext = 0;
  246. //
  247. // order above doesn't really matter since it's between verifier/host and ocsp responder
  248. // and each request/response is independent
  249. // spec basically says what's correct here
  250. // but we'll leave condition to show how to traverse in either order
  251. //
  252. #if !defined(LEAFTOROOT)
  253. #error LEAFTOROOT not defined
  254. #endif
  255. #if !LEAFTOROOT
  256. //
  257. // this clause adds responses from root to leaf
  258. //
  259. SGX_DBGPRINT_PRINT_STRING_LTP("root ocsp to leaf ocsp direction");
  260. std::list<upse::Buffer>::reverse_iterator itRespList = ocspResponseList.rbegin();
  261. for ( ; itRespList != ocspResponseList.rend(); ++itRespList)
  262. {
  263. const upse::Buffer& item = *itRespList;
  264. memcpy_s(pVLR->OcspResponse + nNext, item.getSize(), item.getData(), item.getSize());
  265. nNext += item.getSize();
  266. }
  267. #else
  268. SGX_DBGPRINT_PRINT_STRING_LTP("leaf ocsp to root ocsp direction");
  269. //
  270. // this clause adds responses from leaf to root
  271. //
  272. std::list<upse::Buffer>::iterator itRespList = ocspResponseList.begin();
  273. for ( ; itRespList != ocspResponseList.end(); ++itRespList)
  274. {
  275. const upse::Buffer& item = *itRespList;
  276. memcpy_s(pVLR->OcspResponse + nNext, item.getSize(), item.getData(), item.getSize());
  277. nNext += item.getSize();
  278. }
  279. #endif
  280. Helper::write_ocsp_response_vlr(ocspResp);
  281. status = AE_SUCCESS;
  282. } while (0);
  283. if (status == OAL_NETWORK_UNAVAILABLE_ERROR)
  284. {
  285. if (ocspReq.ReqType == CACHED && AE_SUCCEEDED(Helper::read_ocsp_response_vlr(ocspResp)))
  286. {
  287. status = AE_SUCCESS;
  288. }
  289. }
  290. SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status);
  291. return status;
  292. }