From 6d835c0958c35122582e91e1d1da883de884d9f6 Mon Sep 17 00:00:00 2001 From: alashkova Date: Fri, 14 Feb 2025 16:26:36 +0300 Subject: [PATCH] =?UTF-8?q?SUPPORT-8924.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D0=B0=20KeyUsage=20=D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=82=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=D0=BF=D0=B8=D1=81=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/capi.c | 1 + src/utils/capi.h | 9 ++++++ src/utils/cryptopro.c | 67 ++++++++++++++++++++++++++++++++----------- 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/utils/capi.c b/src/utils/capi.c index 5cc5f8a..4bf63ba 100644 --- a/src/utils/capi.c +++ b/src/utils/capi.c @@ -32,6 +32,7 @@ capi_function_list_init(library_t *lib, capi_function_list_t *fl) LIBRARY_RESOLVE(fl->CertVerifyCertificateChainPolicy, lib, "CertVerifyCertificateChainPolicy"); LIBRARY_RESOLVE(fl->CertFreeCertificateChain, lib, "CertFreeCertificateChain"); LIBRARY_RESOLVE(fl->CryptGenRandom, lib, "CryptGenRandom"); + LIBRARY_RESOLVE(fl->CertGetIntendedKeyUsage, lib, "CertGetIntendedKeyUsage"); #ifdef UNICODE LIBRARY_RESOLVE(fl->CryptSignHash, lib, "CryptSignHashW"); diff --git a/src/utils/capi.h b/src/utils/capi.h index ba5ed09..f19b875 100644 --- a/src/utils/capi.h +++ b/src/utils/capi.h @@ -207,6 +207,14 @@ DECLARE_FN(WINADVAPI, DWORD dwLen, BYTE *pbBuffer)); +DECLARE_FN(WINADVAPI, + BOOL, + CERT_GET_INTENDED_KEY_USAGE, + (DWORD dwCertEncodingType, + PCERT_INFO pCertInfo, + BYTE *pbKeyUsage, + IN DWORD cbKeyUsage)); + #ifdef UNICODE #define CRYPT_SIGN_HASH_FN CRYPT_SIGN_HASH_W_FN #define CRYPT_VERIFY_SIGNATURE_FN CRYPT_VERIFY_SIGNATURE_W_FN @@ -241,6 +249,7 @@ typedef struct { CERT_VERIFY_CERTIFICATE_CHAIN_POLICY_FN CertVerifyCertificateChainPolicy; CERT_FREE_CERTIFICATE_CHAIN_FN CertFreeCertificateChain; CRYPT_GEN_RANDOM_FN CryptGenRandom; + CERT_GET_INTENDED_KEY_USAGE_FN CertGetIntendedKeyUsage; } capi_function_list_t; diff --git a/src/utils/cryptopro.c b/src/utils/cryptopro.c index a6e2833..10422f2 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -210,26 +210,34 @@ exit: return is_verified; } -static void -log_sign_hash_data_last_error() +static bool +check_cert_key_usage(PCCERT_CONTEXT certificate) { - DWORD error = cp_function_list.GetLastError(); + bool is_digital_signature_key_usage = false; + BYTE key_usage; - switch (error) { - case ERROR_FUNCTION_FAILED: - LOG_ERROR("sign_hash_data exit with error. Last error code: " - "license is expired or not yet valid (0x%08x)", error); - break; + LOG_TRACE("check_cert_key_usage enter"); - case SCARD_W_WRONG_CHV: - LOG_ERROR("sign_hash_data exit with error. Last error code: " - "the wrong PIN was presented (0x%08x)", error); - break; - - default: - LOG_ERROR("sign_hash_data exit with error. Last error code: 0x%08x", error); - break; + if (cp_function_list.CertGetIntendedKeyUsage( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + certificate->pCertInfo, + &key_usage, + sizeof(key_usage))) { + if (key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE) { + is_digital_signature_key_usage = true; + } + } else { + LOG_ERROR("CertGetIntendedKeyUsage failed: 0x%08x", cp_function_list.GetLastError()); } + + if (is_digital_signature_key_usage) { + LOG_DEBUG("Certificate KeyUsage contains digitalSignature"); + } else { + LOG_ERROR("Certificate KeyUsage does not contain digitalSignature"); + } + + LOG_TRACE("check_cert_key_usage exit"); + return is_digital_signature_key_usage; } int @@ -247,6 +255,11 @@ open_signer_cert(cryptopro_context_t *ctx) goto error; } + if (!check_cert_key_usage(ctx->signer_cert)) { + goto error; + } + + LOG_TRACE("open_signer_cert exit"); return 0; @@ -274,6 +287,28 @@ close_signer_cert(cryptopro_context_t *ctx) LOG_TRACE("close_signer_cert exit"); } +static void +log_sign_hash_data_last_error() +{ + DWORD error = cp_function_list.GetLastError(); + + switch (error) { + case ERROR_FUNCTION_FAILED: + LOG_ERROR("sign_hash_data exit with error. Last error code: " + "license is expired or not yet valid (0x%08x)", error); + break; + + case SCARD_W_WRONG_CHV: + LOG_ERROR("sign_hash_data exit with error. Last error code: " + "the wrong PIN was presented (0x%08x)", error); + break; + + default: + LOG_ERROR("sign_hash_data exit with error. Last error code: 0x%08x", error); + break; + } +} + static int sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t *sign) {