bool signUsingCng()

in host/securitylib/win/signmessage.h [22:233]


    bool signUsingCng(std::string& errMsg,
        const std::string& message,
        securitylib::signature_t& signature,
        PCCERT_CONTEXT pCertContext,
        NCRYPT_KEY_HANDLE hNcryptKey)
    {
        USES_CONVERSION;

        static LARGE_INTEGER                   s_perfFreq = { 0 };
        static BCRYPT_ALG_HANDLE               s_hHashAlg = NULL;

        const ULONGLONG USECS_IN_SEC = 1000 * 1000;

        SECURITY_STATUS         secStatus = ERROR_SUCCESS;
        NTSTATUS                status = STATUS_UNSUCCESSFUL;
        DWORD                   cbData = 0,
                                cbHash = 0,
                                cbBlob = 0,
                                cbSignature = 0,
                                cbHashObject = 0;

        BCRYPT_HASH_HANDLE              hBCryptHash = NULL;
        CRYPT_KEY_PROV_INFO *           pKeyProvInfo = NULL;

        LARGE_INTEGER startCounter = { 0 }, endCounter = { 0 }, elapsedCounter = { 0 };

        if (!s_perfFreq.QuadPart)
        {
            if (!QueryPerformanceFrequency(&s_perfFreq))
            {
                errMsg += "QueryPerformanceFrequency failed. Error : ";
                GET_LAST_ERROR_CODE_STRING(errMsg);
            }
        }

        if (!CertGetCertificateContextProperty(pCertContext,
            CERT_KEY_PROV_INFO_PROP_ID,
            NULL,
            &cbData))
        {
            errMsg += "Failed to get provider info name length. Error : ";
            GET_LAST_ERROR_CODE_STRING(errMsg);
            return false;
        }

        std::vector<char> pData(cbData, 0);
        pKeyProvInfo = (CRYPT_KEY_PROV_INFO *)&pData[0];

        if (!CertGetCertificateContextProperty(pCertContext,
            CERT_KEY_PROV_INFO_PROP_ID,
            (PBYTE)pKeyProvInfo,
            &cbData))
        {
            errMsg += "Failed to get provider info name. Error : ";
            GET_LAST_ERROR_CODE_STRING(errMsg);
            return false;
        }

        errMsg += " Provider name: ";
        errMsg += W2A(pKeyProvInfo->pwszProvName);
        errMsg += " Container name: ";
        errMsg += W2A(pKeyProvInfo->pwszContainerName);

        if (s_perfFreq.QuadPart)
        {
            if (!QueryPerformanceCounter(&startCounter))
            {
                errMsg += "QueryPerformanceCounter failed. Error : ";
                GET_LAST_ERROR_CODE_STRING(errMsg);
            }
        }

        if (s_hHashAlg == NULL)
        {
            if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
                &s_hHashAlg,
                BCRYPT_SHA256_ALGORITHM,
                NULL,
                0)))
            {
                errMsg += "BCryptOpenAlgorithmProvider retunred error : ";
                errMsg += boost::lexical_cast<std::string>(status);
                return false;
            }
        }

        if (s_perfFreq.QuadPart && startCounter.QuadPart)
        {
            if (!QueryPerformanceCounter(&endCounter))
            {
                errMsg += "QueryPerformanceCounter failed. Error : ";
                GET_LAST_ERROR_CODE_STRING(errMsg);
            }
            else
            {
                elapsedCounter.QuadPart = endCounter.QuadPart - startCounter.QuadPart;
                elapsedCounter.QuadPart *= USECS_IN_SEC;
                ULONGLONG elapsedTimeInUs = elapsedCounter.QuadPart / s_perfFreq.QuadPart;
                if (elapsedTimeInUs > USECS_IN_SEC)
                {
                    errMsg += " Elapsed time for BCryptOpenAlgorithmProvider() is ";
                    errMsg += boost::lexical_cast<std::string>(elapsedTimeInUs);
                    errMsg += "us. ";
                }
            }
        }

        if (!NT_SUCCESS(status = BCryptGetProperty(
            s_hHashAlg,
            BCRYPT_OBJECT_LENGTH,
            (PBYTE)&cbHashObject,
            sizeof(DWORD),
            &cbData,
            0)))
        {
            errMsg += "BCryptGetProperty for object length retunred error : ";
            errMsg += boost::lexical_cast<std::string>(status);
            return false;
        }

        std::vector<BYTE> pbHashObject(cbHashObject, 0);

        if (!NT_SUCCESS(status = BCryptCreateHash(
            s_hHashAlg,
            &hBCryptHash,
            &pbHashObject[0],
            cbHashObject,
            NULL,
            0,
            0)))
        {
            errMsg += "BCryptCreateHash  retunred error : ";
            errMsg += boost::lexical_cast<std::string>(status);
            return false;;
        }

        ON_BLOCK_EXIT(boost::bind<void>(&BCryptDestroyHash, hBCryptHash));

        if (!NT_SUCCESS(status = BCryptGetProperty(
            s_hHashAlg,
            BCRYPT_HASH_LENGTH,
            (PBYTE)&cbHash,
            sizeof(DWORD),
            &cbData,
            0)))
        {
            errMsg += "BCryptGetProperty for hash length retunred error : ";
            errMsg += boost::lexical_cast<std::string>(status);
            return false;
        }

        std::vector<BYTE> pbHash(cbHash, 0);

        if (!NT_SUCCESS(status = BCryptHashData(
            hBCryptHash,
            (PBYTE)message.c_str(),
            message.length(),
            0)))
        {
            errMsg += "BCryptHashData retunred error : ";
            errMsg += boost::lexical_cast<std::string>(status);
            return false;
        }

        if (!NT_SUCCESS(status = BCryptFinishHash(
            hBCryptHash,
            &pbHash[0],
            cbHash,
            0)))
        {
            errMsg += "BCryptFinishHash retunred error : ";
            errMsg += boost::lexical_cast<std::string>(status);
            return false;
        }

        BCRYPT_PKCS1_PADDING_INFO paddingInfo;
        paddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM;

        if (FAILED(secStatus = NCryptSignHash(
            hNcryptKey,
            &paddingInfo,
            &pbHash[0],
            cbHash,
            NULL,
            0,
            &cbSignature,
            NCRYPT_SILENT_FLAG | NCRYPT_PAD_PKCS1_FLAG)))
        {
            errMsg += "NCryptSignHash for length retunred error : ";
            errMsg += boost::lexical_cast<std::string>(secStatus);
            return false;
        }

        signature.resize(cbSignature);

        if (FAILED(secStatus = NCryptSignHash(
            hNcryptKey,
            &paddingInfo,
            &pbHash[0],
            cbHash,
            (PBYTE)&signature[0],
            cbSignature,
            &cbSignature,
            NCRYPT_SILENT_FLAG | NCRYPT_PAD_PKCS1_FLAG)))
        {
            errMsg += "NCryptSignHash retunred error : ";
            errMsg += boost::lexical_cast<std::string>(secStatus);
            return false;
        }

        return true;
    }