From d9db9b393c257d56a1c3fe0955afc8033dcb50bc Mon Sep 17 00:00:00 2001 From: Pavel Zilke Date: Fri, 7 Feb 2025 13:17:03 +0300 Subject: [PATCH 1/7] DEVOPS-1922 grooming --- Dockerfile.micord | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile.micord b/Dockerfile.micord index 09f0521..a3eda9b 100644 --- a/Dockerfile.micord +++ b/Dockerfile.micord @@ -67,6 +67,4 @@ RUN echo "Installing certificates" \ && /opt/cprocsp/sbin/amd64/cryptsrv \ && su -c 'find /certs -regex ".*\.\(cer\|crt\)$" -exec /opt/cprocsp/bin/amd64/certmgr -install -file {} \;' $RUNTIME_USER -#USER ervu - ENTRYPOINT ["/entrypoint.sh"] From f9f0d56bab25d3cf24aac608c62192fa8ae5ad9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D0=B8=D0=BB=D1=8F=20=D0=90=D0=BB=D0=B0=D1=88?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Mon, 17 Feb 2025 10:16:42 +0300 Subject: [PATCH 2/7] # Conflicts: # CMakeLists.txt # conf/nginx.conf # src/utils/cryptopro.c --- conf/nginx.conf | 2 +- src/modules/service_sign.c | 6 +++ src/utils/cryptopro.c | 95 +++++++++++++++++++++++++------------- src/utils/cryptopro.h | 9 ++++ 4 files changed, 80 insertions(+), 32 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 0d5cd44..a91ef19 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -16,7 +16,7 @@ include /etc/nginx/conf-enabled.d/*.conf; http { log_format req_time '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for" $request_time'; + '"$http_user_agent" "$http_x_forwarded_for" $request_time "$upstream_addr"'; access_log /var/log/nginx/access.log req_time; proxy_temp_path /var/spool/nginx/tmp/proxy; fastcgi_temp_path /var/spool/nginx/tmp/fastcgi; diff --git a/src/modules/service_sign.c b/src/modules/service_sign.c index a9f75c8..dd886e7 100644 --- a/src/modules/service_sign.c +++ b/src/modules/service_sign.c @@ -134,6 +134,10 @@ sign_service_create(const sign_conf_t *conf) &conf->sign_cert_thumbprint, &conf->sign_cert_password); + if (open_signer_cert(&hsign->cryptopro_ctx)) { + goto error; + } + LOG_TRACE("sign_service_create exit"); return (HSign)hsign; @@ -150,6 +154,8 @@ sign_service_free(HSign hsign) if (ctx == NULL) return; + close_signer_cert(&ctx->cryptopro_ctx); + free(ctx); } diff --git a/src/utils/cryptopro.c b/src/utils/cryptopro.c index 1187c3b..71b3f63 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -14,6 +14,7 @@ static int sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*o static int reverse_sign(const str_t *sign, /*out*/ str_t *sign_reversed); static HCERTSTORE cert_open_store(); +static void cert_close_store(HCERTSTORE hStoreHandle); static PCCERT_CONTEXT get_signer_cert(const cryptopro_context_t *ctx, HCERTSTORE hStoreHandle); @@ -227,35 +228,65 @@ log_sign_hash_data_last_error() } } +int +open_signer_cert(cryptopro_context_t *ctx) +{ + LOG_TRACE("open_signer_cert enter"); + + ctx->cert_store = cert_open_store(); + if (ctx->cert_store == NULL) { + goto error; + } + + ctx->signer_cert = get_signer_cert(ctx, ctx->cert_store); + if (ctx->signer_cert == NULL) { + goto error; + } + + LOG_TRACE("open_signer_cert exit"); + + return 0; + +error: + LOG_ERROR("open_signer_cert exit with error. Last error code: 0x%08x", + cp_function_list.GetLastError()); + close_signer_cert(ctx); + return -1; +} + +void +close_signer_cert(cryptopro_context_t *ctx) +{ + LOG_TRACE("close_signer_cert enter"); + + if (ctx->signer_cert) { + cp_function_list.CertFreeCertificateContext(ctx->signer_cert); + ctx->signer_cert = NULL; + } + + cert_close_store(ctx->cert_store); + ctx->cert_store = NULL; + + LOG_TRACE("close_signer_cert exit"); +} + static int sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t *sign) { int rc = -1; - HCERTSTORE hStoreHandle; - PCCERT_CONTEXT pSignerCert = NULL; BOOL bReleaseContext = FALSE; HCRYPTPROV hCryptProv; HCRYPTHASH hash = 0; BYTE *pbSignedMessageBlob; DWORD cbSignedMessageBlob; - hStoreHandle = cert_open_store(); - if (hStoreHandle == NULL) { - goto exit; - } - - pSignerCert = get_signer_cert(ctx, hStoreHandle); - if (pSignerCert == NULL) { - goto exit; - } - - if (!verify_cert_chain(pSignerCert)) { + if (!verify_cert_chain(ctx->signer_cert)) { goto exit; } if (!cp_function_list.CryptAcquireCertificatePrivateKey( - pSignerCert, - CRYPT_ACQUIRE_SILENT_FLAG, + ctx->signer_cert, + CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, NULL, @@ -301,15 +332,6 @@ exit: cp_function_list.CryptReleaseContext(hCryptProv, 0); } - if (pSignerCert) { - cp_function_list.CertFreeCertificateContext(pSignerCert); - } - - if (hStoreHandle) { - if (!cp_function_list.CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG)) { - LOG_ERROR("CertCloseStore() failed"); - } - } if (rc) { log_sign_hash_data_last_error(); @@ -348,7 +370,7 @@ cert_open_store() hStoreHandle = cp_function_list.CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, - CERT_SYSTEM_STORE_CURRENT_USER, + CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, L"MY"); if (hStoreHandle == NULL) { @@ -357,10 +379,25 @@ cert_open_store() } LOG_DEBUG("The MY store is open"); - + LOG_TRACE("cert_open_store exit"); return hStoreHandle; } + +static void +cert_close_store(HCERTSTORE hStoreHandle) +{ + LOG_TRACE("cert_close_store enter"); + + if (hStoreHandle) { + if (!cp_function_list.CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG)) { + LOG_ERROR("CertCloseStore() failed"); + } + } + + LOG_TRACE("cert_close_store exit"); +} + static PCCERT_CONTEXT get_cert_by_thumbprint(HCERTSTORE hStoreHandle, const str_t* thumbprint) { @@ -681,11 +718,7 @@ exit: cp_function_list.CertFreeCertificateContext(certificate); } - if (hStoreHandle) { - if (!cp_function_list.CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG)) { - LOG_ERROR("CertCloseStore() failed"); - } - } + cert_close_store(hStoreHandle); if (rc == 0) { LOG_TRACE("cryptopro_verify exit"); diff --git a/src/utils/cryptopro.h b/src/utils/cryptopro.h index 6aed9b0..6391017 100644 --- a/src/utils/cryptopro.h +++ b/src/utils/cryptopro.h @@ -6,10 +6,16 @@ #include #include +#include "capi.h" + typedef struct cryptopro_context_s { const str_t *cert_thumbprint; const str_t *password; + + HCERTSTORE cert_store; + PCCERT_CONTEXT signer_cert; + } cryptopro_context_t; @@ -24,6 +30,9 @@ cryptopro_context_set(cryptopro_context_t *ctx, const str_t *cert_thumbprint, co bool cryptopro_init(const char* cp_file); +int open_signer_cert(cryptopro_context_t *ctx); +void close_signer_cert(cryptopro_context_t *ctx); + 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, From 4b08cab158435aaa6b915c0a74a6b1220e511066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D0=B8=D0=BB=D1=8F=20=D0=90=D0=BB=D0=B0=D1=88?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Mon, 17 Feb 2025 12:07:34 +0300 Subject: [PATCH 3/7] =?UTF-8?q?DEVOPS-1922.=20=D0=B4=D0=BE=D0=BA=D0=B5?= =?UTF-8?q?=D1=80-=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=20=D1=81=20=D0=9A=D1=80?= =?UTF-8?q?=D0=B8=D0=BF=D1=82=D0=BE=20=D0=9F=D1=80=D0=BE=20=D0=9A=D0=A12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile.micord | 22 +++++++++++++--------- entrypoint.sh | 20 +++++++++++++------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Dockerfile.micord b/Dockerfile.micord index 8507186..a3eda9b 100644 --- a/Dockerfile.micord +++ b/Dockerfile.micord @@ -1,5 +1,6 @@ -ARG BUILDER_IMAGE=repo.micord.ru/alt/alt-cprocsp:c10f1-5.0.13000-20241129 +ARG BUILDER_IMAGE=repo.micord.ru/alt/alt-cprocsp-kc2:c10f1-5.0.13000-20250124 ARG RUNTIME_IMAGE=registry.altlinux.org/basealt/altsp:c10f1 +ARG RUNTIME_USER=ervu FROM ${BUILDER_IMAGE} AS builder @@ -30,17 +31,19 @@ RUN mkdir -p .build \ FROM ${RUNTIME_IMAGE} ENV TZ=Europe/Moscow +ARG RUNTIME_USER +ENV RUNTIME_USER=$RUNTIME_USER COPY entrypoint.sh /entrypoint.sh RUN apt-get update \ - && apt-get -y install glib2 libfcgi libjson-glib libuuid \ + && apt-get -y install glib2 libfcgi libjson-glib libuuid su startup \ && apt-get clean \ && rm -f /var/cache/apt/*.bin \ && rm -f /var/lib/apt/lists/update* \ && chmod +x /entrypoint.sh \ - && groupadd --system --gid 500 ervu \ - && adduser --system --no-create-home --uid 500 --gid 500 ervu + && groupadd --system --gid 500 $RUNTIME_USER \ + && adduser --system --no-create-home --uid 500 --gid 500 $RUNTIME_USER COPY --from=builder /usr/lib/locale/ru_RU.utf8 /usr/lib/locale/ru_RU.utf8 COPY --from=builder /etc/opt/cprocsp /etc/opt/cprocsp @@ -52,15 +55,16 @@ COPY --from=builder /build/.build/ervu-sign-module /opt/ervu-sign-module/ervu-si EXPOSE 9009 -COPY --chown=ervu:ervu conf/cacerts /cacerts -COPY --chown=ervu:ervu conf/certs /certs +COPY --chown=$RUNTIME_USER:$RUNTIME_USER conf/cacerts /cacerts +COPY --chown=$RUNTIME_USER:$RUNTIME_USER conf/certs /certs + RUN echo "Installing CA certificates" \ + && /opt/cprocsp/sbin/amd64/cryptsrv \ && find /cacerts -regex ".*\.\(cer\|crt\)$" -exec /opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file {} \; -USER ervu - RUN echo "Installing certificates" \ - && find /certs -regex ".*\.\(cer\|crt\)$" -exec /opt/cprocsp/bin/amd64/certmgr -install -file {} \; + && /opt/cprocsp/sbin/amd64/cryptsrv \ + && su -c 'find /certs -regex ".*\.\(cer\|crt\)$" -exec /opt/cprocsp/bin/amd64/certmgr -install -file {} \;' $RUNTIME_USER ENTRYPOINT ["/entrypoint.sh"] diff --git a/entrypoint.sh b/entrypoint.sh index dd2c6eb..f40af3d 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,19 +1,25 @@ #!/bin/bash -username=$(whoami) +username=$RUNTIME_USER + +set -e +echo "Starting cryptsrv" +/opt/cprocsp/sbin/amd64/cryptsrv +echo $? +set +e if [ ! -d /var/opt/cprocsp/keys/$username ]; then mkdir -m 700 /var/opt/cprocsp/keys/$username - cp -r ~/keys/* /var/opt/cprocsp/keys/$username/ + cp -r /home/$username/keys/* /var/opt/cprocsp/keys/$username/ chown -R $username:$username /var/opt/cprocsp/keys/$username fi -/opt/cprocsp/bin/amd64/csptest -absorb -certs -autoprov +su - -c '/opt/cprocsp/bin/amd64/csptest -absorb -certs -autoprov' $username echo "Installing CA certificates" -find ~/cacerts -regex ".*\.\(cer\|crt\)$" -exec /opt/cprocsp/bin/amd64/certmgr -install -store uCA -file {} \; +su - -c 'find ~/cacerts -regex ".*\.\(cer\|crt\)$" -exec /opt/cprocsp/bin/amd64/certmgr -install -store uCA -file {} \;' $username -echo "Installing certificates" \ -find ~/certs -regex ".*\.\(cer\|crt\)$" -exec /opt/cprocsp/bin/amd64/certmgr -install -file {} \; +echo "Installing certificates" +su - -c 'find ~/certs -regex ".*\.\(cer\|crt\)$" -exec /opt/cprocsp/bin/amd64/certmgr -install -file {} \;' $username -/opt/ervu-sign-module/ervu-sign-module +su - -c '/opt/ervu-sign-module/ervu-sign-module' $username From 339a8f9b1bde116f55357fde937c18c6bb9264b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D0=B8=D0=BB=D1=8F=20=D0=90=D0=BB=D0=B0=D1=88?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Tue, 18 Feb 2025 09:54:37 +0300 Subject: [PATCH 4/7] =?UTF-8?q?SUPPORT-8924.=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B0=20KeyUsage=20=D1=81=D0=B5=D1=80=D1=82=D0=B8?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D0=B0=D1=82=D0=B0=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=BF=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 (cherry picked from commit 6d835c0958c35122582e91e1d1da883de884d9f6) --- 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 71b3f63..5e86db4 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -206,26 +206,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 @@ -243,6 +251,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; @@ -270,6 +283,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) { From fe04ee65a1d7ef2dc5d5f40be52b6347937d78fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D0=B8=D0=BB=D1=8F=20=D0=90=D0=BB=D0=B0=D1=88?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Tue, 18 Feb 2025 10:24:16 +0300 Subject: [PATCH 5/7] Merge branch 'origin/release/1.2.4' into master # Conflicts: # CMakeLists.txt # Dockerfile.micord # entrypoint.sh # src/modules/service_sign.c # src/utils/cryptopro.c # src/utils/cryptopro.h --- CMakeLists.txt | 1 + README.md | 16 ++++ conf/cacerts/ucfk_2024.crt | Bin 0 -> 2017 bytes src/main_conf.c | 2 + src/modules/service_sign.c | 19 ++++- src/utils/cryptopro.c | 76 ++++++++++++++++- src/utils/cryptopro.h | 17 ++-- src/utils/timer.c | 162 +++++++++++++++++++++++++++++++++++++ src/utils/timer.h | 60 ++++++++++++++ 9 files changed, 341 insertions(+), 12 deletions(-) create mode 100644 conf/cacerts/ucfk_2024.crt create mode 100644 src/utils/timer.c create mode 100644 src/utils/timer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b970d76..f7d6ee5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,7 @@ ADD_EXECUTABLE (${PROJECT_NAME} ${UTILS_DIR}/library.c ${UTILS_DIR}/logger.c ${UTILS_DIR}/str_t.c + ${UTILS_DIR}/timer.c ${UTILS_DIR}/uuid.c ${FCGISRV_DIR}/fcgi_map.c ${FCGISRV_DIR}/fcgi_server.c diff --git a/README.md b/README.md index 96c34dc..a4b27e3 100644 --- a/README.md +++ b/README.md @@ -100,3 +100,19 @@ sign_cert_password = \*\*\*\* *\# пароль от контейнера* - В секции **\[verify\]** задать настройки проверки подписи маркера доступа: location = /verify *\# значение по умолчанию: /verify* esia_cert_thumbprint = sha1_thumbprint_of_esia_cert0,sha1_thumbprint_of_esia_cert1 *\# список SHA1 отпечатков сертификатов ЕСИА, указанных через запятую (без пробелов)* + +## Логирование времени обработки запросов + +***Для включения*** логирования времени обработки запросов необходимо задать переменную окружения SIGN_LOG_TIME: + +``` +export SIGN_LOG_TIME=on +``` + +***Для отключения*** логирования времени обработки запросов необходимо удалить переменную окружения SIGN_LOG_TIME: + +``` +unset SIGN_LOG_TIME +``` + + diff --git a/conf/cacerts/ucfk_2024.crt b/conf/cacerts/ucfk_2024.crt new file mode 100644 index 0000000000000000000000000000000000000000..1d595eb8ec1f7607978dfc9adc9cb44bb8f0a33f GIT binary patch literal 2017 zcmeHIU2GIp6y7^COn=x?>0)aiO0R*ow6wElX12Rs#DLaBR4~-0fIk%Lwv-Kxt=nBp zNP*ocUF5eFt2DKy)m9oqG)w8q((P^)P-9KtTs0;>kRU#Y@kNQm#6U22Cq;^gCcc_^ znRCzi?mg!_=YAKAv(@bjt4qyxuEQ~R>n+4f^ibFgv7Qz_DQW?)F z>k=DDPL>J|mkTt|oGwt+d%BD zyKgbUAPp*og}2f>Kj7K4dFx7FYx~xQ?JqWPcK@Ex+taIbR=J$;*LvJ8P~BBJsLw;a zN%MMq6_Xfe2iPl^#8VWHU>qaNz$EMBOs44KeT#ADl*v2m#5g8#g7dCW=N&j#@7Cj4 zQ=&k**_$Hl#|WNGb#xC#@l@*gF-*?xQ586OylA!K2u5){l~IIOfC=7oiW7I<1~xw3(DnhAqqR-GZC+0kUBbDex5Lf0a$tlRY&RxZ5GOH8SJkee8UWO2 zr7(}Dn$1&{M1gz?CETVGg@uqV%lt;XL~i~GH~&O1$POO5NHT~Y4AK@{@VRZn@ztX* zEZh0ziseUtSkUoS+i>`8gH(?gWX1n7@}FeHm~VN#aQM-V25H&*zjuX849CMz!0DeS zlp0_YR17U0Dh-!x@%!7B+3g-57wz^y zdrP3%tM~$TPh*?CIpEPi(-e=d1(c!kp|bFjKf|@V$5+egOJy==P8uPS3o1dMu|fE^ zhx#FO)w~{UQs^fLUA8)K5PPs62k7Zz*w2C(!zr#!=Dpz~d^%2XjB9`?;Z#$=T5X~@ z<~1&En8dM^IGm!alfM)xW#Nk)*Ub*Gy(xKP;nYiGu;A&qwGxkD1Sc@g4yEMCd`m9v zeuJtGw_Ueu{L?8WnL$BQKvy(StE`T@!d!M|g~Q=CQ93B9rf8t4U^UD3@!LmkeR#!( zELVi5_b$!9u>E57_Z1x#)6Y)#){{ppJv9}-TJ+|Ez}5OI`uV!K^`-gl^W&Lkv+It< TJtf8JwZmt6+KURjy>)*8f_6~{ literal 0 HcmV?d00001 diff --git a/src/main_conf.c b/src/main_conf.c index feeb0c4..1238982 100644 --- a/src/main_conf.c +++ b/src/main_conf.c @@ -1,4 +1,5 @@ #include "main_conf.h" +#include "version.h" #include #include @@ -61,6 +62,7 @@ main_conf_load(main_conf_t* conf, const char *filename, const conf_file_context_ goto error; } + LOG_INFO("version = " APP_VERSION); LOG_INFO("conf_file = %s", conf->conf_file); LOG_TRACE("main_conf_load exit with success"); return 0; diff --git a/src/modules/service_sign.c b/src/modules/service_sign.c index dd886e7..ea237a7 100644 --- a/src/modules/service_sign.c +++ b/src/modules/service_sign.c @@ -4,6 +4,7 @@ #include "utils/cryptopro.h" #include "utils/json_writer.h" +#include "utils/timer.h" #include "utils/uuid.h" #define SIGN_CONF_SECTION "sign" @@ -26,6 +27,8 @@ typedef struct sign_service_s { cryptopro_context_t cryptopro_ctx; + timer_context_t timer_ctx; + } sign_service_t; typedef struct fcgi_sign_request_s { @@ -130,9 +133,12 @@ sign_service_create(const sign_conf_t *conf) hsign->conf = conf; + init_timers(&hsign->timer_ctx); + cryptopro_context_set(&hsign->cryptopro_ctx, &conf->sign_cert_thumbprint, - &conf->sign_cert_password); + &conf->sign_cert_password, + &hsign->timer_ctx); if (open_signer_cert(&hsign->cryptopro_ctx)) { goto error; @@ -163,11 +169,13 @@ fcgi_handler_status_t fcgi_sign_handler(FCGX_Request* request, void* ctx) { fcgi_handler_status_t status = HANDLER_ERROR; - const sign_service_t *hsign = (const sign_service_t *) ctx; + sign_service_t *hsign = (sign_service_t *) ctx; fcgi_sign_request_t req_info = {0}; LOG_TRACE("fcgi_sign_handler enter"); + timer_on_fcgi_sign_handler_enter(&hsign->timer_ctx); + if (request == NULL) { LOG_ERROR("fcgi_sign_handler exit with error. Desc: request is NULL"); goto exit; @@ -190,11 +198,15 @@ fcgi_sign_handler(FCGX_Request* request, void* ctx) goto exit; } + timer_on_sign_content_enter(&hsign->timer_ctx); + if (sign_content_with_state(hsign, &req_info)) { status = HANDLER_ERROR; goto exit; } + timer_on_sign_content_exit(&hsign->timer_ctx); + // status = HANDLER_SUCCESS; exit: @@ -202,6 +214,9 @@ exit: fcgi_sign_request_clear(&req_info); + timer_on_fcgi_sign_handler_exit(&hsign->timer_ctx); + timer_log_sign(&hsign->timer_ctx); + LOG_TRACE("fcgi_sign_handler exit"); return status; } diff --git a/src/utils/cryptopro.c b/src/utils/cryptopro.c index 5e86db4..446a447 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -180,17 +180,21 @@ exit: } static bool -verify_cert_chain(PCCERT_CONTEXT certificate) +verify_cert_chain(PCCERT_CONTEXT certificate, timer_context_t *timer_ctx) { bool is_verified = false; LOG_TRACE("verify_cert_chain enter"); + timer_on_get_cert_chain_enter(timer_ctx); + PCCERT_CHAIN_CONTEXT chain_ctx = get_cert_chain(certificate); if (chain_ctx == NULL) { goto exit; } + timer_on_get_cert_chain_exit(timer_ctx); + if (!check_cert_chain_policy(chain_ctx)) { goto exit; } @@ -305,6 +309,48 @@ log_sign_hash_data_last_error() } } +int +open_signer_cert(cryptopro_context_t *ctx) +{ + LOG_TRACE("open_signer_cert enter"); + + ctx->cert_store = cert_open_store(); + if (ctx->cert_store == NULL) { + goto error; + } + + ctx->signer_cert = get_signer_cert(ctx, ctx->cert_store); + if (ctx->signer_cert == NULL) { + goto error; + } + + LOG_TRACE("open_signer_cert exit"); + + return 0; + +error: + LOG_ERROR("open_signer_cert exit with error. Last error code: 0x%08x", + cp_function_list.GetLastError()); + close_signer_cert(ctx); + return -1; +} + +void +close_signer_cert(cryptopro_context_t *ctx) +{ + LOG_TRACE("close_signer_cert enter"); + + if (ctx->signer_cert) { + cp_function_list.CertFreeCertificateContext(ctx->signer_cert); + ctx->signer_cert = NULL; + } + + cert_close_store(ctx->cert_store); + ctx->cert_store = NULL; + + LOG_TRACE("close_signer_cert exit"); +} + static int sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t *sign) { @@ -315,10 +361,16 @@ sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t BYTE *pbSignedMessageBlob; DWORD cbSignedMessageBlob; - if (!verify_cert_chain(ctx->signer_cert)) { + timer_on_verify_cert_chain_enter(ctx->timer_ctx); + + if (!verify_cert_chain(ctx->signer_cert, ctx->timer_ctx)) { goto exit; } + timer_on_verify_cert_chain_exit(ctx->timer_ctx); + + timer_on_acquire_private_key_enter(ctx->timer_ctx); + if (!cp_function_list.CryptAcquireCertificatePrivateKey( ctx->signer_cert, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_CACHE_FLAG, @@ -330,6 +382,8 @@ sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t goto exit; } + timer_on_acquire_private_key_exit(ctx->timer_ctx); + if (!cp_function_list.CryptCreateHash(hCryptProv, CALG_GR3411_2012_256, 0, 0, &hash)) { LOG_ERROR("CryptCreateHash() failed"); goto exit; @@ -339,6 +393,8 @@ sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t LOG_ERROR("CryptHashData() failed"); goto exit; } + + timer_on_sign_hash_enter(ctx->timer_ctx); if (!cp_function_list.CryptSignHash(hash, AT_KEYEXCHANGE, NULL, 0, NULL, &cbSignedMessageBlob)) { LOG_ERROR("CryptSignHash() failed"); @@ -353,6 +409,8 @@ sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t goto exit; } + timer_on_sign_hash_exit(ctx->timer_ctx); + sign->data = (char*)pbSignedMessageBlob; sign->len = (size_t)cbSignedMessageBlob; @@ -662,9 +720,14 @@ cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t* da HCRYPTKEY hPubKey = 0; str_t sign_reversed = str_t_null; ALG_ID alg_id; + timer_context_t timer_ctx = {}; + + init_timers(&timer_ctx); LOG_TRACE("cryptopro_verify enter"); + timer_on_cryptopro_verify_enter(&timer_ctx); + *is_verified = false; if (alg_id_from_str(alg, &alg_id, verify_error)) { @@ -685,10 +748,14 @@ cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t* da goto exit; } - if (!verify_cert_chain(certificate)) { + timer_on_verify_cert_chain_enter(&timer_ctx); + + if (!verify_cert_chain(certificate, &timer_ctx)) { goto exit; } + timer_on_verify_cert_chain_exit(&timer_ctx); + if (!cp_function_list.CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_GOST_2012_256, CRYPT_VERIFYCONTEXT)) { LOG_ERROR("CryptAcquireContext() failed"); @@ -762,6 +829,9 @@ exit: cp_function_list.GetLastError()); } + timer_on_cryptopro_verify_exit(&timer_ctx); + timer_log_verify(&timer_ctx); + return rc; } diff --git a/src/utils/cryptopro.h b/src/utils/cryptopro.h index 6391017..5919fc6 100644 --- a/src/utils/cryptopro.h +++ b/src/utils/cryptopro.h @@ -1,31 +1,34 @@ #ifndef CRYPTOPRO_H_INCLUDED #define CRYPTOPRO_H_INCLUDED +#include "capi.h" #include "str_t.h" +#include "timer.h" #include #include -#include "capi.h" - typedef struct cryptopro_context_s { - const str_t *cert_thumbprint; - const str_t *password; + const str_t *cert_thumbprint; + const str_t *password; + timer_context_t *timer_ctx; - HCERTSTORE cert_store; - PCCERT_CONTEXT signer_cert; + HCERTSTORE cert_store; + PCCERT_CONTEXT signer_cert; } cryptopro_context_t; static inline void -cryptopro_context_set(cryptopro_context_t *ctx, const str_t *cert_thumbprint, const str_t *password) +cryptopro_context_set(cryptopro_context_t *ctx, const str_t *cert_thumbprint, + const str_t *password, timer_context_t *timer_ctx) { assert(ctx != NULL); ctx->cert_thumbprint = cert_thumbprint; ctx->password = password; + ctx->timer_ctx = timer_ctx; } bool cryptopro_init(const char* cp_file); diff --git a/src/utils/timer.c b/src/utils/timer.c new file mode 100644 index 0000000..c2fb2bc --- /dev/null +++ b/src/utils/timer.c @@ -0,0 +1,162 @@ +#include "timer.h" +#include "logger.h" + +#include +#include + +#define ENV_SIGN_LOG_TIME "SIGN_LOG_TIME" + +void +init_timers(timer_context_t *ctx) +{ + const char* slt = getenv(ENV_SIGN_LOG_TIME); + if (slt != NULL) { + LOG_INFO("environment variable '" ENV_SIGN_LOG_TIME "'='%s' -> timings logging: ON", slt); + ctx->is_timer_on = true; + } else { + LOG_INFO("environment variable '" ENV_SIGN_LOG_TIME "' does not exist " + "-> timings logging: OFF"); + ctx->is_timer_on = false; + } +} + +static inline void +set_timer(bool is_timer_on, struct timeval *timer, const char *timer_name) +{ + if (!is_timer_on) { + return; + } + + if (gettimeofday(timer, NULL)) { + LOG_WARN("gettimeofday(%s) failed. Desc: %s", timer_name, strerror(errno)); + } +} + +static inline time_t +get_diff(const struct timeval *tv_start, const struct timeval *tv_end) +{ + return (tv_end->tv_sec - tv_start->tv_sec) * 1000 + + (tv_end->tv_usec - tv_start->tv_usec) / 1000; +} + +void +timer_on_fcgi_sign_handler_enter(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->sign_handler_start, "sign_handler_start"); +} + +void +timer_on_fcgi_sign_handler_exit(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->sign_handler_end, "sign_handler_end"); +} + +void +timer_on_sign_content_enter(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->sign_content_start, "sign_content_start"); +} + +void +timer_on_sign_content_exit(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->sign_content_end, "sign_content_end"); +} + +void +timer_on_verify_cert_chain_enter(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->verify_cert_chain_start, "verify_cert_chain_start"); +} + +void +timer_on_verify_cert_chain_exit(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->verify_cert_chain_end, "verify_cert_chain_end"); +} + +void +timer_on_acquire_private_key_enter(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->acquire_private_key_start, "acquire_private_key_start"); +} + +void +timer_on_acquire_private_key_exit(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->acquire_private_key_end, "acquire_private_key_end"); +} + +void timer_on_sign_hash_enter(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->sign_hash_start, "sign_hash_start"); +} + +void timer_on_sign_hash_exit(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->sign_hash_end, "sign_hash_end"); +} + +void +timer_on_get_cert_chain_enter(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->get_cert_chain_start, "get_cert_chain_start"); +} + +void +timer_on_get_cert_chain_exit(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->get_cert_chain_end, "get_cert_chain_end"); +} + +void timer_on_cryptopro_verify_enter(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->cryptopro_verify_start, "cryptopro_verify_start"); +} + +void timer_on_cryptopro_verify_exit(timer_context_t *ctx) +{ + set_timer(ctx->is_timer_on, &ctx->cryptopro_verify_end, "cryptopro_verify_end"); +} + +void +timer_log_sign(const timer_context_t *ctx) +{ + if (!ctx->is_timer_on) { + return; + } + + time_t diff_sign_handler = get_diff(&ctx->sign_handler_start, &ctx->sign_handler_end); + time_t diff_sign_content = get_diff(&ctx->sign_content_start, &ctx->sign_content_end); + time_t diff_verify_cert_chain = get_diff(&ctx->verify_cert_chain_start, + &ctx->verify_cert_chain_end); + time_t diff_get_cert_chain = get_diff(&ctx->get_cert_chain_start, &ctx->get_cert_chain_end); + time_t diff_acquire_private_key = get_diff(&ctx->acquire_private_key_start, + &ctx->acquire_private_key_end); + time_t diff_sign_hash = get_diff(&ctx->sign_hash_start, &ctx->sign_hash_end); + + LOG_INFO("sign_handler: %ld sign_content: %ld verify_cert_chain: %ld " + "get_cert_chain: %ld acquire_private_key: %ld sign_hash: %ld", + diff_sign_handler, + diff_sign_content, + diff_verify_cert_chain, + diff_get_cert_chain, + diff_acquire_private_key, + diff_sign_hash); +} + +void +timer_log_verify(const timer_context_t *ctx) +{ + if (!ctx->is_timer_on) { + return; + } + + time_t diff_verify_handler = get_diff(&ctx->cryptopro_verify_start, &ctx->cryptopro_verify_end); + time_t diff_verify_cert_chain = get_diff(&ctx->verify_cert_chain_start, + &ctx->verify_cert_chain_end); + + LOG_INFO("verify_handler: %ld verify_cert_chain: %ld", + diff_verify_handler, + diff_verify_cert_chain); +} \ No newline at end of file diff --git a/src/utils/timer.h b/src/utils/timer.h new file mode 100644 index 0000000..762ee35 --- /dev/null +++ b/src/utils/timer.h @@ -0,0 +1,60 @@ +#ifndef TIMER_H_INCLUDED +#define TIMER_H_INCLUDED + +#include +#include + +typedef struct timer_context_s +{ + bool is_timer_on; + + struct timeval sign_handler_start; + struct timeval sign_handler_end; + + struct timeval sign_content_start; + struct timeval sign_content_end; + + struct timeval verify_cert_chain_start; + struct timeval verify_cert_chain_end; + + struct timeval acquire_private_key_start; + struct timeval acquire_private_key_end; + + struct timeval sign_hash_start; + struct timeval sign_hash_end; + + struct timeval get_cert_chain_start; + struct timeval get_cert_chain_end; + + struct timeval cryptopro_verify_start; + struct timeval cryptopro_verify_end; + +} timer_context_t; + +void init_timers(timer_context_t *ctx); + +void timer_on_fcgi_sign_handler_enter(timer_context_t *ctx); +void timer_on_fcgi_sign_handler_exit(timer_context_t *ctx); + +void timer_on_sign_content_enter(timer_context_t *ctx); +void timer_on_sign_content_exit(timer_context_t *ctx); + +void timer_on_verify_cert_chain_enter(timer_context_t *ctx); +void timer_on_verify_cert_chain_exit(timer_context_t *ctx); + +void timer_on_acquire_private_key_enter(timer_context_t *ctx); +void timer_on_acquire_private_key_exit(timer_context_t *ctx); + +void timer_on_sign_hash_enter(timer_context_t *ctx); +void timer_on_sign_hash_exit(timer_context_t *ctx); + +void timer_on_get_cert_chain_enter(timer_context_t *ctx); +void timer_on_get_cert_chain_exit(timer_context_t *ctx); + +void timer_on_cryptopro_verify_enter(timer_context_t *ctx); +void timer_on_cryptopro_verify_exit(timer_context_t *ctx); + +void timer_log_sign(const timer_context_t *ctx); +void timer_log_verify(const timer_context_t *ctx); + +#endif // TIMER_H_INCLUDED \ No newline at end of file From 0538b120bcc7f8b8feae6a9d0d1dfc91ddebcd7b Mon Sep 17 00:00:00 2001 From: alashkova Date: Tue, 18 Feb 2025 10:29:57 +0300 Subject: [PATCH 6/7] fix after merge --- src/utils/cryptopro.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/src/utils/cryptopro.c b/src/utils/cryptopro.c index 446a447..10422f2 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -309,48 +309,6 @@ log_sign_hash_data_last_error() } } -int -open_signer_cert(cryptopro_context_t *ctx) -{ - LOG_TRACE("open_signer_cert enter"); - - ctx->cert_store = cert_open_store(); - if (ctx->cert_store == NULL) { - goto error; - } - - ctx->signer_cert = get_signer_cert(ctx, ctx->cert_store); - if (ctx->signer_cert == NULL) { - goto error; - } - - LOG_TRACE("open_signer_cert exit"); - - return 0; - -error: - LOG_ERROR("open_signer_cert exit with error. Last error code: 0x%08x", - cp_function_list.GetLastError()); - close_signer_cert(ctx); - return -1; -} - -void -close_signer_cert(cryptopro_context_t *ctx) -{ - LOG_TRACE("close_signer_cert enter"); - - if (ctx->signer_cert) { - cp_function_list.CertFreeCertificateContext(ctx->signer_cert); - ctx->signer_cert = NULL; - } - - cert_close_store(ctx->cert_store); - ctx->cert_store = NULL; - - LOG_TRACE("close_signer_cert exit"); -} - static int sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t *sign) { From 56e47c718adafcd0c7bb6e9f8d232fc2d4919f9a Mon Sep 17 00:00:00 2001 From: alashkova Date: Tue, 18 Feb 2025 10:34:16 +0300 Subject: [PATCH 7/7] =?UTF-8?q?=D0=92=D0=B5=D1=80=D1=81=D0=B8=D1=8F=201.3.?= =?UTF-8?q?2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7d6ee5..3c05ab1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED (VERSION 3.0) SET (CMAKE_C_COMPILER "gcc") -PROJECT (ervu-sign-module VERSION 1.3.1 LANGUAGES C) +PROJECT (ervu-sign-module VERSION 1.3.2 LANGUAGES C) IF (CMAKE_VERBOSE) SET (CMAKE_VERBOSE_MAKEFILE 1)