interface_ocsp.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * Copyright (C) 2011-2017 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 "aeerror.h"
  32. #include <cstddef>
  33. #pragma GCC diagnostic push
  34. #pragma GCC diagnostic ignored "-Wredundant-decls"
  35. #include "openssl/ocsp.h"
  36. #pragma GCC diagnostic pop
  37. #include "oal/oal.h"
  38. #include "pse_pr_sigma_common_defs.h"
  39. #include "Buffer.h"
  40. #include "network_encoding_wrapper.h"
  41. #include "helper.h"
  42. #undef OCSP_CLEAN
  43. #undef _OPENSSL_FULL_INIT
  44. #undef USE_CERTID_STACK
  45. extern "C" int get_ocsp_req_size(BIO* reqbio, OCSP_REQUEST *pOcspReq)
  46. {
  47. #if defined(OCSP_CLEAN)
  48. return i2d_OCSP_REQUEST_bio(reqbio, pOcspReq);
  49. #else
  50. return ASN1_i2d_bio(CHECKED_I2D_OF(OCSP_REQUEST, i2d_OCSP_REQUEST), reqbio, (unsigned char*)pOcspReq);
  51. #endif
  52. }
  53. //
  54. // we should 1) make sure this function is right, for the AESM and all its uses of OpenSSL and
  55. // 2) move it to a more central/global location. 1 may require adding the so-called OpenSSL
  56. // thread callbacks. Also, what about all the config settings? Are the defaults okay for us?
  57. //
  58. void OpenSSL_init()
  59. {
  60. #if defined(_OPENSSL_FULL_INIT)
  61. CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use
  62. SSL_library_init(); // Initialize OpenSSL's SSL libraries
  63. SSL_load_error_strings(); // Load SSL error strings
  64. ERR_load_BIO_strings(); // Load BIO error strings
  65. OpenSSL_add_all_algorithms(); // Load all available encryption algorithms
  66. #else
  67. //
  68. // This needed by openssl, else OCSP_basic_verify fails
  69. //
  70. EVP_add_digest(EVP_sha1());
  71. // CRYPTO_malloc_init to be done first as per OpenSSL documentation
  72. CRYPTO_malloc_init();
  73. #endif
  74. }
  75. ae_error_t Get_OCSPResponse
  76. (
  77. /*in */ const char* urlOcspResponder,
  78. /*in */ const SIGMA_NONCE* ocspNonce,
  79. /*in */ const upse::Buffer& verifierCertificateDER,
  80. /*in */ const upse::Buffer& issuerCertificateDER,
  81. /*out*/ upse::Buffer& OcspResponseDER
  82. )
  83. {
  84. X509* verifierX509Cert = NULL;
  85. X509* issuerX509Cert = NULL;
  86. OCSP_REQUEST* pOcspReq = NULL;
  87. OCSP_CERTID* pCertID = NULL;
  88. OCSP_ONEREQ *pOneReq = NULL;
  89. #if defined(USE_CERTID_STACK)
  90. STACK_OF(OCSP_CERTID) *ids = NULL;
  91. #endif
  92. BIO *reqbio = NULL;
  93. const EVP_MD *cert_id_md = NULL;
  94. void* ocsp_response = NULL;
  95. uint32_t ocsp_response_size = 0;
  96. //OCSP_RESPONSE *pOcspResponse = NULL;
  97. char* ocsp_request = NULL;
  98. ae_error_t status = AE_FAILURE;
  99. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("Get_OCSPResponse: (int) nonce = ", *((int*)*ocspNonce));
  100. OpenSSL_init();
  101. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("init'd", 0);
  102. do
  103. {
  104. const unsigned char* x509CertNextDER = NULL;
  105. // Convert verifier to internal X509 data
  106. x509CertNextDER = verifierCertificateDER.getData();
  107. if (NULL == d2i_X509(&verifierX509Cert, &x509CertNextDER, verifierCertificateDER.getSize()))
  108. {
  109. Helper::RemoveCertificateChain();
  110. break;
  111. }
  112. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("converted verifier", 0);
  113. // Convert issuer to internal X509 data
  114. x509CertNextDER = issuerCertificateDER.getData();
  115. if (NULL == d2i_X509(&issuerX509Cert, &x509CertNextDER, issuerCertificateDER.getSize()))
  116. {
  117. Helper::RemoveCertificateChain();
  118. break;
  119. }
  120. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("converted issuer", 0);
  121. // Populate OCSP Request
  122. pOcspReq = OCSP_REQUEST_new();
  123. if (NULL == pOcspReq) break;
  124. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("created new request", 0);
  125. #if defined(USE_CERTID_STACK)
  126. ids = sk_OCSP_CERTID_new_null();
  127. if (NULL == ids) break;
  128. #endif
  129. cert_id_md = EVP_sha1();
  130. // Add Verifier cert and issuer to OCSP Request
  131. pCertID = OCSP_cert_to_id(cert_id_md, verifierX509Cert, issuerX509Cert);
  132. if (NULL == pCertID)
  133. {
  134. Helper::RemoveCertificateChain();
  135. break;
  136. }
  137. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("added cert and issuer to ocsp request", 0);
  138. #if defined(USE_CERTID_STACK)
  139. if (NULL == sk_OCSP_CERTID_push(ids, pCertID)) break;
  140. #endif
  141. pOneReq = OCSP_request_add0_id(pOcspReq, pCertID);
  142. if (NULL == pOneReq)
  143. {
  144. Helper::RemoveCertificateChain();
  145. break;
  146. }
  147. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("added id", 0);
  148. // Add nonce
  149. int retVal = OCSP_request_add1_nonce(pOcspReq, (uint8_t*)const_cast<SIGMA_NONCE*>(ocspNonce), NONCE_LENGTH);
  150. if (retVal <= 0)
  151. {
  152. Helper::RemoveCertificateChain();
  153. break;
  154. }
  155. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("added nonce", 0);
  156. reqbio = BIO_new(BIO_s_mem());
  157. if (NULL == reqbio) break;
  158. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("created new mem bio for request", 0);
  159. //
  160. // go from internal OpenSSL representation of request
  161. // to mem bio to binary
  162. //
  163. retVal = get_ocsp_req_size(reqbio, pOcspReq);
  164. if (retVal <= 0)
  165. {
  166. Helper::RemoveCertificateChain();
  167. break;
  168. }
  169. ocsp_request = (char*) malloc(reqbio->num_write);
  170. if (NULL == ocsp_request) break;
  171. memset(ocsp_request, 0x0, reqbio->num_write);
  172. retVal = reqbio->method->bread(reqbio, ocsp_request, static_cast<int>(reqbio->num_write));
  173. if (retVal <= 0)
  174. {
  175. Helper::RemoveCertificateChain();
  176. break;
  177. }
  178. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("convertd to binary", 0);
  179. ae_error_t netStatus = aesm_network_send_receive( urlOcspResponder,
  180. (const uint8_t *) ocsp_request,
  181. static_cast<uint32_t>(reqbio->num_write),
  182. (uint8_t **) &ocsp_response,
  183. &ocsp_response_size,
  184. POST,
  185. true);
  186. if (AE_SUCCESS != netStatus) {
  187. status = netStatus;
  188. break;
  189. }
  190. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("called network stack, ocsp_response_size = ", ocsp_response_size);
  191. BIO* respbio = BIO_new(BIO_s_mem());
  192. if (NULL == respbio) break;
  193. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("created new mem bio for response", 0);
  194. //
  195. // reverse what we did for req above,
  196. // go from binary to mem bio to internal OpenSSL representation of response
  197. //
  198. retVal = respbio->method->bwrite(respbio, (const char*) ocsp_response, ocsp_response_size);
  199. if (retVal <= 0) break;
  200. ae_error_t ocspRespError = AE_SUCCESS;
  201. OCSP_RESPONSE* pOcspResponse = d2i_OCSP_RESPONSE_bio(respbio, NULL);
  202. BIO_free(respbio);
  203. if(NULL == pOcspResponse)
  204. {
  205. status = AESM_PSE_PR_OCSP_RESPONSE_INTERNAL_ERROR;
  206. break;
  207. }
  208. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("converted ocsp response to internal format", 0);
  209. //
  210. // even though cse verifies/checks the ocsp response,
  211. // we can save time by doing the easy checks here
  212. // we'll check:
  213. // status
  214. // nonce
  215. // relationships among fields
  216. //
  217. retVal = OCSP_response_status(pOcspResponse);
  218. while (retVal != OCSP_RESPONSE_STATUS_SUCCESSFUL)
  219. {
  220. switch(retVal)
  221. {
  222. case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST:
  223. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_STATUS_MALFORMEDREQUEST; break;
  224. case OCSP_RESPONSE_STATUS_INTERNALERROR:
  225. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_STATUS_INTERNALERROR; break;
  226. case OCSP_RESPONSE_STATUS_TRYLATER:
  227. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_STATUS_TRYLATER; break;
  228. case OCSP_RESPONSE_STATUS_SIGREQUIRED:
  229. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_STATUS_SIGREQUIRED; break;
  230. case OCSP_RESPONSE_STATUS_UNAUTHORIZED:
  231. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_STATUS_UNAUTHORIZED; break;
  232. default:
  233. ocspRespError = AESM_PSE_PR_NO_OCSP_RESPONSE_ERROR; break;
  234. }
  235. break;
  236. }
  237. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("checked ocsp response status: ", ocspRespError);
  238. if ((AE_SUCCESS != ocspRespError) && (AESM_PSE_PR_OCSP_RESPONSE_STATUS_TRYLATER != ocspRespError)) {
  239. if (AESM_PSE_PR_OCSP_RESPONSE_STATUS_INTERNALERROR != ocspRespError) {
  240. // According to RFC6960, the response "internalError" indicates that the OCSP responder
  241. // reached an inconsistent internal state.The query should be retried,
  242. // potentially with another responder. So we don't delete cert chain here
  243. Helper::RemoveCertificateChain();
  244. }
  245. AESM_LOG_ERROR("%s", g_event_string_table[SGX_EVENT_OCSP_RESPONSE_ERROR]);
  246. }
  247. while (AE_SUCCESS == ocspRespError)
  248. {
  249. OCSP_BASICRESP* bs = OCSP_response_get1_basic(pOcspResponse);
  250. if (!bs)
  251. {
  252. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_INTERNAL_ERROR;
  253. break;
  254. }
  255. {
  256. //
  257. // above status check is "external", doesn't include revoked or not
  258. //
  259. int respStatus, reason;
  260. ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
  261. if(!OCSP_resp_find_status(bs, pCertID, &respStatus, &reason, &rev, &thisupd, &nextupd))
  262. {
  263. SGX_DBGPRINT_PRINT_STRING("OCSP: No status found.");
  264. }
  265. else if (V_OCSP_CERTSTATUS_REVOKED == respStatus) {
  266. ocspRespError = AESM_LTP_PSE_CERT_REVOKED;
  267. AESM_LOG_ERROR("%s", g_event_string_table[SGX_EVENT_PSE_CERT_REVOCATION]);
  268. break;
  269. }
  270. }
  271. int i;
  272. if ((i = OCSP_check_nonce(pOcspReq, bs)) <= 0)
  273. {
  274. if (i == -1)
  275. {
  276. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_NO_NONCE_ERROR;
  277. }
  278. else
  279. {
  280. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_NONCE_VERIFY_ERROR;
  281. }
  282. break;
  283. }
  284. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("checked nonce: ", ocspRespError);
  285. //
  286. // following checks relationships between fields in response, but does not verify signature
  287. // cse will do that (along with other checks we do above)
  288. //
  289. i = OCSP_basic_verify(bs, NULL, NULL, OCSP_NOCHECKS|OCSP_NOEXPLICIT|OCSP_NOVERIFY|OCSP_NOCHAIN|OCSP_NOSIGS);
  290. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("verified ocsp response: ", i);
  291. if(i <= 0)
  292. {
  293. ocspRespError = AESM_PSE_PR_OCSP_RESPONSE_VERIFY_ERROR;
  294. break;
  295. }
  296. break;
  297. }
  298. if (AE_SUCCESS != ocspRespError)
  299. {
  300. status = ocspRespError;
  301. break;
  302. }
  303. if (AE_FAILED(OcspResponseDER.Alloc((uint8_t*)ocsp_response, ocsp_response_size))) break;
  304. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("created ocsp response in der format", 0);
  305. status = AE_SUCCESS;
  306. } while (0);
  307. if (ocsp_response)
  308. {
  309. aesm_free_network_response_buffer((uint8_t*)ocsp_response);
  310. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("freed network response buffer", 0);
  311. }
  312. if (verifierX509Cert)
  313. {
  314. X509_free(verifierX509Cert);
  315. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("freed verifier cert", 0);
  316. }
  317. if (issuerX509Cert)
  318. {
  319. X509_free(issuerX509Cert);
  320. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("freed issuer cert", 0);
  321. }
  322. if (pOcspReq)
  323. {
  324. OCSP_REQUEST_free(pOcspReq);
  325. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("freed ocsp request", 0);
  326. }
  327. if (NULL != reqbio)
  328. {
  329. BIO_free(reqbio);
  330. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("freed request bio", 0);
  331. }
  332. if (NULL != ocsp_request)
  333. {
  334. free(ocsp_request);
  335. SGX_DBGPRINT_ONE_STRING_ONE_INT_OCSP("freed binary ocsp request", 0);
  336. }
  337. #if defined(USE_CERTID_STACK)
  338. if (ids) sk_OCSP_CERTID_free(ids);
  339. #endif
  340. return status;
  341. }