Example #1
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 #2
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;
}