ae_error_t Helper::PrepareCertificateChainVLR( /*in*/ std::list<upse::Buffer>& certChain, /*out*/ upse::Buffer& certChainVLR) { ae_error_t status = AESM_PSE_PR_LOAD_VERIFIER_CERT_ERROR; try { do { int nPaddedBytes = 0; int nCertChain = 0; #if !defined(LEAFTOROOT) #error LEAFTOROOT not #defined #endif // // spec'd behavior is to receive certs in leaft to root order // then, it only makes sense to store them leaf to root // but sigma wants them root to leaf // we'll leave the #if here since, cumulatively, it shows how to traverse // in both directions // #if !LEAFTOROOT SGX_DBGPRINT_PRINT_STRING_LTP("leaf cert to root cert direction, padding"); std::list<upse::Buffer>::reverse_iterator it; for (it = certChain.rbegin(); it != certChain.rend(); ++it) { int nSize = (*it).getSize(); nPaddedBytes += REQUIRED_PADDING_DWORD_ALIGNMENT(nSize); nCertChain += nSize; } #else SGX_DBGPRINT_PRINT_STRING_LTP("root cert to leaf cert direction, padding"); std::list<upse::Buffer>::iterator it; for (it = certChain.begin(); it != certChain.end(); ++it) { int nSize = (*it).getSize(); nPaddedBytes += REQUIRED_PADDING_DWORD_ALIGNMENT(nSize); nCertChain += nSize; } #endif SGX_DBGPRINT_PRINT_STRING_LTP("less cert padding"); //NRG: This doesn't work, but should. It should replace the previous nPaddedBytes = REQUIRED_PADDING_DWORD_ALIGNMENT(nCertChain); if(UINT16_MAX - ((int)sizeof(SIGMA_VLR_HEADER) + nPaddedBytes) < nCertChain){ break; } int nLength = static_cast<int>(sizeof(SIGMA_VLR_HEADER)) + nPaddedBytes + nCertChain; certChainVLR.Alloc(nLength); upse::BufferWriter bw(certChainVLR); VERIFIER_CERT_CHAIN_VLR* pVLR; uint8_t* p; if (AE_FAILED(bw.reserve(nLength, &p))) break; pVLR = (VERIFIER_CERT_CHAIN_VLR*)p; pVLR->VlrHeader.ID = VERIFIER_CERTIFICATE_CHAIN_VLR_ID; pVLR->VlrHeader.PaddedBytes = (UINT8)nPaddedBytes; pVLR->VlrHeader.Length = (UINT16)nLength; memset(pVLR->VerifierCertificateChain, 0, nPaddedBytes + nCertChain); int ndx = 0; // // see above // #if (!LEAFTOROOT) SGX_DBGPRINT_PRINT_STRING_LTP("leaf cert to root cert direction"); for (it = certChain.rbegin(); it != certChain.rend(); ++it) { memcpy_s(pVLR->VerifierCertificateChain + ndx, (*it).getSize(), (*it).getData(), (*it).getSize()); ndx += (*it).getSize(); } #else SGX_DBGPRINT_PRINT_STRING_LTP("root cert to leaf cert direction"); for (it = certChain.begin(); it != certChain.end(); ++it) { memcpy_s(pVLR->VerifierCertificateChain + ndx, (*it).getSize(), (*it).getData(), (*it).getSize()); ndx += (*it).getSize(); } #endif status = AE_SUCCESS; } while (0); } catch(...) { } SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status); return status; }
ae_error_t SigmaHelper::GetOcspResponseFromServer ( /*in */ const std::list<upse::Buffer>& certChain, /*in */ const OCSP_REQ& ocspReq, /*out*/ upse::Buffer& ocspResp ) { ae_error_t status = AE_FAILURE; int nPaddedBytes = 0; int nTotalOcspBytes = 0; do { if (ocspReq.ReqType == NO_OCSP) { status = AE_SUCCESS; break; } const char *url = EndpointSelectionInfo::instance().get_server_url( PSE_OCSP); if (url == NULL){ return OAL_CONFIG_FILE_ERROR; } // Load the root certificate into a local buffer upse::Buffer rootCert; SigmaHelper::GetRootCA(rootCert); std::list<upse::Buffer> ocspResponseList; // loop through chain and get an OCSP Response for each certificate/issuer pair bool fDone = false; // // certs were added leaf to root direction (assuming server functions according to spec) // std::list<upse::Buffer>::const_iterator itCertificate = certChain.begin(); do { if (itCertificate == certChain.end()) { status = AE_FAILURE; break; } upse::Buffer ocspResponse; const upse::Buffer& verifierCertificate = *itCertificate; ++itCertificate; int busy_loop = 0; do { if (itCertificate != certChain.end()) { const upse::Buffer& issuerCertificate = *itCertificate; status = Get_OCSPResponse(url, &ocspReq.OcspNonce, verifierCertificate, issuerCertificate, ocspResponse); } else { fDone = true; const upse::Buffer& issuerCertificate = rootCert; status = Get_OCSPResponse(url, &ocspReq.OcspNonce, verifierCertificate, issuerCertificate, ocspResponse); } if (AESM_PSE_PR_OCSP_RESPONSE_STATUS_TRYLATER != status) break; se_sleep(OCSP_BUSY_RETRY_SLEEP_MILLISECONDS); } while (busy_loop++ < MAX_OCSP_BUSY_RETRIES); if (AE_FAILED(status)) break; nPaddedBytes += REQUIRED_PADDING_DWORD_ALIGNMENT(ocspResponse.getSize()); nTotalOcspBytes += ocspResponse.getSize(); ocspResponseList.push_back(ocspResponse); } while (!fDone); if (AE_FAILED(status)) break; if (0 == ocspResponseList.size()) { status = AE_FAILURE; break; } nPaddedBytes = REQUIRED_PADDING_DWORD_ALIGNMENT(nTotalOcspBytes); if(UINT16_MAX-((int)sizeof(SIGMA_VLR_HEADER) + nPaddedBytes) < nTotalOcspBytes){ status = AE_FAILURE; break; } int nLength = static_cast<int>(sizeof(SIGMA_VLR_HEADER)) + nPaddedBytes + nTotalOcspBytes; ocspResp.Alloc(nLength); upse::BufferWriter bw(ocspResp); uint8_t* p; status = bw.reserve(nLength, &p); if (AE_FAILED(status)) break; OCSP_RESPONSE_VLR* pVLR = (OCSP_RESPONSE_VLR*)p; pVLR->VlrHeader.ID = OCSP_RESPONSE_VLR_ID; pVLR->VlrHeader.PaddedBytes = (UINT8)nPaddedBytes; pVLR->VlrHeader.Length = (UINT16)nLength; memset(pVLR->OcspResponse, 0, nPaddedBytes + nTotalOcspBytes); int nNext = 0; // // order above doesn't really matter since it's between verifier/host and ocsp responder // and each request/response is independent // spec basically says what's correct here // but we'll leave condition to show how to traverse in either order // #if !defined(LEAFTOROOT) #error LEAFTOROOT not defined #endif #if !LEAFTOROOT // // this clause adds responses from root to leaf // SGX_DBGPRINT_PRINT_STRING_LTP("root ocsp to leaf ocsp direction"); std::list<upse::Buffer>::reverse_iterator itRespList = ocspResponseList.rbegin(); for ( ; itRespList != ocspResponseList.rend(); ++itRespList) { const upse::Buffer& item = *itRespList; memcpy_s(pVLR->OcspResponse + nNext, item.getSize(), item.getData(), item.getSize()); nNext += item.getSize(); } #else SGX_DBGPRINT_PRINT_STRING_LTP("leaf ocsp to root ocsp direction"); // // this clause adds responses from leaf to root // std::list<upse::Buffer>::iterator itRespList = ocspResponseList.begin(); for ( ; itRespList != ocspResponseList.end(); ++itRespList) { const upse::Buffer& item = *itRespList; memcpy_s(pVLR->OcspResponse + nNext, item.getSize(), item.getData(), item.getSize()); nNext += item.getSize(); } #endif Helper::write_ocsp_response_vlr(ocspResp); status = AE_SUCCESS; } while (0); if (status == OAL_NETWORK_UNAVAILABLE_ERROR) { if (ocspReq.ReqType == CACHED && AE_SUCCEEDED(Helper::read_ocsp_response_vlr(ocspResp))) { status = AE_SUCCESS; } } SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status); return status; }