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;
}