SUPPORT-8592. Добавлен cryptopro_verify()
This commit is contained in:
parent
17aec4de8b
commit
503287af7f
4 changed files with 255 additions and 1 deletions
|
|
@ -26,11 +26,17 @@ capi_function_list_init(library_t *lib, capi_function_list_t *fl)
|
|||
LIBRARY_RESOLVE(fl->CryptReleaseContext, lib, "CryptReleaseContext");
|
||||
LIBRARY_RESOLVE(fl->CryptSignMessage, lib, "CryptSignMessage");
|
||||
LIBRARY_RESOLVE(fl->GetLastError, lib, "GetLastError");
|
||||
LIBRARY_RESOLVE(fl->CryptImportPublicKeyInfo, lib, "CryptImportPublicKeyInfo");
|
||||
LIBRARY_RESOLVE(fl->CryptDestroyKey, lib, "CryptDestroyKey");
|
||||
|
||||
#ifdef UNICODE
|
||||
LIBRARY_RESOLVE(fl->CryptSignHash, lib, "CryptSignHashW");
|
||||
LIBRARY_RESOLVE(fl->CryptVerifySignature, lib, "CryptVerifySignatureW");
|
||||
LIBRARY_RESOLVE(fl->CryptAcquireContext, lib, "CryptAcquireContextW");
|
||||
#else
|
||||
LIBRARY_RESOLVE(fl->CryptSignHash, lib, "CryptSignHashA");
|
||||
LIBRARY_RESOLVE(fl->CryptVerifySignature, lib, "CryptVerifySignatureA");
|
||||
LIBRARY_RESOLVE(fl->CryptAcquireContext, lib, "CryptAcquireContextA");
|
||||
#endif // !UNICODE
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -124,10 +124,65 @@ DECLARE_FN(WINADVAPI,
|
|||
BYTE *pbSignature,
|
||||
DWORD *pdwSigLen));
|
||||
|
||||
DECLARE_FN(WINADVAPI,
|
||||
BOOL,
|
||||
CRYPT_VERIFY_SIGNATURE_A,
|
||||
(HCRYPTHASH hHash,
|
||||
CONST BYTE *pbSignature,
|
||||
DWORD dwSigLen,
|
||||
HCRYPTKEY hPubKey,
|
||||
LPCSTR szDescription,
|
||||
DWORD dwFlags));
|
||||
|
||||
DECLARE_FN(WINADVAPI,
|
||||
BOOL,
|
||||
CRYPT_VERIFY_SIGNATURE_W,
|
||||
(HCRYPTHASH hHash,
|
||||
CONST BYTE *pbSignature,
|
||||
DWORD dwSigLen,
|
||||
HCRYPTKEY hPubKey,
|
||||
LPCWSTR szDescription,
|
||||
DWORD dwFlags));
|
||||
|
||||
DECLARE_FN(WINADVAPI,
|
||||
BOOL,
|
||||
CRYPT_ACQUIRE_CONTEXT_A,
|
||||
(HCRYPTPROV *phProv,
|
||||
LPCSTR pszContainer,
|
||||
LPCSTR pszProvider,
|
||||
DWORD dwProvType,
|
||||
DWORD dwFlags));
|
||||
|
||||
DECLARE_FN(WINADVAPI,
|
||||
BOOL,
|
||||
CRYPT_ACQUIRE_CONTEXT_W,
|
||||
(HCRYPTPROV *phProv,
|
||||
LPCSTR pszContainer,
|
||||
LPCSTR pszProvider,
|
||||
DWORD dwProvType,
|
||||
DWORD dwFlags));
|
||||
|
||||
DECLARE_FN(WINADVAPI,
|
||||
BOOL,
|
||||
CRYPT_IMPORT_PUBLIC_KEY_INFO,
|
||||
(HCRYPTPROV hCryptProv,
|
||||
DWORD dwCertEncodingType,
|
||||
PCERT_PUBLIC_KEY_INFO pInfo,
|
||||
HCRYPTKEY *phKey));
|
||||
|
||||
DECLARE_FN(WINADVAPI,
|
||||
BOOL,
|
||||
CRYPT_DESTROY_KEY,
|
||||
(HCRYPTKEY hKey));
|
||||
|
||||
#ifdef UNICODE
|
||||
#define CRYPT_SIGN_HASH_FN CRYPT_SIGN_HASH_W_FN
|
||||
#define CRYPT_VERIFY_SIGNATURE_FN CRYPT_VERIFY_SIGNATURE_W_FN
|
||||
#define CRYPT_ACQUIRE_CONTEXT_FN CRYPT_ACQUIRE_CONTEXT_W_FN
|
||||
#else
|
||||
#define CRYPT_SIGN_HASH_FN CRYPT_SIGN_HASH_A_FN
|
||||
#define CRYPT_VERIFY_SIGNATURE_FN CRYPT_VERIFY_SIGNATURE_A_FN
|
||||
#define CRYPT_ACQUIRE_CONTEXT_FN CRYPT_ACQUIRE_CONTEXT_A_FN
|
||||
#endif // !UNICODE
|
||||
|
||||
|
||||
|
|
@ -146,6 +201,11 @@ typedef struct {
|
|||
CERT_FIND_CERTIFICATE_IN_STORE_FN CertFindCertificateInStore;
|
||||
CERT_GET_CERTIFICATE_CONTEXT_PROPERTY_FN CertGetCertificateContextProperty;
|
||||
CERT_SET_CERTIFICATE_CONTEXT_PROPERTY_FN CertSetCertificateContextProperty;
|
||||
CRYPT_VERIFY_SIGNATURE_FN CryptVerifySignature;
|
||||
CRYPT_ACQUIRE_CONTEXT_FN CryptAcquireContext;
|
||||
CRYPT_IMPORT_PUBLIC_KEY_INFO_FN CryptImportPublicKeyInfo;
|
||||
CRYPT_DESTROY_KEY_FN CryptDestroyKey;
|
||||
|
||||
} capi_function_list_t;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -292,4 +292,189 @@ set_pin(PCCERT_CONTEXT pSignerCert, const str_t *pin)
|
|||
error:
|
||||
LOG_ERROR("set_pin exit with error. Last error code: 0x%08x", cp_function_list.GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static PCCERT_CONTEXT
|
||||
get_cert_by_thumbprint(HCERTSTORE hStoreHandle, const str_t* thumbprint)
|
||||
{
|
||||
str_t thumbprint_bin = str_t_null;
|
||||
|
||||
if (hex_to_bin(thumbprint, &thumbprint_bin)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
CRYPT_HASH_BLOB hash = {
|
||||
.pbData = (BYTE*)thumbprint_bin.data,
|
||||
.cbData = thumbprint_bin.len
|
||||
};
|
||||
|
||||
PCCERT_CONTEXT cert = cp_function_list.CertFindCertificateInStore(hStoreHandle,
|
||||
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
0,
|
||||
CERT_FIND_HASH,
|
||||
&hash,
|
||||
NULL);
|
||||
if (cert == NULL) {
|
||||
LOG_ERROR("Could not find certificate in store");
|
||||
goto error;
|
||||
}
|
||||
|
||||
str_t_clear(&thumbprint_bin);
|
||||
|
||||
return cert;
|
||||
|
||||
error:
|
||||
str_t_clear(&thumbprint_bin);
|
||||
LOG_ERROR("get_cert_by_thumbprint exit with error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
alg_id_from_str(const str_t* alg, /*out*/ ALG_ID* alg_id)
|
||||
{
|
||||
LOG_TRACE("alg_id_from_str");
|
||||
|
||||
if (strncmp(alg->data, "GOST3410_2012_256", alg->len) == 0) {
|
||||
*alg_id = CALG_GR3411_2012_256;
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(alg->data, "GOST3410_2012_512", alg->len) == 0) {
|
||||
*alg_id = CALG_GR3411_2012_512;
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(alg->data, "RS256", alg->len) == 0) {
|
||||
*alg_id = CALG_SHA_256;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_ERROR("Unknown alg: '%.*s'", (int) alg->len, alg->data);
|
||||
LOG_ERROR("alg_id_from_str exit with error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
log_verify_error()
|
||||
{
|
||||
DWORD err = cp_function_list.GetLastError();
|
||||
|
||||
switch (err) {
|
||||
case NTE_BAD_SIGNATURE:
|
||||
LOG_WARN("sign is invalid: bad signature (0x%08x)", err);
|
||||
break;
|
||||
|
||||
case NTE_BAD_ALGID:
|
||||
LOG_WARN("sign is invalid: bad alg id (0x%08x)", err);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WARN("sign is invalid. Last error code: 0x%08x", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t *data,
|
||||
const str_t *sign, bool* is_verified)
|
||||
{
|
||||
int rc = -1;
|
||||
HCERTSTORE hStoreHandle = NULL;
|
||||
PCCERT_CONTEXT certificate = NULL;
|
||||
HCRYPTPROV hCryptProv = 0;
|
||||
HCRYPTHASH hash = 0;
|
||||
HCRYPTKEY hPubKey = 0;
|
||||
str_t sign_reversed = str_t_null;
|
||||
ALG_ID alg_id;
|
||||
|
||||
LOG_TRACE("cryptopro_verify enter");
|
||||
|
||||
*is_verified = false;
|
||||
|
||||
if (alg_id_from_str(alg, &alg_id)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (reverse_sign(sign, &sign_reversed)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
hStoreHandle = cert_open_store();
|
||||
if (hStoreHandle == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
certificate = get_cert_by_thumbprint(hStoreHandle, cert_thumbprint);
|
||||
if (certificate == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!cp_function_list.CryptAcquireContext(&hCryptProv, NULL, CP_KC1_GR3410_2001_PROV,
|
||||
PROV_GOST_2001_DH, CRYPT_VERIFYCONTEXT)) {
|
||||
LOG_ERROR("CryptAcquireContext() failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!cp_function_list.CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,
|
||||
&certificate->pCertInfo->SubjectPublicKeyInfo,
|
||||
&hPubKey)) {
|
||||
LOG_ERROR("CryptImportPublicKeyInfo() failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!cp_function_list.CryptCreateHash(hCryptProv, alg_id, 0, 0, &hash)) {
|
||||
LOG_ERROR("CryptCreateHash() failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!cp_function_list.CryptHashData(hash, (CONST BYTE *) data->data, data->len, 0)) {
|
||||
LOG_ERROR("CryptHashData() failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (cp_function_list.CryptVerifySignature(hash,
|
||||
(CONST BYTE *) sign_reversed.data,
|
||||
sign_reversed.len,
|
||||
hPubKey,
|
||||
NULL,
|
||||
0)) {
|
||||
LOG_DEBUG("sign is valid");
|
||||
*is_verified = true;
|
||||
} else {
|
||||
log_verify_error();
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
exit:
|
||||
str_t_clear(&sign_reversed);
|
||||
|
||||
if (hash) {
|
||||
cp_function_list.CryptDestroyHash(hash);
|
||||
}
|
||||
|
||||
if (hPubKey) {
|
||||
cp_function_list.CryptDestroyKey(hPubKey);
|
||||
}
|
||||
|
||||
if (hCryptProv) {
|
||||
cp_function_list.CryptReleaseContext(hCryptProv, 0);
|
||||
}
|
||||
|
||||
if (certificate) {
|
||||
cp_function_list.CertFreeCertificateContext(certificate);
|
||||
}
|
||||
|
||||
if (hStoreHandle) {
|
||||
if (!cp_function_list.CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG)) {
|
||||
LOG_ERROR("CertCloseStore() failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
LOG_TRACE("cryptopro_verify exit");
|
||||
} else {
|
||||
LOG_ERROR("cryptopro_verify exit with error. Last error code: 0x%08x",
|
||||
cp_function_list.GetLastError());
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,4 +26,7 @@ bool cryptopro_init(const char* cp_file);
|
|||
|
||||
int cryptopro_sign(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t *sign);
|
||||
|
||||
int cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t *data,
|
||||
const str_t *sign, bool* is_verified);
|
||||
|
||||
#endif // CRYPTOPRO_H_INCLUDED
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue