Example #1
0
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;
}
Example #2
0
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::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;
}
ae_error_t CertificateProvisioningProtocol::SendM1_ReceiveM2
(   /*in */ const uint32_t gid,
    /*out*/ upse::Buffer& nonce,
    /*out*/ upse::Buffer& sigRLBuffer
)
{
    ae_error_t status = AE_FAILURE;

    upse::Buffer serializedMsg1;
    upse::Buffer serializedMsg2;

    do
    {
        BREAK_IF_FALSE((m_is_initialized), status, AESM_PSE_PR_BACKEND_NOT_INITIALIZED);

        BREAK_IF_FALSE( (msg_next_state_M1 == m_nextState), status, AESM_PSE_PR_CALL_ORDER_ERROR);

        status = msg1_generate(*(const GroupId*)&gid, serializedMsg1);
        BREAK_IF_FAILED_ERR(status, AESM_PSE_PR_BACKEND_MSG1_GENERATE);
//        BREAK_IF_FAILED(status);

        status = sendReceive(serializedMsg1, serializedMsg2);
        if (AE_FAILED(status))
            break;

        status = msg2_process(serializedMsg2, nonce, sigRLBuffer);
        if (AE_FAILED(status))
            break;

        m_nextState = msg_next_state_M3;
    } while (0);

    return status;
}
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;
}
Example #6
0
aesm_error_t AESMLogic::get_launch_token(
    const uint8_t * mrenclave, uint32_t mrenclave_size,
    const uint8_t *public_key, uint32_t public_key_size,
    const uint8_t *se_attributes, uint32_t se_attributes_size,
    uint8_t * lictoken, uint32_t lictoken_size)
{
    AESM_DBG_INFO("enter function");

    CHECK_SERVICE_STATUS;
    AESMLogicLock lock(_le_mutex);
    CHECK_SERVICE_STATUS;

    ae_error_t ret_le = AE_SUCCESS;
    if (NULL == mrenclave ||
        NULL == public_key ||
        NULL == se_attributes ||
        NULL == lictoken)
    {
        //sizes are checked in CLEClass::get_launch_token()
        AESM_DBG_TRACE("Invalid parameter");
        return AESM_PARAMETER_ERROR;
    }
    ae_error_t ae_ret = CLEClass::instance().load_enclave();
    if(ae_ret == AE_SERVER_NOT_AVAILABLE)
    {
        AESM_LOG_ERROR("%s", g_event_string_table[SGX_EVENT_SERVICE_UNAVAILABLE]);
        AESM_DBG_FATAL("LE not loaded due to AE_SERVER_NOT_AVAILABLE, possible SGX Env Not Ready");
        return AESM_NO_DEVICE_ERROR;
    }
    else if(AE_FAILED(ae_ret))
    {
        AESM_DBG_ERROR("LE not loaded:%d", ae_ret);
        return AESM_UNEXPECTED_ERROR;
    }
    ret_le = static_cast<ae_error_t>(CLEClass::instance().get_launch_token(
        const_cast<uint8_t *>(mrenclave), mrenclave_size,
        const_cast<uint8_t *>(public_key), public_key_size,
        const_cast<uint8_t *>(se_attributes), se_attributes_size,
        lictoken, lictoken_size));

    switch (ret_le)
    {
    case AE_SUCCESS:
        return AESM_SUCCESS;
    case LE_INVALID_PARAMETER:
        AESM_DBG_TRACE("Invalid parameter");
        return AESM_PARAMETER_ERROR;
    case LE_INVALID_ATTRIBUTE:
    case LE_INVALID_PRIVILEGE_ERROR:
        AESM_DBG_TRACE("Launch token error");
        return AESM_GET_LICENSETOKEN_ERROR;
    case LE_WHITELIST_UNINITIALIZED_ERROR:
        AESM_DBG_TRACE("LE whitelist uninitialized error");
        return AESM_UNEXPECTED_ERROR;
    default:
        AESM_DBG_WARN("unexpeted error %d", ret_le);
        return AESM_UNEXPECTED_ERROR;
    }
}
Example #7
0
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;
}
Example #8
0
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::msg1_create_seq2_1(TLVsMsg& seq2_1_tlv_block_cipher_info)
{
    //* 2.1 Block Cipher Info TLV (TLV Type, Type, Version, Size, [SK])
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status;

    do
    {
        status = get_random_value(SK_SIZE, M1SK);
        if (AE_FAILED(status))
            break;

        tlv_status = seq2_1_tlv_block_cipher_info.add_block_cipher_info(M1SK.getData());
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;
    } while (0);

    return status;
}
Example #10
0
ae_error_t CertificateProvisioningProtocol::get_random_value(uint32_t size, upse::Buffer& randomValue)
{
    ae_error_t status = AE_FAILURE;

    do
    {
        status = randomValue.Alloc(size);
        if (AE_FAILED(status))
            break;

        uint8_t* p;
        upse::BufferWriter bw(randomValue);
        status = bw.reserve(size, &p);
        if (AE_FAILED(status))
            break;

        status = aesm_read_rand(p, size);

    } while (0);

    return status;
}
Example #11
0
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;
}
Example #12
0
ae_error_t CertificateProvisioningProtocol::msg1_create_seq2_0(const TLVsMsg& seq2_1_tlv_block_cipher_info, TLVsMsg& seq2_0_tlv_cipher_text)
{
    //* 2.0 Cipher Text TLV (TLV Type, Type, Version, Size, [KeyID, EncryptedPayload is 2.1])
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status;

    do
    {
        upse::Buffer seq2_1_encrypted_tlv;
        upse::Buffer encryptedBlockCipherInfo;

        const public_key_t& public_key = get_intel_pek();

        // Encrypt TLV 2.1
        upse::Buffer blockCipherInfo;
        status = blockCipherInfo.Alloc(seq2_1_tlv_block_cipher_info.get_tlv_msg(), seq2_1_tlv_block_cipher_info.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        upse::BufferReader blockCipherInfoReader(blockCipherInfo);

        status = encryptRSA_OAEP_SHA256(public_key, blockCipherInfoReader, encryptedBlockCipherInfo);
        if (AE_FAILED(status))
            break;

        tlv_status = seq2_0_tlv_cipher_text.add_cipher_text(encryptedBlockCipherInfo.getData(), encryptedBlockCipherInfo.getSize(), PEK_3072_PUB);
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;
    } while (0);


    return status;
}
Example #13
0
aesm_error_t AESMLogic::white_list_register(
        const uint8_t *white_list_cert, uint32_t white_list_cert_size)
{
    AESM_DBG_INFO("enter function");
    CHECK_SERVICE_STATUS;
    AESMLogicLock lock(_le_mutex);
    CHECK_SERVICE_STATUS;
    ae_error_t ret_le = AE_SUCCESS;
    if (NULL == white_list_cert||0==white_list_cert_size){
        AESM_DBG_TRACE("Invalid parameter");
        return AESM_PARAMETER_ERROR;
    }
    ae_error_t ae_ret = CLEClass::instance().load_enclave();
    if(ae_ret == AE_SERVER_NOT_AVAILABLE)
    {
        AESM_DBG_WARN("LE not loaded due to AE_SERVER_NOT_AVAILABLE, possible SGX Env Not Ready");
        ret_le = save_unverified_white_list(white_list_cert, white_list_cert_size);
    }
    else if(AE_FAILED(ae_ret))
    {
        AESM_DBG_ERROR("LE not loaded:%d", ae_ret);
        return AESM_UNEXPECTED_ERROR;
    }else{
        ret_le = static_cast<ae_error_t>(CLEClass::instance().white_list_register(
            white_list_cert, white_list_cert_size));
    }

    switch (ret_le)
    {
    case AE_SUCCESS:
        return AESM_SUCCESS;
    case LE_INVALID_PARAMETER:
        AESM_DBG_TRACE("Invalid parameter");
        return AESM_PARAMETER_ERROR;
    case LE_INVALID_ATTRIBUTE:
        AESM_DBG_TRACE("Launch token error");
        return AESM_GET_LICENSETOKEN_ERROR;
    default:
        AESM_DBG_WARN("unexpeted error %d", ret_le);
        return AESM_UNEXPECTED_ERROR;
    }
}
Example #14
0
ae_error_t ecall_tGenM7
(
    /*in */ const SIGMA_S1_MESSAGE*      pS1,
    /*in */ const EPID_SIG_RL*           pSigRL,
    /*in */ uint32_t  nTotalLen_SigRL,
    /*in */ const uint8_t*               pOcspResp, 
    /*in */ uint32_t  nLen_OcspResp,
    /*in */ const uint8_t*               pVerifierCert,
    /*in */ uint32_t  nLen_VerifierCert,
    /*in */ const pairing_blob_t* pPairingBlob,
    /*in */ uint32_t  nMax_S2,
    /*out*/       SIGMA_S2_MESSAGE*      pS2,
    /*out*/ uint32_t* pnLen_S2
)
{
    ae_error_t status = AE_FAILURE;

    PSE_PR_SAFE_DELETE(s_pVerifier);

    do
    {
        s_pVerifier = new (std::nothrow) TEpidSigmaVerifier;
        BREAK_IF_TRUE((NULL == s_pVerifier), status, PSE_PR_INSUFFICIENT_MEMORY_ERROR);

        status = s_pVerifier->GenM7(
            pS1, 
            pSigRL, 
            nTotalLen_SigRL,
            pOcspResp, nLen_OcspResp, 
            pVerifierCert, nLen_VerifierCert,
            pPairingBlob,
            nMax_S2, pS2, pnLen_S2);
        BREAK_IF_FAILED(status);

    } while (0);

    if (AE_FAILED(status))
        PSE_PR_SAFE_DELETE(s_pVerifier);

    return status;
}
Example #15
0
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;
}
Example #16
0
ae_error_t CertificateProvisioningProtocol::msg1_create_seq3_0(const TLVsMsg& seq3_1_tlv_epid_gid, const provision_request_header_t& serializedHeader,
                               const upse::Buffer& ek1, TLVsMsg& seq3_0_tlv_block_cipher_text, upse::Buffer& mac)
{
    //* 3.0 Block Cipher Text TLV (TLV Type, Type, Version, Size, [IV, EncryptedPayload is 3.1])
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status;

    do
    {
        status = get_random_value(IV_SIZE, M1IV);
        if (AE_FAILED(status))
            break;

        upse::Buffer aad;
        status = aad.Alloc(sizeof(serializedHeader));
        if (AE_FAILED(status))
            break;

        upse::BufferWriter aadWriter(aad);
        status = aadWriter.writeRaw((const uint8_t*)&serializedHeader, sizeof(serializedHeader));
        if (AE_FAILED(status))
            break;

        upse::Buffer epidGid;
        status = epidGid.Alloc(seq3_1_tlv_epid_gid.get_tlv_msg(), seq3_1_tlv_epid_gid.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        upse::Buffer encryptedPayload;
        status = aesGCMEncrypt(M1IV, ek1, epidGid, aad, encryptedPayload, mac);
        if (AE_FAILED(status))
            break;

        tlv_status = seq3_0_tlv_block_cipher_text.add_block_cipher_text(M1IV.getData(), encryptedPayload.getData(), encryptedPayload.getSize());
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;

    } while (0);

    return status;
}
Example #17
0
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;
}
//
// return values
// SUCCESS:
// NO_LONGTERM_PAIRING_BLOB:
// DONT_NEED_UPDATE_PAIR_LTP: psda svn now up to date
// MAY_NEED_UPDATE_LTP: psda updated, but may not be up to date
// OLD_EPID11_RLS:
//
ae_error_t PlatformInfoLogic::need_long_term_pairing(const platform_info_blob_wrapper_t* platformInfoBlobWrapper)
{
    AESM_DBG_TRACE("enter fun");
    ae_error_t status = AE_SUCCESS;

    pairing_blob_t pairing_blob;

    if (AE_FAILED(Helper::read_ltp_blob(pairing_blob)))
    {
        status = AESM_NLTP_NO_LTP_BLOB;
    }
    else if (Helper::noPseCert())
    {
        status = AESM_NPC_NO_PSE_CERT;
    }
    else
    {
        uint32_t current_psda_svn = PSDAService::instance().psda_svn;

        pse_pr_interface_psda* pPSDA = NULL;

        pPSDA = new(std::nothrow) pse_pr_interface_psda();
        if (pPSDA == NULL) {
            return AE_OUT_OF_MEMORY_ERROR;
        }
        EPID_GID meGid;

        if (NULL != platformInfoBlobWrapper)
        {

            //
            // psda svn was bad, cse gid was good and now psda svn is good
            // fact that we may not be able to get current PSDA SVN doesn't matter
            // here as long as expression involving it evaluates to false
            //
            uint32_t pib_psda_svn;
            pib_psda_svn = latest_psda_svn(platformInfoBlobWrapper);

            //pairing_blob_t pairing_blob;
            //Helper::read_ltp_blob(pairing_blob);

            //
            // psda svn was bad, cse gid was good and now psda svn is good
            // fact that we may not be able to get current PSDA SVN doesn't matter
            // here as long as expression involving it evaluates to false
            //
            if (((psda_svn_out_of_date(platformInfoBlobWrapper)) &&
                (current_psda_svn == pib_psda_svn)) || 0)
                //(!psda_svn_out_of_date(platformInfoBlobWrapper) && cse_gid_out_of_date(platformInfoBlobWrapper)))
            {
                status = AESM_NLTP_DONT_NEED_UPDATE_PAIR_LTP;      // don't need update, but need pairing
            }
            else if (cse_gid_out_of_date(platformInfoBlobWrapper)) {
                if (AE_SUCCESS == pPSDA->get_csme_gid(&meGid)) {
                    if (Helper::ltpBlobCseGid(pairing_blob) != meGid) {
                        status = AESM_NLTP_DONT_NEED_UPDATE_PAIR_LTP;
                    }
                }
                else {
                    status = AESM_NLTP_DONT_NEED_UPDATE_PAIR_LTP;
                }

            }
            //
            // we need to handle cases where current psda svn or psda svn in ltp
            // blob is unavailable
            // no ltp blob is handled above
            // not being able to get current psda svn is handled elsewhere
            // we just need to make sure we don't return something misleading
            //
            else if (newer_psda_svn(current_psda_svn, Helper::ltpBlobPsdaSvn(pairing_blob)))
                //(currentCse_gid() != ltpBlobCse_gid()))                       // assume no rollback
            {
                status = AESM_NLTP_MAY_NEED_UPDATE_LTP;       // may need update and need pairing
            }
            else if (old_epid11_rls(platformInfoBlobWrapper))
            {
                status = AESM_NLTP_OLD_EPID11_RLS;
            }
        }
        else
        {
            if ((AE_SUCCESS == pPSDA->get_csme_gid(&meGid)) && (Helper::ltpBlobCseGid(pairing_blob) != meGid)) {
                status = AESM_NLTP_DONT_NEED_UPDATE_PAIR_LTP;

            }
            //
            // see comment above about what happens when no ltp blob
            // or we can't get current psda svn
            //
            else if (newer_psda_svn(current_psda_svn, Helper::ltpBlobPsdaSvn(pairing_blob)))
                //(currentCse_gid() != ltpBlobCse_gid()))
            {
                status = AESM_NLTP_MAY_NEED_UPDATE_LTP;
            }
        }

        delete pPSDA;
        pPSDA = NULL;
    }
    SGX_DBGPRINT_ONE_STRING_TWO_INTS_CREATE_SESSION(__FUNCTION__" returning ", status, status);
    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;
}
//*********************************************************************
// Call quoting enclave to get target info
//*********************************************************************
static ae_error_t do_quote_initialization
    (
    /*out */ upse::Buffer& targetInfo,
    /*out */ GroupId* pGID
    )
{
    ae_error_t status = AE_FAILURE;


    do
    {
        BREAK_IF_TRUE( (NULL == pGID), status, PSE_PR_BAD_POINTER_ERROR);

#ifndef FAKE_QUOTE
        if (AE_FAILED(targetInfo.Alloc(sizeof(sgx_target_info_t))))
            break;
        upse::BufferWriter bwTargetInfo(targetInfo);
        uint8_t* p;
        status = bwTargetInfo.reserve(sizeof(sgx_target_info_t), &p);
        if (AE_FAILED(status))
            break;
        sgx_target_info_t* pTargetInfo = (sgx_target_info_t*)p;

        aesm_error_t result;
        SGX_DBGPRINT_PRINT_ANSI_STRING("aesmLogic.init_quote?");

        result = AESMLogic::init_quote(
            (uint8_t*)pTargetInfo, sizeof(sgx_target_info_t),
            (uint8_t*)pGID, sizeof(*pGID));
        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 init_quote
            result = AESMLogic::init_quote(
                (uint8_t*)pTargetInfo, sizeof(sgx_target_info_t),
                (uint8_t*)pGID, sizeof(*pGID));
        }
        BREAK_IF_TRUE(AESM_UPDATE_AVAILABLE == result, status, PSW_UPDATE_REQUIRED);
        BREAK_IF_TRUE(AESM_OUT_OF_EPC == result, status, AESM_AE_OUT_OF_EPC);
        BREAK_IF_TRUE(AESM_SUCCESS != result, status, AESM_PSE_PR_INIT_QUOTE_ERROR);
#else

        //NRG: m_tmpGID = 0;
        upse::Buffer m_tmpGID;
        if (AE_FAILED(m_tmpGID.Alloc(GID_TO_USE, sizeof(GID_TO_USE))))
            break;

        //      m_tmpGID = 1244;
        //      upse::BufferWriter(m_tmpGID).writeRaw(GID_TO_USE, sizeof(GID_TO_USE));
        SigmaData::SetGID(m_tmpGID);
        memcpy_s(pGID, sizeof(GroupId), m_tmpGID.getData(), sizeof(GroupId));
        if (AE_FAILED(targetInfo.Alloc(sizeof(sgx_target_info_t))))
            break;
#endif

        SGX_DBGPRINT_PRINT_ANSI_STRING("aesmLogic.init_quote success");
        status = AE_SUCCESS;

    } while (0);

    SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status);

    return status;
}
ae_error_t ConvertBackendStatus(CertificateProvisioningProtocol& cpp, ae_error_t status)
{
    if (AE_FAILED(status))
    {
        if (PSE_PRS_OK != cpp.GetProtocolResponseStatus())
        {
            SGX_DBGPRINT_ONE_STRING_ONE_INT("Backend ProtocolResponseStatus", cpp.GetProtocolResponseStatus());
            switch (cpp.GetProtocolResponseStatus())
            {
            case PSE_PRS_INVALID_GID:       status = AESM_PSE_PR_BACKEND_INVALID_GID;               break;
            case PSE_PRS_GID_REVOKED:       status = AESM_PSE_PR_BACKEND_GID_REVOKED;               break;
            case PSE_PRS_INVALID_QUOTE:     status = AESM_PSE_PR_BACKEND_INVALID_QUOTE;             break;
            case PSE_PRS_INVALID_REQUEST:   status = AESM_PSE_PR_BACKEND_INVALID_REQUEST;           break;
            default:                        status = AESM_PSE_PR_BACKEND_UNKNOWN_PROTOCOL_RESPONSE; break;
            }
            AESM_DBG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_PROTOCOL_RESPONSE_FAILURE], status);
            AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_PROTOCOL_RESPONSE_FAILURE], status);
        }
        else if (GRS_OK != cpp.GetGeneralResponseStatus())
        {
            SGX_DBGPRINT_ONE_STRING_ONE_INT("Backend GeneralResponseStatus", cpp.GetGeneralResponseStatus());
            switch (cpp.GetGeneralResponseStatus())
            {
            case GRS_SERVER_BUSY:               status = AESM_PSE_PR_BACKEND_SERVER_BUSY;               break;
            case GRS_INTEGRITY_CHECK_FAIL:      status = AESM_PSE_PR_BACKEND_INTEGRITY_CHECK_FAIL;      break;
            case GRS_INCORRECT_SYNTAX:          status = AESM_PSE_PR_BACKEND_INCORRECT_SYNTAX;          break;
            case GRS_INCOMPATIBLE_VERSION:      status = PSW_UPDATE_REQUIRED;                           break;
            case GRS_TRANSACTION_STATE_LOST:    status = AESM_PSE_PR_BACKEND_TRANSACTION_STATE_LOST;    break;
            case GRS_PROTOCOL_ERROR:            status = AESM_PSE_PR_BACKEND_PROTOCOL_ERROR;            break;
            case GRS_INTERNAL_ERROR:            status = AESM_PSE_PR_BACKEND_INTERNAL_ERROR;            break;
            default:                            status = AESM_PSE_PR_BACKEND_UNKNOWN_PROTOCOL_RESPONSE; break;
            }
            AESM_DBG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_GENERAL_RESPONSE_FAILURE], status);
            AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_GENERAL_RESPONSE_FAILURE], status);
        }
        else
        {
            switch (status)
            {
            case OAL_NETWORK_UNAVAILABLE_ERROR:
                {
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_FAILURE]);
                    break;
                }
            case PSE_PAIRING_BLOB_UNSEALING_ERROR:
                {
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_LTP_BLOB_INTEGRITY_ERROR]);
                    break;
                }
            case PSE_PAIRING_BLOB_INVALID_ERROR:
                {
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_LTP_BLOB_INVALID_ERROR]);
                    break;
                }
            case AESM_PSE_PR_BACKEND_MSG4_PLATFORM_INFO_BLOB_SIZE:
                {
                    //
                    // happens if pib returned is not the right size
                    //
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_PROTOCOL_RESPONSE_FAILURE]);
                    break;
                }
            case AE_FAILURE:
                {
                    //
                    // happens if problem with proxy setting
                    //
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_FAILURE]);
                    break;
                }
            case AESM_CP_ATTESTATION_FAILURE:
                {
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_ATTESTATION_ERROR]);
                    break;
                }
            default:
                {
                    AESM_DBG_ERROR("Error in ConvertBackendStatus(status) : status = %d (%xh)", status, status);
                    break;
                }
            }
        }
    }

    return status;
}
Example #22
0
bool Helper::noLtpBlob()
{
    upse::Buffer pairing_blob;
    return AE_FAILED(read_ltp_blob(pairing_blob));
}
Example #23
0
bool Helper::noPseCert()
{
    std::list<upse::Buffer> certChain;
    return AE_FAILED(Helper::LoadCertificateChain(certChain));
}
Example #24
0
ae_error_t Helper::SaveCertificateChain( /*in */ std::list<upse::Buffer>& certChain)
{
    ae_error_t status = AESM_PSE_PR_CERT_SAVE_ERROR;

    char* szParseString = NULL; 
    int nLen, pos=0;

    do
    {
        RemoveCertificateChain();

        // Allocate enough space for the list of names and separator character
        if(((size_t)(INT32_MAX-1))/sizeof(CERT_FILENAME_POSTFIX_FORMAT) < certChain.size() )
            break;
        int nBytes = static_cast<int>(certChain.size() * sizeof(CERT_FILENAME_POSTFIX_FORMAT)) + 1;
        szParseString = (char*)calloc(1, nBytes);
        if (NULL == szParseString)
        {
            break;
        }

        char* szNextCertNamePostfix = szParseString;

        int fileNo = 0;
        char szFilenamePostfix[80];
        std::list<upse::Buffer>::iterator it = certChain.begin();
        aesm_data_id_t fileid = PSE_PR_CERTIFICATE_FID;
        while (it != certChain.end())
        {
            nLen = sprintf_s(szFilenamePostfix, sizeof(szFilenamePostfix), CERT_FILENAME_POSTFIX_FORMAT, ++fileNo);
            if (AE_SUCCESS != upsePersistentStorage::Write(fileid++, *it))
            {
                break;
            }
            if (PSE_PR_CERTIFICATE_FID_MAX == fileid)
            {
                break;
            }

            strcpy_s(szNextCertNamePostfix, nBytes-pos, szFilenamePostfix);
            pos += nLen;
            szNextCertNamePostfix += nLen;

            ++it;
            if (it != certChain.end())
            {
                if (pos >= nBytes)
                {
                    break;
                }
                *szNextCertNamePostfix = ';';
                pos++;
                ++szNextCertNamePostfix;
            }
        }

        if ((szNextCertNamePostfix - szParseString) > nBytes)
        {
            break;
        }
        nBytes = static_cast<int>(szNextCertNamePostfix - szParseString);
        upse::Buffer nameListBuffer;
        if (AE_FAILED(nameListBuffer.Alloc(nBytes)))
            break;
        upse::BufferWriter bw(nameListBuffer);
        bw.writeRaw((uint8_t*)szParseString, nBytes);
        if (AE_SUCCESS != upsePersistentStorage::Write(PSE_PR_CERTIFICATE_CHAIN_FID, nameListBuffer))
        {
            break;
        }

        status = AE_SUCCESS;

    } while (0);

    if (NULL != szParseString)
    {
        free(szParseString);
    }

    SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status);

    return status;
}
Example #25
0
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;
}
Example #26
0
ae_error_t CertificateProvisioningProtocol::msg1_generate(const GroupId gid, upse::Buffer& serializedMsg1)
{
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status = TLV_UNKNOWN_ERROR;
    GroupId be_gid; //gid from init_quote is little endian, change to bigendian for backend server here
    be_gid.data[0]=gid.data[3];
    be_gid.data[1]=gid.data[2];
    be_gid.data[2]=gid.data[1];
    be_gid.data[3]=gid.data[0];

    provision_request_header_t header;
    memset(&header, 0, sizeof(header));

    TLVsMsg seq2_0_tlv_cipher_text;
    TLVsMsg seq2_1_tlv_block_cipher_info;
    TLVsMsg seq3_0_tlv_block_cipher_text;
    TLVsMsg seq3_1_tlv_epid_gid;
    TLVsMsg seq4_0_tlv_mac;

    do
    {
        status = get_random_value(XID_SIZE, TransactionID);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 2.1 -- Block Cipher Text TLV with SK
        status = msg1_create_seq2_1(seq2_1_tlv_block_cipher_info);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 2.0 -- Cipher Text TLV with KeyID and encrypted 2.1
        status = msg1_create_seq2_0(seq2_1_tlv_block_cipher_info, seq2_0_tlv_cipher_text);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 3.1 -- EPID GID TLV
        tlv_status = seq3_1_tlv_epid_gid.add_epid_gid(be_gid);
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        // Derive EK1
        upse::Buffer EK1;
        status = aesCMAC(M1SK, TransactionID, EK1);
        if (AE_FAILED(status))
            break;

        // Create Request Header (we need to calculate size before AES-GCM CMAC)
        status = msg1_create_header(seq2_0_tlv_cipher_text.get_tlv_msg_size(), seq3_1_tlv_epid_gid.get_tlv_msg_size(), TransactionID, header);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 3.0 -- Block Cipher Text TLV with IV and encrypted 3.1
        upse::Buffer mac;
        status = msg1_create_seq3_0(seq3_1_tlv_epid_gid, header, EK1, seq3_0_tlv_block_cipher_text, mac);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 4.0 -- MAC TLV
        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_msg1 = static_cast<uint32_t>(PROVISION_REQUEST_HEADER_SIZE) + seq2_0_tlv_cipher_text.get_tlv_msg_size() +
                                seq3_0_tlv_block_cipher_text.get_tlv_msg_size() + seq4_0_tlv_mac.get_tlv_msg_size();

        status = serializedMsg1.Alloc(size_msg1);
        if (AE_FAILED(status))
            break;

        serializedMsg1.zeroMemory();
        upse::BufferWriter bwMsg1(serializedMsg1);

        // Write serialized request header to serialized message
        status = bwMsg1.writeRaw((uint8_t*)&header, sizeof(header));
        if (AE_FAILED(status))
            break;

        // Write sequence 2.0 - Cipher Text TLV (contains 2.1 as encrypted payload)
        status = bwMsg1.writeRaw(const_cast<uint8_t*>(seq2_0_tlv_cipher_text.get_tlv_msg()), seq2_0_tlv_cipher_text.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        // Write sequence 3.0 - Block Cipher Text TLV (contains 3.1 as encrypted payload)
        status = bwMsg1.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 = bwMsg1.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;
}
Example #27
0
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;
}
ae_error_t prepare_for_certificate_provisioning
(
    /*in */ UINT64  nonce64,
    /*in */ const sgx_target_info_t*     pTargetInfo,
    /*in */ UINT16  nMax_CSR_pse,
    /*out*/ UINT8*  pCSR_pse,
    /*out*/ UINT16* pnLen_CSR_pse,
    /*out*/ sgx_report_t*          pREPORT,
    /*i/o*/ pairing_blob_t* pPairingBlob
)
{
    // Flow:  1) Check pointers for buffer data sizes
    //        2) If buffers are too small, return and tell caller size required
    //        3) Validate pointers and ensure buffers are within the enclave
    //        4) Generate a new private/public ECDSA key pair
    //        5) Request signed CSR template
    //        6) Calculate HASH_pse of (CSR_pse || nonce64)
    //        7) Generate REPORT with HASH_pse as the REPORTDATA, targeting QE
    //        8) Copy private key and public key into unsealed_pairing buffer
    //        9) Seal pairing blob
    //       10) Return Sealed pairing blob, generated CSR, REPORT, and status

    ae_error_t status = AE_FAILURE;

    pairing_data_t pairingData;
    EcDsaPrivKey privateKey;
    EcDsaPubKey publicKey;
    uint8_t     temp_instance_id[16];

    SignCSR CSR;

    size_t nMaxSizeCSR = CSR.GetMaxSize();
    sgx_ecc_state_handle_t csr_ecc_handle = NULL;

    memset(&pairingData, 0, sizeof(pairingData));

    /////////////////////////////////////////////////////////////////

    do
    {
        //*********************************************************************
        // Validate pointers and sizes
        //*********************************************************************
        BREAK_IF_TRUE((NULL == pPairingBlob),
            status, PSE_PR_BAD_POINTER_ERROR);

        // save SW_INSTANCE_ID
        memcpy(temp_instance_id, pPairingBlob->plaintext.pse_instance_id, sizeof(temp_instance_id));

        {

            BREAK_IF_TRUE((NULL == pTargetInfo),
                status, PSE_PR_BAD_POINTER_ERROR);

            BREAK_IF_TRUE((NULL == pREPORT),
                status, PSE_PR_BAD_POINTER_ERROR);

            BREAK_IF_TRUE((NULL == pCSR_pse || NULL == pnLen_CSR_pse),
                status, PSE_PR_BAD_POINTER_ERROR);

            BREAK_IF_TRUE((nMax_CSR_pse < nMaxSizeCSR),
                status, PSE_PR_PARAMETER_ERROR);

            BREAK_IF_FALSE(sgx_is_within_enclave(pCSR_pse, nMaxSizeCSR), status, PSE_PR_BAD_POINTER_ERROR);

            //*********************************************************************
            // Generate a new ECDSA Key Pair
            //*********************************************************************
            
            sgx_status_t sgx_status = sgx_ecc256_open_context(&csr_ecc_handle);
            BREAK_IF_TRUE((SGX_ERROR_OUT_OF_MEMORY == sgx_status), status, PSE_PR_INSUFFICIENT_MEMORY_ERROR);
            BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), status, PSE_PR_KEY_PAIR_GENERATION_ERROR);

            sgx_status = sgx_ecc256_create_key_pair((sgx_ec256_private_t *)privateKey, (sgx_ec256_public_t*)publicKey, csr_ecc_handle);
            BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), status, PSE_PR_KEY_PAIR_GENERATION_ERROR);

            *pnLen_CSR_pse = (uint16_t)nMaxSizeCSR;

            //*********************************************************************
            // Get a signed Certificate Signing Request from the template
            //*********************************************************************
            status = CSR.GetSignedTemplate(&privateKey, &publicKey, csr_ecc_handle,  pCSR_pse, pnLen_CSR_pse);
            BREAK_IF_FAILED(status);

            //*********************************************************************
            // Calculate HASH_pse of (CSR_pse || nonce64)
            //*********************************************************************
            PrepareHashSHA256 hash;
            SHA256_HASH computedHash;
            status = hash.Update(pCSR_pse, *pnLen_CSR_pse);
            BREAK_IF_FAILED(status);
            status = hash.Update(&nonce64, sizeof(nonce64));
            BREAK_IF_FAILED(status);
            status = hash.Finalize(&computedHash);
            BREAK_IF_FAILED(status);

            //*********************************************************************
            // Generate a REPORT with HASH_pse
            //*********************************************************************
            sgx_report_data_t report_data = {{0}};
            memcpy(&report_data, &computedHash, sizeof(computedHash));
            if (SGX_SUCCESS != sgx_create_report(const_cast<sgx_target_info_t*>(pTargetInfo), 
                &report_data, (sgx_report_t*)pREPORT))
            {
                status = PSE_PR_CREATE_REPORT_ERROR;
                break;
            }

            //*********************************************************************
            // Try to unseal the pairing data
            //*********************************************************************
            status = UnsealPairingBlob(pPairingBlob, &pairingData);
            if (AE_FAILED(status))
                memset_s(&pairingData, sizeof(pairingData), 0, sizeof(pairingData));

            //*********************************************************************
            // Seal ECDSA Verifier Private Key into blob
            //*********************************************************************

            memcpy(pairingData.secret_data.VerifierPrivateKey, &privateKey, sizeof(EcDsaPrivKey));
        
        } // "Public" PSE Cert

        // Set pairingData.plaintext.pse_instance_id using saved temp_instance_id
        memcpy(pairingData.plaintext.pse_instance_id, temp_instance_id, sizeof(pairingData.plaintext.pse_instance_id));

        status = SealPairingBlob(&pairingData, pPairingBlob);
        BREAK_IF_FAILED(status);

        //*********************************************************************
        // WE PASSED ALL BARRIERS TO SUCCESS
        //*********************************************************************

        status = AE_SUCCESS;

//        OutputOctets("::tPrepareForCertificateProvisioning:: New CSR generated", NULL, 0);

    } while (false);

    // Defense-in-depth: clear the data on stack that contains enclave secret.
    memset_s(&pairingData, sizeof(pairingData), 0, sizeof(pairingData));
    memset_s(&privateKey, sizeof(privateKey), 0, sizeof(privateKey));

    if (csr_ecc_handle != NULL) sgx_ecc256_close_context(csr_ecc_handle);

    return map_error_for_return(status);

}
Example #29
0
ae_error_t CertificateProvisioningProtocol::msg3_seq3_0_create_block_cipher_text_tlv(const TLVsMsg& quote, const TLVsMsg& epidSigTLV, const TLVsMsg& csrTLV, const TLVsMsg& nonceTLV, 
                                                      const provision_request_header_t& requestHeader, const upse::Buffer& ek2,
                                                      TLVsMsg& blockCipherTextTLV, upse::Buffer& mac)
{
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status;

    upse::Buffer plainText;
    upse::Buffer encryptedPayload;

    do
    {
        status = get_random_value(IV_SIZE, M3IV);
        if (AE_FAILED(status))
            break;

        status = plainText.Alloc(quote.get_tlv_msg_size() + epidSigTLV.get_tlv_msg_size() + csrTLV.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        upse::BufferWriter plainTextWriter(plainText);
        status = plainTextWriter.writeRaw(quote.get_tlv_msg(), quote.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;
        status = plainTextWriter.writeRaw(epidSigTLV.get_tlv_msg(), epidSigTLV.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;
        status = plainTextWriter.writeRaw(csrTLV.get_tlv_msg(), csrTLV.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        uint32_t payloadSize = BLOCK_CIPHER_TEXT_TLV_PAYLOAD_SIZE(plainText.getSize());
        uint32_t blockCipherTextHeaderSize = get_tlv_total_size(payloadSize) - payloadSize;

        // Calculate AAD (concatenation of Request header, Nonce, Block Cipher Text TLV header and IV from Block Cipher Text TLV)
        upse::Buffer aad;
        status = aad.Alloc(static_cast<uint32_t>(sizeof(requestHeader) + nonceTLV.get_tlv_msg_size() +  blockCipherTextHeaderSize + M3IV.getSize()));
        if (AE_FAILED(status))
            break;

        TLVsMsg tmpBlockCipherTextTLV;
        tlv_status = tmpBlockCipherTextTLV.add_block_cipher_text(M3IV.getData(), NULL, plainText.getSize());
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        upse::BufferWriter aadWriter(aad);
        status = aadWriter.writeRaw((const uint8_t*)&requestHeader, sizeof(requestHeader));
        if (AE_FAILED(status))
            break;
        status = aadWriter.writeRaw(nonceTLV.get_tlv_msg(), nonceTLV.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;
        status = aadWriter.writeRaw(tmpBlockCipherTextTLV.get_tlv_msg(), blockCipherTextHeaderSize);
        if (AE_FAILED(status))
            break;
        status = aadWriter.writeRaw(M3IV.getData(), M3IV.getSize());
        if (AE_FAILED(status))
            break;

        status = aesGCMEncrypt(M3IV, ek2, plainText, aad, encryptedPayload, mac);
        if (AE_FAILED(status))
            break;

        tlv_status = blockCipherTextTLV.add_block_cipher_text(M3IV.getData(), encryptedPayload.getData(), encryptedPayload.getSize());
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;

    } while (0);

    return status;
}
Example #30
0
ae_error_t SigmaHelper::GetRLsFromServer
    (   /*out*/ upse::Buffer& sigRlOut,
    /*out*/ upse::Buffer& privRlOut
    )
{

    //
    // iKGF serves up binary (legacy) versions of EPID 1.1 RLs
    // all we need to do is convey the GID in the URL itself
    // for example, https://trustedservices.intel.com/content/crl/Signature_<GID>.crl
    // so, we get url out of config file and concatenate with filename that's
    // specific to the type of RL

    ae_error_t sigRetValue = AE_FAILURE;
    ae_error_t privRetValue = AE_FAILURE;

    const char *url = EndpointSelectionInfo::instance().get_server_url(REVOCATION_LIST_RETRIEVAL);
    if (url == NULL)
    {
        return OAL_CONFIG_FILE_ERROR;
    }

    uint8_t* p1 = const_cast<uint8_t*>(m_gid.getData());

    do {

        if ((m_gid.getSize() < 1) || (m_gid.getSize() > 4)) break;
        char msg[9];
        for (unsigned i = 0; i < m_gid.getSize(); i++)
        {
            
            sprintf_s((char*) msg+2*i, 3, "%02X", *(p1+m_gid.getSize()-1-i));
        }
        std::string gidString(msg);

        unsigned numLeading0s = 8 - static_cast<unsigned>(gidString.length());

        for (unsigned i = 0; i < numLeading0s; i++)
        {
            gidString = '0' + gidString;
        }

        //if config file entry doesn't have trailing "/" , add it.
        std::string s_url = url;
        if(s_url.size()>0&&s_url[s_url.size()-1]!='/')
            s_url+='/';
        std::string stringUrl = s_url + "Signature_" + gidString + ".crl";

        uint8_t *recv=NULL;
        uint32_t recv_size = 0;
        sigRetValue = AESMNetworkEncoding::aesm_send_recv_msg(stringUrl.c_str(), NULL, 0, recv, recv_size, GET, false);

        if (AE_SUCCESS != sigRetValue)
        {
            sigRlOut.Alloc(0);
        }
        else
        {
            sigRlOut.Alloc(recv_size);
            upse::BufferWriter bw(sigRlOut);
            bw.writeRaw(recv, recv_size);
            AESMNetworkEncoding::aesm_free_response_msg(recv);
        }

        stringUrl = s_url + "Product_" + gidString + ".crl";
        recv=NULL;
        recv_size = 0;
        privRetValue = AESMNetworkEncoding::aesm_send_recv_msg(stringUrl.c_str(), NULL, 0, recv, recv_size, GET, false);

        if (AE_SUCCESS != privRetValue)
        {
            privRlOut.Alloc(0);
        }
        else
        {
            privRlOut.Alloc(recv_size);
            upse::BufferWriter bw(privRlOut);
            bw.writeRaw(recv, recv_size);
            aesm_free_network_response_buffer(recv);
        }
    } while (0);

    if (AE_FAILED(privRetValue))
    {
        SGX_DBGPRINT_PRINT_STRING_LTP("PrivRL not retrieved: continuing without PrivRL");
    }
    if (AE_FAILED(sigRetValue))
    {
        SGX_DBGPRINT_PRINT_STRING_LTP("SigRL not retrieved: continuing without SigRL");
    }

    if ((privRetValue == AE_SUCCESS) && (sigRetValue == AE_SUCCESS)) {
        return AE_SUCCESS;
    }
    else if (sigRetValue != AE_SUCCESS) {
        return AESM_PSE_PR_GET_SIGRL_ERROR;
    }
    else {
        return AESM_PSE_PR_GET_PRIVRL_ERROR;
    }
}