Я работаю над нестандартным поставщиком CNG, чтобы разрешить подпись Authenticode с помощью частного API HSM.
Я внедрил провайдера КПГ и зарегистрировался. Мне удалось использовать signtool.exe для вызова API-интерфейса для частной подписи, предоставляемого HSM.
Вот команда, которую я использую
signtool.exe sign /v /debug /f cert.cer /csp "Sample Key Storage Provider" /k "keyid" /t http://timestamp.digicert.com /fd sha256 helloworld.exe
Команда выдает следующий вывод
The following certificates were considered:
Issued to: Sample test certificate
Issued by: Sample Certificate Authority
Expires: Thu May 28 13:40:10 2020
SHA1 hash: A679DF5E89B9C23E57E89AEB434CA98230F52DC3
After EKU filter, 1 certs were left.
After expiry filter, 1 certs were left.
The following certificate was selected:
Issued to: Sample test certificate
Issued by: Sample Certificate Authority
Expires: Thu May 28 13:40:10 2020
SHA1 hash: A679DF5E89B9C23E57E89AEB434CA98230F52DC3
The following additional certificates will be attached:
Done Adding Additional Store
[KSP Logging] Signature size: 256
[KSP Logging] Signhash status: 0
[KSP Logging] hash digest is
Wr╥ìΩ╤ⁿír1é┘│vCx²▀2╡3┼1┼!░¢╝╙
[KSP Logging] digest size 32
[KSP Logging] calling HSM for signing
[KSP Logging] Call to HSM success
[KSP Logging] Signature from API
Aq#^y╝¢O$Ü╟╓W╪▄s║U≡αK«åqDKÿï^NBD=érî╢Üùo╫à█RXàmf┐█K
┤╩F.I╠╗Hsé]▐)ùFR#D,y;╣JX╝H┼c,
[KSP Logging] Signature size 256
[KSP Logging] pbsig: Aq#^y╝¢O$Ü╟╓W╪▄s║U≡αK«åqDKÿï^NBD=érî╢Üùo╫à█RXàmf┐█K
┤╩F.I╠╗Hsé]▐)ùFR#D,y;╣JX╝H┼c,
[KSP Logging] Signhash status: 0
Successfully signed: helloworld.exe
Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0
Однако, когда я запускаю проверку, ниже вывод
> signtool.exe verify /v /pa helloworld.exe
Verifying: helloworld.exe
Signature Index: 0 (Primary Signature)
Hash of file (sha256): 3338A11DDAB9CBB7B39E65C30F235C2DF8EDE17BB5BE759A3213D25EC286F390
Signing Certificate Chain:
Issued to: Sample Certificate Authority
Issued by: Sample Certificate Authority
Expires: Fri Feb 07 21:37:36 2070
SHA1 hash: 2B5B37DADFCBD018BDB2789176A69708FFCA25E0
Issued to: Sample test certificate
Issued by: Sample Certificate Authority
Expires: Thu May 28 13:40:10 2020
SHA1 hash: A679DF5E89B9C23E57E89AEB434CA98230F52DC3
The signature is timestamped: Sun Mar 29 16:44:01 2020
Timestamp Verified by:
Issued to: DigiCert Assured ID Root CA
Issued by: DigiCert Assured ID Root CA
Expires: Sun Nov 09 17:00:00 2031
SHA1 hash: 0563B8630D62D75ABBC8AB1E4BDFB5A899B24D43
Issued to: DigiCert SHA2 Assured ID Timestamping CA
Issued by: DigiCert Assured ID Root CA
Expires: Tue Jan 07 05:00:00 2031
SHA1 hash: 3BA63A6E4841355772DEBEF9CDCF4D5AF353A297
Issued to: TIMESTAMP-SHA256-2019-10-15
Issued by: DigiCert SHA2 Assured ID Timestamping CA
Expires: Wed Oct 16 17:00:00 2030
SHA1 hash: 0325BD505EDA96302DC22F4FA01E4C28BE2834C5
SignTool Error: No signature found.
Number of files successfully Verified: 0
Number of warnings: 0
Number of errors: 1
Ниже приведен код KSPSignHa sh в моем провайдере CNG
SECURITY_STATUS
WINAPI
SampleKSPSignHash(
__in NCRYPT_PROV_HANDLE hProvider,
__in NCRYPT_KEY_HANDLE hKey,
__in_opt VOID *pPaddingInfo,
__in_bcount(cbHashValue) PBYTE pbHashValue,
__in DWORD cbHashValue,
__out_bcount_part_opt(cbSignaturee, *pcbResult) PBYTE pbSignature,
__in DWORD cbSignaturee,
__out DWORD * pcbResult,
__in DWORD dwFlags)
{
SECURITY_STATUS Status = NTE_INTERNAL_ERROR;
NTSTATUS ntStatus = STATUS_INTERNAL_ERROR;
SAMPLEKSP_KEY *pKey = NULL;
DWORD cbTmpSig = 0;
DWORD cbTmp = 0;
UNREFERENCED_PARAMETER(hProvider);
debug("In SampleKSPSignHash\n");
//
// Validate input parameters.
//
pKey = SampleKspValidateKeyHandle(hKey);
if(pKey == NULL)
{
Status = NTE_INVALID_HANDLE;
goto cleanup;
}
if (pcbResult == NULL)
{
Status = NTE_INVALID_PARAMETER;
goto cleanup;
}
if(dwFlags & ~(BCRYPT_PAD_PKCS1 | BCRYPT_PAD_PSS | NCRYPT_SILENT_FLAG))
{
Status = NTE_BAD_FLAGS;
goto cleanup;
}
if(pKey->fFinished == FALSE)
{
Status = NTE_BAD_KEY_STATE;
goto cleanup;
}
//
// Verify that this key is allowed to perform sign operations.
//
if (pbSignature == NULL)
{
//This call is to query the size.
ntStatus = BCryptGetProperty(pKey->hPublicKey,
BCRYPT_SIGNATURE_LENGTH,
(BYTE*)&cbTmpSig,
sizeof(DWORD),
&cbTmp,
0);
if (!NT_SUCCESS(ntStatus))
{
Status = NormalizeNteStatus(ntStatus);
goto cleanup;
}
Status = ERROR_SUCCESS;
*pcbResult = cbTmpSig;
goto cleanup;
}
if(pbHashValue == NULL || cbHashValue == 0)
{
Status = NTE_INVALID_PARAMETER;
goto cleanup;
}
pbSignature = hsmSign(pbHashValue, cbHashValue, &pKey->pszKeyName);
printf("pbsig: %s\n", pbSignature);
Status = ERROR_SUCCESS;
cleanup:
printf("Signhash status: %X \n", Status);
return Status;
}
HSMClient. cpp
extern "C" unsigned char* hsmSign(const unsigned char* digest, int digestSize, const char* keyId);
unsigned char* hsmSign(const unsigned char* digest, int digestSize, const char* keyId) {
...
request.SetKeyId(keyId);
request.SetDigest(buffer);
return hsm_client.Sign(request).GetResult().GetSignature().GetUnderlyingData();
}
Что я делаю неправильно, если двоичный файл не имеет подписи?