| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent dfc192f commit 5871768
38 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,6 +22,11 @@ on: | |||
| 22 | 22 | required: false | |
| 23 | 23 | type: string | |
| 24 | 24 | default: '' | |
| 25 | + pkcs11-store-test: | ||
| 26 | + description: Whether to enable the PKCS#11-backed crypto STORE test | ||
| 27 | + required: false | ||
| 28 | + type: boolean | ||
| 29 | + default: false | ||
| 25 | 30 | secrets: | |
| 26 | 31 | CACHIX_AUTH_TOKEN: | |
| 27 | 32 | description: Cachix auth token for nodejs.cachix.org. | |
@@ -84,6 +89,7 @@ jobs: | |||
| 84 | 89 | --arg ccache "${NIX_SCCACHE:-null}" \ | |
| 85 | 90 | --arg devTools '[]' \ | |
| 86 | 91 | --arg benchmarkTools '[]' \ | |
| 92 | + --arg pkcs11 ${{ inputs.pkcs11-store-test }} \ | ||
| 87 | 93 | ${{ inputs.extra-nix-flags }} \ | |
| 88 | 94 | --run ' | |
| 89 | 95 | make -C "$TAR_DIR" run-ci -j4 V=1 TEST_CI_ARGS="-p actions --measure-flakiness 9 --skip-tests=$CI_SKIP_TESTS" | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -69,6 +69,7 @@ jobs: | |||
| 69 | 69 | ++ builtins.attrValues ( | |
| 70 | 70 | { inherit (import <nixpkgs> {}) nixfmt-tree sccache; } | |
| 71 | 71 | // import ./tools/nix/openssl-matrix.nix {} | |
| 72 | + // import ./tools/nix/pkcs11.nix {} | ||
| 72 | 73 | )")" \ | |
| 73 | 74 | | xargs nix-store --realise \ | |
| 74 | 75 | | xargs nix-store --query --requisites \ | |
@@ -77,6 +78,7 @@ jobs: | |||
| 77 | 78 | ||
| 78 | 79 | - name: Compute requisites before change | |
| 79 | 80 | shell: bash # See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference, we want the pipefail option. | |
| 81 | + # TODO(panva): add `// import ./tools/nix/pkcs11.nix {}` once landed | ||
| 80 | 82 | run: | | |
| 81 | 83 | git reset HEAD^ --hard | |
| 82 | 84 | nix-store --query --references "$( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -246,6 +246,7 @@ jobs: | |||
| 246 | 246 | with: | |
| 247 | 247 | runner: ubuntu-24.04-arm | |
| 248 | 248 | v8-nar: ${{ needs.build-aarch64-linux-v8.outputs.local-cache && 'libv8-aarch64-linux.nar' }} | |
| 249 | + pkcs11-store-test: ${{ matrix.openssl.attr == 'openssl_3_5' }} | ||
| 249 | 250 | # Override just the `openssl` attr of the default shared-lib set with | |
| 250 | 251 | # the matrix-selected nixpkgs attribute (e.g. `openssl_3_6`). All | |
| 251 | 252 | # other shared libs (brotli, cares, libuv, …) keep their defaults. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,13 +4,13 @@ | |||
| 4 | 4 | #include <openssl/dh.h> | |
| 5 | 5 | #include <openssl/evp.h> | |
| 6 | 6 | #include <openssl/hmac.h> | |
| 7 | + #include <openssl/pem.h> | ||
| 7 | 8 | #include <openssl/pkcs12.h> | |
| 8 | 9 | #include <openssl/rand.h> | |
| 9 | 10 | #include <openssl/x509v3.h> | |
| 10 | 11 | #if NCRYPTO_USE_BORINGSSL_EVP_DO_ALL_FALLBACK | |
| 11 | 12 | #include <openssl/bytestring.h> | |
| 12 | 13 | #include <openssl/cipher.h> | |
| 13 | - #include <openssl/pem.h> | ||
| 14 | 14 | #endif | |
| 15 | 15 | #include <algorithm> | |
| 16 | 16 | #include <array> | |
@@ -21,6 +21,8 @@ | |||
| 21 | 21 | #include <openssl/core_names.h> | |
| 22 | 22 | #include <openssl/params.h> | |
| 23 | 23 | #include <openssl/provider.h> | |
| 24 | + #include <openssl/store.h> | ||
| 25 | + #include <openssl/ui.h> | ||
| 24 | 26 | #if OPENSSL_WITH_ARGON2 | |
| 25 | 27 | #include <openssl/thread.h> | |
| 26 | 28 | #endif | |
@@ -76,6 +78,17 @@ using BignumCtxPointer = DeleteFnPtr<BN_CTX, BN_CTX_free>; | |||
| 76 | 78 | using BignumGenCallbackPointer = DeleteFnPtr<BN_GENCB, BN_GENCB_free>; | |
| 77 | 79 | using NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>; | |
| 78 | 80 | ||
| 81 | + #if NCRYPTO_USE_OPENSSL3_PROVIDER | ||
| 82 | + using X509PubKeyPointer = DeleteFnPtr<X509_PUBKEY, X509_PUBKEY_free>; | ||
| 83 | + // OSSL_STORE_close() returns int, so it needs a void-returning adapter to be | ||
| 84 | + // usable as a DeleteFnPtr deleter. | ||
| 85 | + void CloseStoreCtx(OSSL_STORE_CTX* ctx) { | ||
| 86 | + OSSL_STORE_close(ctx); | ||
| 87 | + } | ||
| 88 | + using StoreCtxPointer = DeleteFnPtr<OSSL_STORE_CTX, CloseStoreCtx>; | ||
| 89 | + using UIMethodPointer = DeleteFnPtr<UI_METHOD, UI_destroy_method>; | ||
| 90 | + #endif | ||
| 91 | + | ||
| 79 | 92 | const EVP_CIPHER* GetCipherCtxCipher(const EVP_CIPHER_CTX* ctx) { | |
| 80 | 93 | #if NCRYPTO_USE_OPENSSL3_PROVIDER | |
| 81 | 94 | return EVP_CIPHER_CTX_get0_cipher(ctx); | |
@@ -332,7 +345,7 @@ ClearErrorOnReturn::~ClearErrorOnReturn() { | |||
| 332 | 345 | ERR_clear_error(); | |
| 333 | 346 | } | |
| 334 | 347 | ||
| 335 | - int ClearErrorOnReturn::peekError() { | ||
| 348 | + unsigned long ClearErrorOnReturn::peekError() { // NOLINT(runtime/int) | ||
| 336 | 349 | return ERR_peek_error(); | |
| 337 | 350 | } | |
| 338 | 351 | ||
@@ -346,7 +359,7 @@ MarkPopErrorOnReturn::~MarkPopErrorOnReturn() { | |||
| 346 | 359 | ERR_pop_to_mark(); | |
| 347 | 360 | } | |
| 348 | 361 | ||
| 349 | - int MarkPopErrorOnReturn::peekError() { | ||
| 362 | + unsigned long MarkPopErrorOnReturn::peekError() { // NOLINT(runtime/int) | ||
| 350 | 363 | return ERR_peek_error(); | |
| 351 | 364 | } | |
| 352 | 365 | ||
@@ -840,6 +853,7 @@ int NoPasswordCallback(char* buf, int size, int rwflag, void* u) { | |||
| 840 | 853 | ||
| 841 | 854 | int PasswordCallback(char* buf, int size, int rwflag, void* u) { | |
| 842 | 855 | auto passphrase = static_cast<const Buffer<char>*>(u); | |
| 856 | + if (size <= 0) return -1; | ||
| 843 | 857 | if (passphrase != nullptr) { | |
| 844 | 858 | size_t buflen = static_cast<size_t>(size); | |
| 845 | 859 | size_t len = passphrase->len; | |
@@ -851,6 +865,31 @@ int PasswordCallback(char* buf, int size, int rwflag, void* u) { | |||
| 851 | 865 | return -1; | |
| 852 | 866 | } | |
| 853 | 867 | ||
| 868 | + #if NCRYPTO_USE_OPENSSL3_PROVIDER | ||
| 869 | + namespace { | ||
| 870 | + struct StorePassphraseData { | ||
| 871 | + Buffer<char> passphrase{.data = nullptr, .len = 0}; | ||
| 872 | + bool has_passphrase = false; | ||
| 873 | + bool missing_passphrase = false; | ||
| 874 | + }; | ||
| 875 | + | ||
| 876 | + int StorePasswordCallback(char* buf, int size, int rwflag, void* u) { | ||
| 877 | + auto data = static_cast<StorePassphraseData*>(u); | ||
| 878 | + if (data == nullptr || !data->has_passphrase) { | ||
| 879 | + if (data != nullptr) data->missing_passphrase = true; | ||
| 880 | + return -1; | ||
| 881 | + } | ||
| 882 | + | ||
| 883 | + if (size <= 0) return -1; | ||
| 884 | + size_t buflen = static_cast<size_t>(size); | ||
| 885 | + size_t len = data->passphrase.len; | ||
| 886 | + if (buflen < len) return -1; | ||
| 887 | + memcpy(buf, reinterpret_cast<const char*>(data->passphrase.data), len); | ||
| 888 | + return len; | ||
| 889 | + } | ||
| 890 | + } // namespace | ||
| 891 | + #endif | ||
| 892 | + | ||
| 854 | 893 | // Algorithm: http://howardhinnant.github.io/date_algorithms.html | |
| 855 | 894 | constexpr int days_from_epoch(int y, unsigned m, unsigned d) { | |
| 856 | 895 | y -= m <= 2; | |
@@ -3585,7 +3624,7 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePrivateKey( | |||
| 3585 | 3624 | const Buffer<const unsigned char>& buffer) { | |
| 3586 | 3625 | static constexpr auto keyOrError = [](EVPKeyPointer pkey, | |
| 3587 | 3626 | bool had_passphrase = false) { | |
| 3588 | - if (int err = ERR_peek_error()) { | ||
| 3627 | + if (unsigned long err = ERR_peek_error()) { // NOLINT(runtime/int) | ||
| 3589 | 3628 | if (ERR_GET_LIB(err) == ERR_LIB_PEM && | |
| 3590 | 3629 | ERR_GET_REASON(err) == PEM_R_BAD_PASSWORD_READ && !had_passphrase) { | |
| 3591 | 3630 | return ParseKeyResult(PKParseError::NEED_PASSPHRASE); | |
@@ -3645,6 +3684,99 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePrivateKey( | |||
| 3645 | 3684 | }; | |
| 3646 | 3685 | } | |
| 3647 | 3686 | ||
| 3687 | + EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryLoadPrivateKeyFromStore( | ||
| 3688 | + const StorePrivateKeyConfig& config) { | ||
| 3689 | + #if !NCRYPTO_USE_OPENSSL3_PROVIDER | ||
| 3690 | + return ParseKeyResult(PKParseError::FAILED); | ||
| 3691 | + #else | ||
| 3692 | + // The error queue is left populated on failure so the caller can surface a | ||
| 3693 | + // `code` and an `opensslErrorStack`, matching TryParsePrivateKey(), and is | ||
| 3694 | + // cleared on success because decoders leave entries behind either way. | ||
| 3695 | + std::string uri_str(config.uri); | ||
| 3696 | + std::string properties_str; | ||
| 3697 | + const char* properties = nullptr; | ||
| 3698 | + if (config.properties.has_value() && !config.properties->empty()) { | ||
| 3699 | + properties_str.assign(config.properties->data(), config.properties->size()); | ||
| 3700 | + properties = properties_str.c_str(); | ||
| 3701 | + } | ||
| 3702 | + | ||
| 3703 | + // config.passphrase outlives this call, so no copy is needed. | ||
| 3704 | + Buffer<char> passbuf{.data = nullptr, .len = 0}; | ||
| 3705 | + if (config.passphrase.has_value()) { | ||
| 3706 | + passbuf.data = const_cast<char*>(config.passphrase->data); | ||
| 3707 | + passbuf.len = config.passphrase->len; | ||
| 3708 | + } | ||
| 3709 | + StorePassphraseData passphrase_data{ | ||
| 3710 | + .passphrase = passbuf, | ||
| 3711 | + .has_passphrase = config.passphrase.has_value(), | ||
| 3712 | + }; | ||
| 3713 | + // Declared before ctx so that reverse destruction closes the store first; | ||
| 3714 | + // it holds both for its lifetime. | ||
| 3715 | + UIMethodPointer ui_method( | ||
| 3716 | + UI_UTIL_wrap_read_pem_callback(StorePasswordCallback, 0)); | ||
| 3717 | + if (!ui_method) return ParseKeyResult(PKParseError::FAILED); | ||
| 3718 | + | ||
| 3719 | + // Errors from loaders that declined the URI are retained oldest-first, so the | ||
| 3720 | + // newest entry is the loader that actually handled it. Must run before ctx is | ||
| 3721 | + // destroyed, since OSSL_STORE_close() can push errors of its own. | ||
| 3722 | + const auto failed = [&](bool missing_passphrase) { | ||
| 3723 | + if (missing_passphrase) | ||
| 3724 | + return ParseKeyResult(PKParseError::NEED_PASSPHRASE); | ||
| 3725 | + return ParseKeyResult(PKParseError::FAILED, ERR_peek_last_error()); | ||
| 3726 | + }; | ||
| 3727 | + | ||
| 3728 | + const OSSL_PARAM store_params[] = {OSSL_PARAM_END}; | ||
| 3729 | + StoreCtxPointer ctx(OSSL_STORE_open_ex(uri_str.c_str(), | ||
| 3730 | + nullptr, | ||
| 3731 | + properties, | ||
| 3732 | + ui_method.get(), | ||
| 3733 | + &passphrase_data, | ||
| 3734 | + store_params, | ||
| 3735 | + nullptr, | ||
| 3736 | + nullptr)); | ||
| 3737 | + if (!ctx) return failed(passphrase_data.missing_passphrase); | ||
| 3738 | + | ||
| 3739 | + if (!OSSL_STORE_expect(ctx.get(), OSSL_STORE_INFO_PKEY)) { | ||
| 3740 | + return failed(passphrase_data.missing_passphrase); | ||
| 3741 | + } | ||
| 3742 | + | ||
| 3743 | + EVPKeyPointer pkey; | ||
| 3744 | + bool store_error = false; | ||
| 3745 | + while (!OSSL_STORE_eof(ctx.get())) { | ||
| 3746 | + OSSL_STORE_INFO* info = OSSL_STORE_load(ctx.get()); | ||
| 3747 | + if (info == nullptr) { | ||
| 3748 | + if (OSSL_STORE_error(ctx.get())) { | ||
| 3749 | + store_error = true; | ||
| 3750 | + break; | ||
| 3751 | + } | ||
| 3752 | + continue; | ||
| 3753 | + } | ||
| 3754 | + if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) { | ||
| 3755 | + EVP_PKEY* raw_pkey = OSSL_STORE_INFO_get1_PKEY(info); | ||
| 3756 | + if (raw_pkey != nullptr) { | ||
| 3757 | + pkey = EVPKeyPointer(raw_pkey); | ||
| 3758 | + } else { | ||
| 3759 | + store_error = true; | ||
| 3760 | + } | ||
| 3761 | + } | ||
| 3762 | + OSSL_STORE_INFO_free(info); | ||
| 3763 | + if (pkey || store_error) break; | ||
| 3764 | + } | ||
| 3765 | + | ||
| 3766 | + // missing_passphrase is sticky, so a key that loaded anyway wins over it. | ||
| 3767 | + if (pkey) { | ||
| 3768 | + ctx.reset(); | ||
| 3769 | + ERR_clear_error(); | ||
| 3770 | + return ParseKeyResult(std::move(pkey)); | ||
| 3771 | + } | ||
| 3772 | + | ||
| 3773 | + if (passphrase_data.missing_passphrase || store_error) { | ||
| 3774 | + return failed(passphrase_data.missing_passphrase); | ||
| 3775 | + } | ||
| 3776 | + return ParseKeyResult(PKParseError::NOT_RECOGNIZED); | ||
| 3777 | + #endif | ||
| 3778 | + } | ||
| 3779 | + | ||
| 3648 | 3780 | Result<BIOPointer, bool> EVPKeyPointer::writePrivateKey( | |
| 3649 | 3781 | const PrivateKeyEncodingConfig& config) const { | |
| 3650 | 3782 | if (config.format == PKFormatType::JWK) { | |
@@ -3686,6 +3818,8 @@ Result<BIOPointer, bool> EVPKeyPointer::writePrivateKey( | |||
| 3686 | 3818 | #else | |
| 3687 | 3819 | RSA* rsa = EVP_PKEY_get0_RSA(get()); | |
| 3688 | 3820 | #endif | |
| 3821 | + if (rsa == nullptr) return Result<BIOPointer, bool>(false); | ||
| 3822 | + | ||
| 3689 | 3823 | switch (config.format) { | |
| 3690 | 3824 | case PKFormatType::PEM: { | |
| 3691 | 3825 | err = PEM_write_bio_RSAPrivateKey( | |
@@ -3761,6 +3895,8 @@ Result<BIOPointer, bool> EVPKeyPointer::writePrivateKey( | |||
| 3761 | 3895 | #else | |
| 3762 | 3896 | EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); | |
| 3763 | 3897 | #endif | |
| 3898 | + if (ec == nullptr) return Result<BIOPointer, bool>(false); | ||
| 3899 | + | ||
| 3764 | 3900 | switch (config.format) { | |
| 3765 | 3901 | case PKFormatType::PEM: { | |
| 3766 | 3902 | err = PEM_write_bio_ECPrivateKey( | |
@@ -3827,6 +3963,8 @@ Result<BIOPointer, bool> EVPKeyPointer::writePublicKey( | |||
| 3827 | 3963 | #else | |
| 3828 | 3964 | RSA* rsa = EVP_PKEY_get0_RSA(get()); | |
| 3829 | 3965 | #endif | |
| 3966 | + if (rsa == nullptr) return Result<BIOPointer, bool>(false); | ||
| 3967 | + | ||
| 3830 | 3968 | if (config.format == ncrypto::EVPKeyPointer::PKFormatType::PEM) { | |
| 3831 | 3969 | // Encode PKCS#1 as PEM. | |
| 3832 | 3970 | if (PEM_write_bio_RSAPublicKey(bio.get(), rsa) != 1) { | |
@@ -3855,10 +3993,28 @@ Result<BIOPointer, bool> EVPKeyPointer::writePublicKey( | |||
| 3855 | 3993 | ||
| 3856 | 3994 | if (config.format == ncrypto::EVPKeyPointer::PKFormatType::PEM) { | |
| 3857 | 3995 | // Encode SPKI as PEM. | |
| 3996 | + #if NCRYPTO_USE_OPENSSL3_PROVIDER | ||
| 3997 | + // Build the SubjectPublicKeyInfo wrapper explicitly before PEM encoding. | ||
| 3998 | + // Provider-backed keys can fail the direct PEM_write_bio_PUBKEY() path even | ||
| 3999 | + // when OpenSSL can materialize the public wrapper with X509_PUBKEY_set(). | ||
| 4000 | + X509_PUBKEY* pubkey = nullptr; | ||
| 4001 | + if (X509_PUBKEY_set(&pubkey, get()) != 1) { | ||
| 4002 | + X509_PUBKEY_free(pubkey); | ||
| 4003 | + return Result<BIOPointer, bool>(false, | ||
| 4004 | + mark_pop_error_on_return.peekError()); | ||
| 4005 | + } | ||
| 4006 | + X509PubKeyPointer pubkey_ptr(pubkey); | ||
| 4007 | + if (PEM_write_bio_X509_PUBKEY(bio.get(), pubkey_ptr.get()) != 1) { | ||
| 4008 | + return Result<BIOPointer, bool>(false, | ||
| 4009 | + mark_pop_error_on_return.peekError()); | ||
| 4010 | + } | ||
| 4011 | + #else | ||
| 4012 | + // Non-OpenSSL >= 3 builds do not all declare PEM_write_bio_X509_PUBKEY(). | ||
| 3858 | 4013 | if (PEM_write_bio_PUBKEY(bio.get(), get()) != 1) { | |
| 3859 | 4014 | return Result<BIOPointer, bool>(false, | |
| 3860 | 4015 | mark_pop_error_on_return.peekError()); | |
| 3861 | 4016 | } | |
| 4017 | + #endif | ||
| 3862 | 4018 | return bio; | |
| 3863 | 4019 | } | |
| 3864 | 4020 | ||
@@ -3929,21 +4085,37 @@ std::optional<uint32_t> EVPKeyPointer::getBytesOfRS() const { | |||
| 3929 | 4085 | bits = BignumPointer::GetBitCount(q.get()); | |
| 3930 | 4086 | #else | |
| 3931 | 4087 | const DSA* dsa_key = EVP_PKEY_get0_DSA(get()); | |
| 4088 | + bool has_bits = false; | ||
| 3932 | 4089 | // Both r and s are computed mod q, so their width is limited by that of q. | |
| 3933 | - bits = BignumPointer::GetBitCount(DSA_get0_q(dsa_key)); | ||
| 4090 | + if (dsa_key != nullptr) { | ||
| 4091 | + const BIGNUM* q = DSA_get0_q(dsa_key); | ||
| 4092 | + if (q != nullptr) { | ||
| 4093 | + bits = BignumPointer::GetBitCount(q); | ||
| 4094 | + has_bits = true; | ||
| 4095 | + } | ||
| 4096 | + } | ||
| 4097 | + if (!has_bits) return std::nullopt; | ||
| 3934 | 4098 | #endif | |
| 3935 | 4099 | } else if (id == EVP_PKEY_EC) { | |
| 3936 | 4100 | #if NCRYPTO_USE_OPENSSL3_PROVIDER | |
| 3937 | 4101 | Ec ec(get()); | |
| 3938 | 4102 | if (!ec) return std::nullopt; | |
| 3939 | - bits = EC_GROUP_order_bits(ec.getGroup()); | ||
| 4103 | + const EC_GROUP* group = ec.getGroup(); | ||
| 4104 | + if (group == nullptr) return std::nullopt; | ||
| 4105 | + bits = EC_GROUP_order_bits(group); | ||
| 3940 | 4106 | #else | |
| 3941 | - bits = EC_GROUP_order_bits(ECKeyPointer::GetGroup(*this)); | ||
| 4107 | + const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(get()); | ||
| 4108 | + if (ec_key == nullptr) return std::nullopt; | ||
| 4109 | + const EC_GROUP* group = ECKeyPointer::GetGroup(ec_key); | ||
| 4110 | + if (group == nullptr) return std::nullopt; | ||
| 4111 | + bits = EC_GROUP_order_bits(group); | ||
| 3942 | 4112 | #endif | |
| 3943 | 4113 | } else { | |
| 3944 | 4114 | return std::nullopt; | |
| 3945 | 4115 | } | |
| 3946 | 4116 | ||
| 4117 | + if (bits <= 0) return std::nullopt; | ||
| 4118 | + | ||
| 3947 | 4119 | return (bits + 7) / 8; | |
| 3948 | 4120 | } | |
| 3949 | 4121 | ||
@@ -3982,12 +4154,12 @@ EVPKeyPointer::operator Dsa() const { | |||
| 3982 | 4154 | ||
| 3983 | 4155 | bool EVPKeyPointer::validateDsaParameters() const { | |
| 3984 | 4156 | if (!pkey_) return false; | |
| 3985 | - /* Validate DSA2 parameters from FIPS 186-4 */ | ||
| 3986 | 4157 | #if OPENSSL_VERSION_MAJOR >= 3 | |
| 3987 | 4158 | if (EVP_default_properties_is_fips_enabled(nullptr) && EVP_PKEY_DSA == id()) { | |
| 3988 | 4159 | #else | |
| 3989 | 4160 | if (FIPS_mode() && EVP_PKEY_DSA == id()) { | |
| 3990 | 4161 | #endif | |
| 4162 | + // Validate DSA2 parameters from FIPS 186-4. | ||
| 3991 | 4163 | #if NCRYPTO_USE_OPENSSL3_PROVIDER | |
| 3992 | 4164 | DeleteFnPtr<BIGNUM, BN_free> p; | |
| 3993 | 4165 | DeleteFnPtr<BIGNUM, BN_free> q; | |
@@ -3999,9 +4171,11 @@ bool EVPKeyPointer::validateDsaParameters() const { | |||
| 3999 | 4171 | const BIGNUM* q_value = q.get(); | |
| 4000 | 4172 | #else | |
| 4001 | 4173 | const DSA* dsa = EVP_PKEY_get0_DSA(pkey_.get()); | |
| 4174 | + if (dsa == nullptr) return false; | ||
| 4002 | 4175 | const BIGNUM* p; | |
| 4003 | 4176 | const BIGNUM* q; | |
| 4004 | 4177 | DSA_get0_pqg(dsa, &p, &q, nullptr); | |
| 4178 | + if (p == nullptr || q == nullptr) return false; | ||
| 4005 | 4179 | const BIGNUM* p_value = p; | |
| 4006 | 4180 | const BIGNUM* q_value = q; | |
| 4007 | 4181 | #endif | |
@@ -6452,9 +6626,14 @@ DataPointer EVPMDCtxPointer::sign( | |||
| 6452 | 6626 | ||
| 6453 | 6627 | bool EVPMDCtxPointer::verify(const Buffer<const unsigned char>& buf, | |
| 6454 | 6628 | const Buffer<const unsigned char>& sig) const { | |
| 6455 | - if (!ctx_) return false; | ||
| 6456 | - int ret = EVP_DigestVerify(ctx_.get(), sig.data, sig.len, buf.data, buf.len); | ||
| 6457 | - return ret == 1; | ||
| 6629 | + return verifyOneShot(buf, sig) == 1; | ||
| 6630 | + } | ||
| 6631 | + | ||
| 6632 | + int EVPMDCtxPointer::verifyOneShot( | ||
| 6633 | + const Buffer<const unsigned char>& buf, | ||
| 6634 | + const Buffer<const unsigned char>& sig) const { | ||
| 6635 | + if (!ctx_) return -1; | ||
| 6636 | + return EVP_DigestVerify(ctx_.get(), sig.data, sig.len, buf.data, buf.len); | ||
| 6458 | 6637 | } | |
| 6459 | 6638 | ||
| 6460 | 6639 | EVPMDCtxPointer EVPMDCtxPointer::New() { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments