ae_error_t CertificateProvisioningProtocol::msg3_seq3_2_create_quote_signature_tlv(const upse::Buffer& quote, TLVsMsg& seq3_2_tlv_quote_signature) { ae_error_t status = AESM_PSE_PR_INTERNAL_ERROR; tlv_status_t tlv_status; do { if (sizeof(sgx_quote_t) > quote.getSize()) break; const sgx_quote_t* pQuote = (const sgx_quote_t*)quote.getData(); /* the QUOTE SIGNATURE TLV doesn't include Quote.signature_len */ uint32_t SigLen = pQuote->signature_len; if (sizeof(sgx_quote_t) + SigLen > quote.getSize()) break; const uint8_t *pSig = pQuote->signature; tlv_status = seq3_2_tlv_quote_signature.add_quote_signature(pSig, SigLen); status = tlv_error_2_pve_error(tlv_status); if (AE_FAILED(status)) break; status = AE_SUCCESS; } while (0); return status; }
ae_error_t CertificateProvisioningProtocol::msg3_create_header(const upse::Buffer& transactionID, uint32_t nonceSize, uint32_t quoteSize, uint32_t epidSigSize, uint32_t csrSize, provision_request_header_t& header) { ae_error_t status = AESM_PSE_PR_INTERNAL_ERROR; do { uint32_t seq2_0_tlv_block_cipher_text_size = BLOCK_CIPHER_TEXT_TLV_SIZE(quoteSize + epidSigSize + csrSize); uint32_t seq3_0_tlv_nonce_size = nonceSize; uint32_t seq4_0_tlv_mac_size = MAC_TLV_SIZE(MAC_SIZE); header.protocol = PSE_PROVISIONING; header.version = TLV_VERSION_1; header.type = static_cast<uint8_t>(TYPE_PSE_MSG3); if (XID_SIZE != transactionID.getSize()) break; if (memcpy_s(header.xid, sizeof(header.xid), transactionID.getData(), transactionID.getSize()) != 0) break; uint32_t totalSize = seq2_0_tlv_block_cipher_text_size + seq3_0_tlv_nonce_size + seq4_0_tlv_mac_size; uint32_t serializedSize = _htonl(totalSize); se_static_assert(sizeof(serializedSize) == sizeof(header.size)); if (memcpy_s(header.size, sizeof(header.size), &serializedSize, sizeof(serializedSize)) != 0) break; status = AE_SUCCESS; } while (0); return status; }
ae_error_t CertificateProvisioningProtocol::aesCMAC(const upse::Buffer& key, const upse::Buffer& message, upse::Buffer& cmac) { ae_error_t status = AE_FAILURE; do { if (key.getSize() != sizeof(sgx_aes_gcm_128bit_key_t)) break; status = cmac.Alloc(sizeof(sgx_cmac_128bit_tag_t)); if (AE_FAILED(status)) break; uint8_t* pCMAC; status = upse::BufferWriter(cmac).reserve(cmac.getSize(), &pCMAC); if (AE_FAILED(status)) break; sgx_status_t sgx_status; sgx_status = sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(key.getData()), message.getData(), message.getSize(), reinterpret_cast<sgx_cmac_128bit_tag_t *>(pCMAC)); if (SGX_SUCCESS != sgx_status) { status = AE_FAILURE; break; } status = AE_SUCCESS; } while (0); return status; }
ae_error_t CertificateProvisioningProtocol::aesGCMDecrypt(const upse::Buffer& iv, const upse::Buffer& key, const upse::Buffer& cipherText, const upse::Buffer& aad, const upse::Buffer& mac, upse::Buffer& plainText) { ae_error_t status = AE_FAILURE; do { if (key.getSize() != sizeof(sgx_aes_gcm_128bit_key_t)) break; status = plainText.Alloc(cipherText.getSize()); if (AE_FAILED(status)) break; uint8_t* pPlainText = NULL; status = upse::BufferWriter(plainText).reserve(plainText.getSize(), &pPlainText); if (AE_FAILED(status)) break; sgx_status_t sgx_status; sgx_status = sgx_rijndael128GCM_decrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(key.getData()), cipherText.getData(), cipherText.getSize(), pPlainText, iv.getData(), IV_SIZE, aad.getData(), aad.getSize(), reinterpret_cast<const sgx_aes_gcm_128bit_tag_t *>(mac.getData())); if (SGX_SUCCESS != sgx_status) { AESM_LOG_ERROR("%s", g_event_string_table[SGX_EVENT_PSE_CERT_PROV_INTEGRITY_ERROR]); status = AE_FAILURE; break; } status = AE_SUCCESS; } while (0); return status; }
ae_error_t CertificateProvisioningProtocol::encryptRSA_OAEP_SHA256(const public_key_t& publicKey, upse::BufferReader& plainTextReader, upse::Buffer& cipherText) { ae_error_t status = AE_FAILURE; void* rsa_pub_key = NULL; size_t dst_len = 0; do { if(SGX_SUCCESS != get_intel_rsa_pub_key(publicKey, &rsa_pub_key)) break; int plainTextSize = plainTextReader.getRemainingSize(); const uint8_t* pPlainText = NULL; if (AE_FAILED(plainTextReader.readRaw(&pPlainText))) break; int cipherTextSize = get_intel_pek_cipher_text_size(); if (AE_FAILED(cipherText.Alloc(cipherTextSize))) break; upse::BufferWriter cipherTextWriter(cipherText); uint8_t* pCipherText; if (AE_FAILED(cipherTextWriter.reserve(cipherText.getSize(), &pCipherText))) break; // Check the encrypt output length sgx_status_t res = sgx_rsa_pub_encrypt_sha256(rsa_pub_key, NULL, &dst_len, pPlainText, plainTextSize); if(res != SGX_SUCCESS || dst_len != cipherText.getSize()) break; res = sgx_rsa_pub_encrypt_sha256(rsa_pub_key, pCipherText, &dst_len, pPlainText, plainTextSize); if(res != SGX_SUCCESS) break; status = AE_SUCCESS; } while (0); free_intel_rsa_pub_key(rsa_pub_key); return status; }
ae_error_t CertificateProvisioningProtocol::aesGCMEncrypt(const upse::Buffer& iv, const upse::Buffer& key, const upse::Buffer& plainText, const upse::Buffer& aad, upse::Buffer& encryptedText, upse::Buffer& mac) { ae_error_t status = AE_FAILURE; do { if (key.getSize() != sizeof(sgx_aes_gcm_128bit_key_t)) break; status = encryptedText.Alloc(plainText.getSize()); if (AE_FAILED(status)) break; uint8_t* pEncryptedText; status = upse::BufferWriter(encryptedText).reserve(encryptedText.getSize(), &pEncryptedText); if (AE_FAILED(status)) break; status = mac.Alloc(sizeof(sgx_aes_gcm_128bit_tag_t)); if (AE_FAILED(status)) break; uint8_t* pMAC; status = upse::BufferWriter(mac).reserve(mac.getSize(), &pMAC); if (AE_FAILED(status)) break; sgx_status_t sgx_status; sgx_status = sgx_rijndael128GCM_encrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(key.getData()), plainText.getData(), plainText.getSize(), pEncryptedText, iv.getData(), IV_SIZE, aad.getData(), aad.getSize(), reinterpret_cast<sgx_aes_gcm_128bit_tag_t *>(pMAC)); if (SGX_SUCCESS != sgx_status) { status = AE_FAILURE; break; } status = AE_SUCCESS; } while (0); return status; }
ae_error_t CertificateProvisioningProtocol::msg3_seq3_1_create_quote_tlv(const upse::Buffer& quoteBuffer, TLVsMsg& quoteTLV) { ae_error_t status = AESM_PSE_PR_INTERNAL_ERROR; tlv_status_t tlv_status; do { if (sizeof(sgx_quote_t) > quoteBuffer.getSize()) break; const sgx_quote_t* pQuote = (const sgx_quote_t*)quoteBuffer.getData(); tlv_status = quoteTLV.add_quote((uint8_t*)pQuote, static_cast<uint32_t>(sizeof(sgx_quote_t)-sizeof(pQuote->signature_len))); status = tlv_error_2_pve_error(tlv_status); if (AE_FAILED(status)) break; } while (0); return status; }
ae_error_t CertificateProvisioningProtocol::sendReceive(const upse::Buffer& sendSerialized, upse::Buffer& recvSerialized) { ae_error_t status = AE_FAILURE; uint8_t* recv = NULL; uint32_t recv_size = 0; do { AESM_DBG_INFO("start send msg"); status = AESMNetworkEncoding::aesm_send_recv_msg_encoding(m_url.c_str(), const_cast<uint8_t *>(sendSerialized.getData()), sendSerialized.getSize(), recv, recv_size); if (AE_FAILED(status)) break; AESM_DBG_INFO("msg received with size %u", recv_size); status = recvSerialized.Alloc(recv_size); if (AE_FAILED(status)) break; AESM_DBG_INFO("buffer alloced"); status = upse::BufferWriter(recvSerialized).writeRaw(recv, recv_size); if (AE_FAILED(status)) break; AESM_DBG_INFO("buffer written"); status = AE_SUCCESS; } while (0); if (NULL != recv) AESMNetworkEncoding::aesm_free_response_msg(recv); return status; }
//********************************************************************* // Call quoting enclave to convert report to name-based quote //********************************************************************* static ae_error_t do_get_quote ( /*in */ upse::Buffer& reportBuffer, /*in */ upse::Buffer& sigRLBuffer, /*out*/ upse::Buffer& quoteBuffer ) { // Call QE to convert REPORT to a name-based QUOTE ae_error_t status = AE_FAILURE; ae_error_t tmp_status = AE_SUCCESS; do { #ifndef FAKE_QUOTE uint32_t nQuote; // in - Quote buffer size sgx_report_t enclaveReport; // in sgx_quote_sign_type_t quote_type; // in sgx_spid_t spid = {{0}}; // in uint8_t* pSigRL = NULL; // in uint32_t nSigRL = 0; // in - Sig RL buffer size memset(&enclaveReport, 0, sizeof(enclaveReport)); nSigRL = sigRLBuffer.getSize(); if (0 != nSigRL) pSigRL = const_cast<uint8_t*>(sigRLBuffer.getData()); if (SGX_SUCCESS != sgx_calc_quote_size(pSigRL, nSigRL, &nQuote)) break; tmp_status = quoteBuffer.Alloc(nQuote); if (AE_FAILED(tmp_status)) break; upse::BufferWriter bwQuote(quoteBuffer); uint8_t* pQuote; tmp_status = bwQuote.reserve(nQuote, &pQuote); // out if (AE_FAILED(tmp_status)) break; quote_type = SGX_UNLINKABLE_SIGNATURE; // or SGX_LINKABLE_SIGNATURE // LSB16(SHA256("SGX PSE PROVISIONING SERVER")) // const char* SPID_VALUE = "SGX PSE PROVISIONING SERVER"; // sgx_sha256_hash_t spid_hash; // sgx_sha256_msg((const uint8_t*)SPID_VALUE, strlen(SPID_VALUE), &spid_hash); // memcpy_s(spid.id, sizeof(spid.id), &spid_hash[0], 16); static uint8_t spid_hash[] = { 0x32, 0x81, 0xE5, 0x9E, 0xB1, 0x23, 0xFA, 0xCD, 0x56, 0xDB, 0x62, 0x1E, 0x3B, 0x37, 0xFB, 0xE2 }; memcpy_s(spid.id, sizeof(spid.id), spid_hash, sizeof(spid_hash)); if (reportBuffer.getSize() != sizeof(enclaveReport)) break; memcpy_s(&enclaveReport, reportBuffer.getSize(), reportBuffer.getData(), reportBuffer.getSize()); aesm_error_t result; result = AESMLogic::get_quote( (uint8_t*)&enclaveReport, sizeof(enclaveReport), quote_type, (uint8_t*)&spid, sizeof(spid), NULL, 0, pSigRL, nSigRL, NULL, 0, (uint8_t*)pQuote, nQuote); if (result == AESM_BUSY) { //EPID_PROVISION triggered, make sure previous EPID provision has finished ae_error_t temp_ret = wait_pve_thread(); BREAK_IF_TRUE(AE_SUCCESS != temp_ret , status, PSE_PR_PCH_EPID_UNKNOWN_ERROR); //redo get_quote result = AESMLogic::get_quote( (uint8_t*)&enclaveReport, sizeof(enclaveReport), quote_type, (uint8_t*)&spid, sizeof(spid), NULL, 0, pSigRL, nSigRL, NULL, 0, (uint8_t*)pQuote, nQuote); } BREAK_IF_TRUE(AESM_OUT_OF_EPC == result, status, AESM_AE_OUT_OF_EPC); BREAK_IF_TRUE(AESM_SUCCESS != result, status, AESM_PSE_PR_GET_QUOTE_ERROR); #else const uint16_t SIGNATURE_LENGTH = 32; tmp_status = quoteBuffer.Alloc(sizeof(sgx_quote_t) + SIGNATURE_LENGTH); if (AE_FAILED(tmp_status)) break; sgx_quote_t* pQuote; tmp_status = upse::BufferWriter(quoteBuffer).reserve(quoteBuffer.getSize(), (uint8_t**)&pQuote); if (AE_FAILED(tmp_status)) break; uint16_t CPUSVN = 1; pQuote->version = 1; memcpy_s(pQuote->epid_group_id, sizeof(pQuote->epid_group_id), &GID_TO_USE, sizeof(GID_TO_USE)); pQuote->report_body.isv_prod_id = 0x0002; //0x8086; pQuote->report_body.isv_svn = 1; memcpy_s(pQuote->report_body.cpu_svn, sizeof(pQuote->report_body.cpu_svn), &CPUSVN, sizeof(CPUSVN)); const sgx_report_t* pReport = (sgx_report_t*)reportBuffer.getData(); memcpy_s(pQuote->report_body.report_data, sizeof(pQuote->report_body.report_data), pReport->body.report_data, sizeof(pQuote->report_body.report_data)); pQuote->signature_len = SIGNATURE_LENGTH; //NOTE: The signature is not valid when doing a FAKE_QUOTE #endif status = AE_SUCCESS; } while (0); if ((AE_FAILURE == status) && AE_FAILED(tmp_status)) status = tmp_status; SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status); return status; }
ae_error_t upsePersistentStorage::Write(aesm_data_id_t data_id, upse::Buffer& data) { ae_error_t status = AESM_PSE_PR_PERSISTENT_STORAGE_WRITE_ERROR; do { if (AE_FAILED(aesm_write_data(FT_PERSISTENT_STORAGE, data_id, data.getData(), data.getSize()))) break; status = AE_SUCCESS; } while (0); return status; }
ae_error_t pse_pr_interface_psda::ExchangeS2AndS3(/*in*/ const uint8_t* pse_instance_id, /*in */ const upse::Buffer& s2, /*out*/ upse::Buffer& s3) { ae_error_t status = AE_FAILURE; lt_session_m7_t* pLt_session_m7 = NULL; lt_session_m8_t* pLt_session_m8 = NULL; uint32_t lt_session_m7_size = static_cast<uint32_t>(sizeof(lt_session_m7_t) + s2.getSize()); uint32_t lt_session_m8_size = 10000; do { pLt_session_m7 = (lt_session_m7_t*)malloc(lt_session_m7_size); BREAK_IF_TRUE( (NULL == pLt_session_m7), status, AESM_PSE_PR_INSUFFICIENT_MEMORY_ERROR); pLt_session_m8 = (lt_session_m8_t*)malloc(lt_session_m8_size); BREAK_IF_TRUE( (NULL == pLt_session_m8), status, AESM_PSE_PR_INSUFFICIENT_MEMORY_ERROR); memset(pLt_session_m8, 0, lt_session_m8_size); memcpy_s(pLt_session_m7->msg_hdr.pse_instance_id, SW_INSTANCE_ID_SIZE, pse_instance_id, SW_INSTANCE_ID_SIZE); pLt_session_m7->msg_hdr.msg_type = _htonl(PSDA_MSG_TYPE_LT_M7); pLt_session_m7->msg_hdr.msg_len = _htonl(s2.getSize()); memcpy_s(&pLt_session_m7->msg7, s2.getSize(), s2.getData(), s2.getSize()); commBuf_s3.TxBuf->buffer = pLt_session_m7; commBuf_s3.TxBuf->length = lt_session_m7_size; commBuf_s3.RxBuf->buffer = pLt_session_m8; commBuf_s3.RxBuf->length = lt_session_m8_size; status = PSDAService::instance().send_and_recv( PSDA_COMMAND_LT, &commBuf_s3, &responseCode, NO_RETRY_ON_SESSION_LOSS); AESM_DBG_INFO("JHI_SendAndRecv2 response_code is %d", responseCode); if (status != AE_SUCCESS) { AESM_LOG_ERROR("%s", g_event_string_table[SGX_EVENT_DAL_COMM_FAILURE]); break; } if (PSDA_SUCCESS != responseCode) { AESM_LOG_ERROR("%s", g_event_string_table[SGX_EVENT_DAL_SIGMA_ERROR]); BREAK_IF_TRUE( (responseCode == PSDA_INTEGRITY_ERROR), status, AESM_PSDA_LT_SESSION_INTEGRITY_ERROR); BREAK_IF_TRUE( (responseCode == PSDA_INTERNAL_ERROR) , status, AESM_PSDA_INTERNAL_ERROR); BREAK_IF_TRUE( (responseCode == PSDA_PLATFORM_KEYS_REVOKED) , status, AESM_PSDA_PLATFORM_KEYS_REVOKED); BREAK_IF_TRUE( (responseCode == PSDA_PERSISTENT_DATA_WRITE_THROTTLED) , status, AESM_PSDA_WRITE_THROTTLED); BREAK_IF_TRUE( (responseCode != PSDA_SUCCESS) , status, AESM_PSDA_INTERNAL_ERROR); } uint32_t msg_len = _ntohl(pLt_session_m8->msg_hdr.msg_len); uint32_t msg_type = _ntohl(pLt_session_m8->msg_hdr.msg_type); if (msg_type != PSDA_MSG_TYPE_LT_M8) { status = AE_FAILURE; break; } if (commBuf_s3.RxBuf->length <= sizeof(pLt_session_m8->msg_hdr) || msg_len != commBuf_s3.RxBuf->length - sizeof(pLt_session_m8->msg_hdr)) { AESM_DBG_INFO("Received invalid S3 message from PSDA!"); status = AE_FAILURE; break; } status = s3.Alloc(msg_len); BREAK_IF_FAILED(status); upse::BufferWriter bw(s3); status = bw.writeRaw((UINT8*)&pLt_session_m8->msg8, msg_len); BREAK_IF_FAILED(status); status = AE_SUCCESS; } while (0); if (NULL != pLt_session_m7) free(pLt_session_m7); if (NULL != pLt_session_m8) free(pLt_session_m8); return status; }
ae_error_t CertificateProvisioningProtocol::msg3_generate(const upse::Buffer& csrBuffer, const upse::Buffer& quoteBuffer, upse::Buffer& serializedMsg3) { ae_error_t status = AE_FAILURE; tlv_status_t tlv_status = TLV_UNKNOWN_ERROR; provision_request_header_t serializedHeader; memset(&serializedHeader, 0, sizeof(serializedHeader)); TLVsMsg seq2_0_tlv_nonce; TLVsMsg seq3_0_tlv_block_cipher_text; TLVsMsg seq3_1_tlv_quote; TLVsMsg seq3_2_tlv_quote_signature; TLVsMsg seq3_3_tlv_x509_csr; TLVsMsg seq4_0_tlv_mac; do { tlv_status = seq2_0_tlv_nonce.add_nonce(Nonce.getData(), Nonce.getSize()); status = tlv_error_2_pve_error(tlv_status); if (AE_FAILED(status)) break; status = msg3_seq3_1_create_quote_tlv(quoteBuffer, seq3_1_tlv_quote); if (AE_FAILED(status)) break; status = msg3_seq3_2_create_quote_signature_tlv(quoteBuffer, seq3_2_tlv_quote_signature); if (AE_FAILED(status)) break; tlv_status = seq3_3_tlv_x509_csr.add_x509_csr(csrBuffer.getData(), csrBuffer.getSize()); status = tlv_error_2_pve_error(tlv_status); if (AE_FAILED(status)) break; status = msg3_create_header(TransactionID, seq2_0_tlv_nonce.get_tlv_msg_size(), seq3_1_tlv_quote.get_tlv_msg_size(), seq3_2_tlv_quote_signature.get_tlv_msg_size(), seq3_3_tlv_x509_csr.get_tlv_msg_size(), serializedHeader); if (AE_FAILED(status)) break; upse::Buffer mac; status = msg3_seq3_0_create_block_cipher_text_tlv(seq3_1_tlv_quote, seq3_2_tlv_quote_signature, seq3_3_tlv_x509_csr, seq2_0_tlv_nonce, serializedHeader, EK2, seq3_0_tlv_block_cipher_text, mac); if (AE_FAILED(status)) break; tlv_status = seq4_0_tlv_mac.add_mac(mac.getData()); status = tlv_error_2_pve_error(tlv_status); if (AE_FAILED(status)) break; //********************************************************************* // Prepare serialized message buffer //********************************************************************* uint32_t size_msg3 = static_cast<uint32_t>(PROVISION_REQUEST_HEADER_SIZE + seq2_0_tlv_nonce.get_tlv_msg_size() + seq3_0_tlv_block_cipher_text.get_tlv_msg_size() + seq4_0_tlv_mac.get_tlv_msg_size()); status = serializedMsg3.Alloc(size_msg3); if (AE_FAILED(status)) break; serializedMsg3.zeroMemory(); upse::BufferWriter bwMsg3(serializedMsg3); // Write serialized request header to serialized message status = bwMsg3.writeRaw((uint8_t*)&serializedHeader, sizeof(serializedHeader)); if (AE_FAILED(status)) break; // Write sequence 2.0 - Nonce TLV status = bwMsg3.writeRaw(const_cast<uint8_t*>(seq2_0_tlv_nonce.get_tlv_msg()), seq2_0_tlv_nonce.get_tlv_msg_size()); if (AE_FAILED(status)) break; // Write sequence 3.0 - Block Cipher Text TLV (contains 3.1, 3.2, and 3.3 as encrypted payload) status = bwMsg3.writeRaw(const_cast<uint8_t*>(seq3_0_tlv_block_cipher_text.get_tlv_msg()), seq3_0_tlv_block_cipher_text.get_tlv_msg_size()); if (AE_FAILED(status)) break; // Write sequence 4.0 - MAC TLV status = bwMsg3.writeRaw(const_cast<uint8_t*>(seq4_0_tlv_mac.get_tlv_msg()), seq4_0_tlv_mac.get_tlv_msg_size()); if (AE_FAILED(status)) break; status = AE_SUCCESS; } while (0); return status; }