From fa06199322723eb4852e5a5a787714fae43e9cc6 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Sun, 15 Jan 2023 16:46:18 -0500 Subject: [PATCH] New approach for discrete logarithm keys Removes the DL_Scheme_PublicKey and DL_Scheme_PrivateKey classes, replaced by inner members --- doc/migration_guide.rst | 20 ++ src/lib/ffi/ffi_pkey_algs.cpp | 17 +- src/lib/pubkey/dh/dh.cpp | 148 +++++++------ src/lib/pubkey/dh/dh.h | 97 ++++++--- src/lib/pubkey/dl_algo/dl_algo.cpp | 109 ---------- src/lib/pubkey/dl_algo/dl_algo.h | 144 ------------- src/lib/pubkey/dl_algo/dl_scheme.cpp | 163 ++++++++++++++ src/lib/pubkey/dl_algo/dl_scheme.h | 95 +++++++++ src/lib/pubkey/dl_algo/info.txt | 10 +- src/lib/pubkey/dl_group/dl_group.cpp | 24 +++ src/lib/pubkey/dl_group/dl_group.h | 22 ++ src/lib/pubkey/dsa/dsa.cpp | 192 ++++++++++------- src/lib/pubkey/dsa/dsa.h | 75 +++++-- src/lib/pubkey/elgamal/elgamal.cpp | 200 ++++++++++-------- src/lib/pubkey/elgamal/elgamal.h | 73 +++++-- src/lib/pubkey/pk_algs.cpp | 3 + src/lib/tls/tls12/msg_server_kex.cpp | 6 +- .../tls/tls13/tls_extensions_key_share.cpp | 1 + src/lib/tls/tls_callbacks.cpp | 1 + src/tests/test_dh.cpp | 26 +-- src/tests/test_dlies.cpp | 5 +- src/tests/test_dsa.cpp | 12 +- src/tests/test_elgamal.cpp | 9 +- src/tests/unit_tls_policy.cpp | 3 +- 24 files changed, 864 insertions(+), 591 deletions(-) delete mode 100644 src/lib/pubkey/dl_algo/dl_algo.cpp delete mode 100644 src/lib/pubkey/dl_algo/dl_algo.h create mode 100644 src/lib/pubkey/dl_algo/dl_scheme.cpp create mode 100644 src/lib/pubkey/dl_algo/dl_scheme.h diff --git a/doc/migration_guide.rst b/doc/migration_guide.rst index e7dce89523f..7ba07c68e73 100644 --- a/doc/migration_guide.rst +++ b/doc/migration_guide.rst @@ -352,3 +352,23 @@ desired hash is not compatible with the algorithm. In previous versions, various APIs required that the application specify the hash function to be used. In most cases this can now be omitted (passing an empty string) and a suitable default will be chosen. + +Discrete Logarithm Key Changes +-------------------------------- + +Keys based on the discrete logarithm problem no longer derive from the +DL_Scheme_PrivateKey and DL_Scheme_PublicKey classes; these classes +have been removed. + +Functions to access DL algorithm interal fields (such as the integer value of +the private key using ``get_x``) have been removed. If you need access to this +information you can use the new ``get_int_field`` function. + +The constructors of the DL scheme private keys have changed. Previously, loading +and creating a key used the same constructor, namely one taking arguments +``(DL_Group, RandomNumberGenerator&, BigInt x = 0)`` and then the behavior of +the constructor depend on if ``x`` was zero (in which case a new key was +created) or otherwise if ``x`` was non-zero then it was taken as the private +key. Now there are two constructors, one taking a random number generator and a +group, which generates a new key, and a second taking a group and an integer, +which loads an existing key. diff --git a/src/lib/ffi/ffi_pkey_algs.cpp b/src/lib/ffi/ffi_pkey_algs.cpp index 2f3426bd102..aa411ddfea6 100644 --- a/src/lib/ffi/ffi_pkey_algs.cpp +++ b/src/lib/ffi/ffi_pkey_algs.cpp @@ -14,12 +14,12 @@ #include #include -#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) - #include +#if defined(BOTAN_HAS_DL_GROUP) + #include #endif -#if defined(BOTAN_HAS_DL_PUBLIC_KEY_FAMILY) - #include +#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) + #include #endif #if defined(BOTAN_HAS_RSA) @@ -346,9 +346,8 @@ int botan_privkey_load_dsa(botan_privkey_t* key, *key = nullptr; return ffi_guard_thunk(__func__, [=]() -> int { - Botan::Null_RNG null_rng; Botan::DL_Group group(safe_get(p), safe_get(q), safe_get(g)); - auto dsa = std::make_unique(null_rng, group, safe_get(x)); + auto dsa = std::make_unique(group, safe_get(x)); *key = new botan_privkey_struct(std::move(dsa)); return BOTAN_FFI_SUCCESS; }); @@ -502,9 +501,8 @@ int botan_privkey_load_elgamal(botan_privkey_t* key, #if defined(BOTAN_HAS_ELGAMAL) *key = nullptr; return ffi_guard_thunk(__func__, [=]() -> int { - Botan::Null_RNG null_rng; Botan::DL_Group group(safe_get(p), safe_get(g)); - auto elg = std::make_unique(null_rng, group, safe_get(x)); + auto elg = std::make_unique(group, safe_get(x)); *key = new botan_privkey_struct(std::move(elg)); return BOTAN_FFI_SUCCESS; }); @@ -527,9 +525,8 @@ int botan_privkey_load_dh(botan_privkey_t* key, #if defined(BOTAN_HAS_DIFFIE_HELLMAN) *key = nullptr; return ffi_guard_thunk(__func__, [=]() -> int { - Botan::Null_RNG null_rng; Botan::DL_Group group(safe_get(p), safe_get(g)); - auto dh = std::make_unique(null_rng, group, safe_get(x)); + auto dh = std::make_unique(group, safe_get(x)); *key = new botan_privkey_struct(std::move(dh)); return BOTAN_FFI_SUCCESS; }); diff --git a/src/lib/pubkey/dh/dh.cpp b/src/lib/pubkey/dh/dh.cpp index 5d6901a0803..964f2dd2b22 100644 --- a/src/lib/pubkey/dh/dh.cpp +++ b/src/lib/pubkey/dh/dh.cpp @@ -1,84 +1,106 @@ /* * Diffie-Hellman -* (C) 1999-2007,2016,2019 Jack Lloyd +* (C) 1999-2007,2016,2019,2023 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include +#include #include -#include #include namespace Botan { -/* -* DH_PublicKey Constructor -*/ -DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1) +DH_PublicKey::DH_PublicKey(const AlgorithmIdentifier& alg_id, + const std::vector& key_bits) { - m_group = grp; - m_y = y1; + m_public_key = std::make_shared(alg_id, key_bits, DL_Group_Format::ANSI_X9_42); + } + +DH_PublicKey::DH_PublicKey(const DL_Group& group, const BigInt& y) + { + m_public_key = std::make_shared(group, y); } -/* -* Return the public value for key agreement -*/ std::vector DH_PublicKey::public_value() const { - return unlock(BigInt::encode_1363(m_y, group_p().bytes())); + return m_public_key->public_key_as_bytes(); } -/* -* Create a DH private key -*/ -DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, - const DL_Group& grp, - const BigInt& x_arg) +size_t DH_PublicKey::estimated_strength() const + { + return m_public_key->estimated_strength(); + } + +size_t DH_PublicKey::key_length() const { - m_group = grp; + return m_public_key->p_bits(); + } - if(x_arg == 0) - { - const size_t exp_bits = grp.exponent_bits(); - m_x.randomize(rng, exp_bits); - m_y = m_group.power_g_p(m_x, exp_bits); - } - else - { - m_x = x_arg; +const BigInt& DH_PublicKey::get_int_field(const std::string& field) const + { + return m_public_key->get_int_field(algo_name(), field); + } - if(m_y == 0) - m_y = m_group.power_g_p(m_x, grp.p_bits()); - } +AlgorithmIdentifier DH_PublicKey::algorithm_identifier() const + { + return AlgorithmIdentifier( + object_identifier(), + m_public_key->group().DER_encode(DL_Group_Format::ANSI_X9_42)); + } + +std::vector DH_PublicKey::public_key_bits() const + { + return m_public_key->DER_encode(); + } + +bool DH_PublicKey::check_key(RandomNumberGenerator& rng, bool strong) const + { + return m_public_key->check_key(rng, strong); + } + +DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, + const DL_Group& group) + { + m_private_key = std::make_shared(group, rng); + m_public_key = m_private_key->public_key(); + } + +DH_PrivateKey::DH_PrivateKey(const DL_Group& group, + const BigInt& x) + { + m_private_key = std::make_shared(group, x); + m_public_key = m_private_key->public_key(); } -/* -* Load a DH private key -*/ DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id, - const secure_vector& key_bits) : - DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group_Format::ANSI_X9_42) + const secure_vector& key_bits) { - if(m_y.is_zero()) - { - m_y = m_group.power_g_p(m_x, m_group.p_bits()); - } + m_private_key = std::make_shared(alg_id, key_bits, DL_Group_Format::ANSI_X9_42); + m_public_key = m_private_key->public_key(); } std::unique_ptr DH_PrivateKey::public_key() const { - return std::make_unique(get_group(), get_y()); + return std::unique_ptr(new DH_PublicKey(m_public_key)); } -/* -* Return the public value for key agreement -*/ std::vector DH_PrivateKey::public_value() const { return DH_PublicKey::public_value(); } +secure_vector DH_PrivateKey::private_key_bits() const + { + return m_private_key->DER_encode(); + } + +const BigInt& DH_PrivateKey::get_int_field(const std::string& field) const + { + return m_private_key->get_int_field(algo_name(), field); + } + namespace { /** @@ -88,32 +110,36 @@ class DH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF { public: - DH_KA_Operation(const DH_PrivateKey& key, const std::string& kdf, RandomNumberGenerator& rng) : + DH_KA_Operation(std::shared_ptr key, + const std::string& kdf, + RandomNumberGenerator& rng) : PK_Ops::Key_Agreement_with_KDF(kdf), - m_p(key.group_p()), - m_x(key.get_x()), - m_x_bits(m_x.bits()), - m_monty_p(key.get_group().monty_params_p()), - m_blinder(m_p, + m_key(key), + m_blinder(key->group().get_p(), rng, [](const BigInt& k) { return k; }, - [this](const BigInt& k) { return powermod_x_p(inverse_mod(k, m_p)); }) + [this](const BigInt& k) + { + const BigInt inv_k = inverse_mod(k, group().get_p()); + return powermod_x_p(inv_k); + }) {} - size_t agreed_value_size() const override { return m_p.bytes(); } + size_t agreed_value_size() const override { return group().p_bytes(); } secure_vector raw_agree(const uint8_t w[], size_t w_len) override; private: + const DL_Group& group() const + { + return m_key->group(); + } + BigInt powermod_x_p(const BigInt& v) const { - const size_t powm_window = 4; - auto powm_v_p = monty_precompute(m_monty_p, v, powm_window); - return monty_execute(*powm_v_p, m_x, m_x_bits); + return group().power_b_p(v, m_key->private_key()); } - const BigInt& m_p; - const BigInt& m_x; - const size_t m_x_bits; + std::shared_ptr m_key; std::shared_ptr m_monty_p; Blinder m_blinder; }; @@ -122,14 +148,14 @@ secure_vector DH_KA_Operation::raw_agree(const uint8_t w[], size_t w_le { BigInt v = BigInt::decode(w, w_len); - if(v <= 1 || v >= m_p - 1) + if(v <= 1 || v >= group().get_p()) throw Invalid_Argument("DH agreement - invalid key provided"); v = m_blinder.blind(v); v = powermod_x_p(v); v = m_blinder.unblind(v); - return BigInt::encode_1363(v, m_p.bytes()); + return BigInt::encode_1363(v, group().p_bytes()); } } @@ -140,7 +166,7 @@ DH_PrivateKey::create_key_agreement_op(RandomNumberGenerator& rng, const std::string& provider) const { if(provider == "base" || provider.empty()) - return std::make_unique(*this, params, rng); + return std::make_unique(this->m_private_key, params, rng); throw Provider_Not_Found(algo_name(), provider); } diff --git a/src/lib/pubkey/dh/dh.h b/src/lib/pubkey/dh/dh.h index b2be40ab1e9..bf2f5ae893f 100644 --- a/src/lib/pubkey/dh/dh.h +++ b/src/lib/pubkey/dh/dh.h @@ -1,6 +1,6 @@ /* * Diffie-Hellman -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2007,2023 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -8,58 +8,77 @@ #ifndef BOTAN_DIFFIE_HELLMAN_H_ #define BOTAN_DIFFIE_HELLMAN_H_ -#include +#include +#include namespace Botan { +class BigInt; +class DL_Group; +class DL_PublicKey; +class DL_PrivateKey; + /** * This class represents Diffie-Hellman public keys. */ -class BOTAN_PUBLIC_API(2,0) DH_PublicKey : public virtual DL_Scheme_PublicKey +class BOTAN_PUBLIC_API(2,0) DH_PublicKey : public virtual Public_Key { public: - std::string algo_name() const override { return "DH"; } - - std::vector public_value() const; - - DL_Group_Format group_format() const override { return DL_Group_Format::ANSI_X9_42; } - - bool supports_operation(PublicKeyOperation op) const override - { - return (op == PublicKeyOperation::KeyAgreement); - } - /** * Create a public key. * @param alg_id the X.509 algorithm identifier * @param key_bits DER encoded public key bits */ DH_PublicKey(const AlgorithmIdentifier& alg_id, - const std::vector& key_bits) : - DL_Scheme_PublicKey(alg_id, key_bits, DL_Group_Format::ANSI_X9_42) {} + const std::vector& key_bits); /** * Construct a public key with the specified parameters. - * @param grp the DL group to use in the key + * @param group the DL group to use in the key * @param y the public value y */ - DH_PublicKey(const DL_Group& grp, const BigInt& y); - protected: + DH_PublicKey(const DL_Group& group, const BigInt& y); + + AlgorithmIdentifier algorithm_identifier() const override; + std::vector public_key_bits() const override; + + bool check_key(RandomNumberGenerator& rng, bool strong) const override; + + size_t estimated_strength() const override; + size_t key_length() const override; + + std::vector public_value() const; + + std::string algo_name() const override { return "DH"; } + + const BigInt& get_int_field(const std::string& field) const override; + + bool supports_operation(PublicKeyOperation op) const override + { + return (op == PublicKeyOperation::KeyAgreement); + } + private: + friend class DH_PrivateKey; + DH_PublicKey() = default; + + DH_PublicKey(std::shared_ptr key) : + m_public_key(key) {} + + std::shared_ptr m_public_key; }; /** * This class represents Diffie-Hellman private keys. */ -class BOTAN_PUBLIC_API(2,0) DH_PrivateKey final : public DH_PublicKey, - public PK_Key_Agreement_Key, - public virtual DL_Scheme_PrivateKey +class BOTAN_PUBLIC_API(2,0) DH_PrivateKey final : + public DH_PublicKey, + public PK_Key_Agreement_Key, + public virtual Private_Key { public: - std::vector public_value() const override; - /** - * Load a private key. + * Load a private key from the ASN.1 encoding * @param alg_id the X.509 algorithm identifier * @param key_bits PKCS #8 structure */ @@ -67,20 +86,36 @@ class BOTAN_PUBLIC_API(2,0) DH_PrivateKey final : public DH_PublicKey, const secure_vector& key_bits); /** - * Create a private key. - * @param rng random number generator to use - * @param grp the group to be used in the key - * @param x the key's secret value (or if zero, generate a new key) + * Load a private key from the integer encoding + * @param group the underlying DL group + * @param private_key the private key */ - DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& grp, - const BigInt& x = BigInt::zero()); + DH_PrivateKey(const DL_Group& group, + const BigInt& private_key); + + /** + * Create a new private key. + * @param group the underlying DL group + * @param rng the RNG to use + */ + DH_PrivateKey(RandomNumberGenerator& rng, + const DL_Group& group); std::unique_ptr public_key() const override; + std::vector public_value() const override; + + secure_vector private_key_bits() const override; + + const BigInt& get_int_field(const std::string& field) const override; + std::unique_ptr create_key_agreement_op(RandomNumberGenerator& rng, const std::string& params, const std::string& provider) const override; + + private: + std::shared_ptr m_private_key; }; } diff --git a/src/lib/pubkey/dl_algo/dl_algo.cpp b/src/lib/pubkey/dl_algo/dl_algo.cpp deleted file mode 100644 index 41b0f169a83..00000000000 --- a/src/lib/pubkey/dl_algo/dl_algo.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* -* DL Scheme -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include -#include -#include - -namespace Botan { - -size_t DL_Scheme_PublicKey::key_length() const - { - return m_group.p_bits(); - } - -size_t DL_Scheme_PublicKey::estimated_strength() const - { - return m_group.estimated_strength(); - } - -AlgorithmIdentifier DL_Scheme_PublicKey::algorithm_identifier() const - { - return AlgorithmIdentifier(object_identifier(), - m_group.DER_encode(group_format())); - } - -std::vector DL_Scheme_PublicKey::public_key_bits() const - { - std::vector output; - DER_Encoder(output).encode(m_y); - return output; - } - -DL_Scheme_PublicKey::DL_Scheme_PublicKey(const DL_Group& group, const BigInt& y) : - m_y(y), - m_group(group) - { - } - -DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, - const std::vector& key_bits, - DL_Group_Format format) : - m_group(alg_id.parameters(), format) - { - BER_Decoder(key_bits).decode(m_y); - } - -secure_vector DL_Scheme_PrivateKey::private_key_bits() const - { - return DER_Encoder().encode(m_x).get_contents(); - } - -DL_Scheme_PrivateKey::DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id, - const secure_vector& key_bits, - DL_Group_Format format) - { - m_group.BER_decode(alg_id.parameters(), format); - - BER_Decoder(key_bits).decode(m_x); - } - -/* -* Check Public DL Parameters -*/ -bool DL_Scheme_PublicKey::check_key(RandomNumberGenerator& rng, - bool strong) const - { - if(!m_group.verify_public_element(m_y)) - return false; - - return m_group.verify_group(rng, strong); - } - -/* -* Check DL Scheme Private Parameters -*/ -bool DL_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng, - bool strong) const - { - return m_group.verify_group(rng, strong) && m_group.verify_element_pair(m_y, m_x); - } - -const BigInt& DL_Scheme_PublicKey::get_int_field(const std::string& field) const - { - if(field == "p") - return this->group_p(); - else if(field == "q") - return this->group_q(); - else if(field == "g") - return this->group_g(); - else if(field == "y") - return this->get_y(); - else - return Public_Key::get_int_field(field); - } - -const BigInt& DL_Scheme_PrivateKey::get_int_field(const std::string& field) const - { - if(field == "x") - return this->get_x(); - else - return DL_Scheme_PublicKey::get_int_field(field); - } - -} diff --git a/src/lib/pubkey/dl_algo/dl_algo.h b/src/lib/pubkey/dl_algo/dl_algo.h deleted file mode 100644 index 9dd76a70aa2..00000000000 --- a/src/lib/pubkey/dl_algo/dl_algo.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -* DL Scheme -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_DL_ALGO_H_ -#define BOTAN_DL_ALGO_H_ - -#include -#include - -namespace Botan { - -/** -* This class represents discrete logarithm (DL) public keys. -*/ -class BOTAN_PUBLIC_API(2,0) DL_Scheme_PublicKey : public virtual Public_Key - { - public: - bool check_key(RandomNumberGenerator& rng, bool) const override; - - AlgorithmIdentifier algorithm_identifier() const override; - - std::vector public_key_bits() const override; - - /** - * Get the DL domain parameters of this key. - * @return DL domain parameters of this key - */ - const DL_Group& get_domain() const { return m_group; } - - /** - * Get the DL domain parameters of this key. - * @return DL domain parameters of this key - */ - const DL_Group& get_group() const { return m_group; } - - /** - * Get the public value y with y = g^x mod p where x is the secret key. - */ - const BigInt& get_y() const { return m_y; } - - /** - * Get the prime p of the underlying DL group. - * @return prime p - */ - const BigInt& group_p() const { return m_group.get_p(); } - - /** - * Get the prime q of the underlying DL group. - * @return prime q - */ - const BigInt& group_q() const { return m_group.get_q(); } - - /** - * Get the generator g of the underlying DL group. - * @return generator g - */ - const BigInt& group_g() const { return m_group.get_g(); } - - /** - * Get the underlying groups encoding format. - * @return encoding format - */ - virtual DL_Group_Format group_format() const = 0; - - size_t key_length() const override; - size_t estimated_strength() const override; - - const BigInt& get_int_field(const std::string& field) const override; - - DL_Scheme_PublicKey& operator=(const DL_Scheme_PublicKey& other) = default; - - protected: - DL_Scheme_PublicKey() = default; - - /** - * Create a public key. - * @param alg_id the X.509 algorithm identifier - * @param key_bits DER encoded public key bits - * @param group_format the underlying groups encoding format - */ - DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, - const std::vector& key_bits, - DL_Group_Format group_format); - - DL_Scheme_PublicKey(const DL_Group& group, const BigInt& y); - - /** - * The DL public key - */ - BigInt m_y; - - /** - * The DL group - */ - DL_Group m_group; - }; - -/** -* This class represents discrete logarithm (DL) private keys. -*/ -class BOTAN_PUBLIC_API(2,0) DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey, - public virtual Private_Key - { - public: - bool check_key(RandomNumberGenerator& rng, bool) const override; - - /** - * Get the secret key x. - * @return secret key - */ - const BigInt& get_x() const { return m_x; } - - secure_vector private_key_bits() const override; - - DL_Scheme_PrivateKey& operator=(const DL_Scheme_PrivateKey& other) = default; - - const BigInt& get_int_field(const std::string& field) const override; - - protected: - /** - * Create a private key. - * @param alg_id the X.509 algorithm identifier - * @param key_bits DER encoded private key bits - * @param group_format the underlying groups encoding format - */ - DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id, - const secure_vector& key_bits, - DL_Group_Format group_format); - - DL_Scheme_PrivateKey() = default; - - /** - * The DL private key - */ - BigInt m_x; - }; - -} - -#endif diff --git a/src/lib/pubkey/dl_algo/dl_scheme.cpp b/src/lib/pubkey/dl_algo/dl_scheme.cpp new file mode 100644 index 00000000000..afd4881e45a --- /dev/null +++ b/src/lib/pubkey/dl_algo/dl_scheme.cpp @@ -0,0 +1,163 @@ +/* +* (C) 2023 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include +#include +#include + +namespace Botan { + +namespace { + +template +BigInt decode_single_bigint(const std::vector& key_bits) + { + BigInt x; + BER_Decoder(key_bits).decode(x); + return x; + } + +BigInt generate_private_dl_key(const DL_Group& group, RandomNumberGenerator& rng) + { + if(group.has_q() && group.q_bits() >= 160 && group.q_bits() <= 384) + { + return BigInt::random_integer(rng, 2, group.get_q()); + } + else + { + return BigInt(rng, group.exponent_bits()); + } + } + +BigInt check_dl_private_key_input(const BigInt& x, const DL_Group& group) + { + BOTAN_ARG_CHECK(group.verify_private_element(x), + "Invalid discrete logarithm private key value"); + return x; + } + +} + +DL_PublicKey::DL_PublicKey(const DL_Group& group, + const BigInt& public_key) : + m_group(group), + m_public_key(public_key) + { + } + +DL_PublicKey::DL_PublicKey(const AlgorithmIdentifier& alg_id, + const std::vector& key_bits, + DL_Group_Format format) : + m_group(alg_id.parameters(), format), + m_public_key(decode_single_bigint(key_bits)) + { + } + +std::vector DL_PublicKey::public_key_as_bytes() const + { + std::vector bits(m_group.p_bytes()); + BigInt::encode_1363(bits.data(), bits.size(), m_public_key); + return bits; + } + +std::vector DL_PublicKey::DER_encode() const + { + std::vector output; + DER_Encoder(output).encode(m_public_key); + return output; + } + +bool DL_PublicKey::check_key(RandomNumberGenerator& rng, bool strong) const + { + return m_group.verify_group(rng, strong) && + m_group.verify_public_element(m_public_key); + } + +size_t DL_PublicKey::estimated_strength() const + { + return m_group.estimated_strength(); + } + +size_t DL_PublicKey::p_bits() const + { + return m_group.p_bits(); + } + +DL_PrivateKey::DL_PrivateKey(const DL_Group& group, + const BigInt& private_key) : + m_group(group), + m_private_key(check_dl_private_key_input(private_key, m_group)), + m_public_key(m_group.power_g_p(m_private_key, m_group.p_bits())) + { + } + +DL_PrivateKey::DL_PrivateKey(const DL_Group& group, + RandomNumberGenerator& rng) : + m_group(group), + m_private_key(generate_private_dl_key(group, rng)), + m_public_key(m_group.power_g_p(m_private_key, m_group.p_bits())) + { + } + +DL_PrivateKey::DL_PrivateKey(const AlgorithmIdentifier& alg_id, + const secure_vector& key_bits, + DL_Group_Format format) : + m_group(alg_id.parameters(), format), + m_private_key(check_dl_private_key_input(decode_single_bigint(key_bits), m_group)), + m_public_key(m_group.power_g_p(m_private_key, m_group.p_bits())) + { + } + +secure_vector DL_PrivateKey::DER_encode() const + { + return DER_Encoder().encode(m_private_key).get_contents(); + } + +bool DL_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const + { + return m_group.verify_group(rng, strong) && + m_group.verify_private_element(m_private_key); + } + +std::shared_ptr DL_PrivateKey::public_key() const + { + return std::make_shared(m_group, m_public_key); + } + +const BigInt& DL_PublicKey::get_int_field(const std::string& algo, + const std::string& field) const + { + if(field == "p") + return m_group.get_p(); + else if(field == "q") + return m_group.get_q(); + else if(field == "g") + return m_group.get_g(); + else if(field == "y") + return m_public_key; + else + throw Unknown_PK_Field_Name(algo, field); + } + +const BigInt& DL_PrivateKey::get_int_field(const std::string& algo, + const std::string& field) const + { + if(field == "p") + return m_group.get_p(); + else if(field == "q") + return m_group.get_q(); + else if(field == "g") + return m_group.get_g(); + else if(field == "x") + return m_private_key; + else if(field == "y") + return m_public_key; + else + throw Unknown_PK_Field_Name(algo, field); + } + +} diff --git a/src/lib/pubkey/dl_algo/dl_scheme.h b/src/lib/pubkey/dl_algo/dl_scheme.h new file mode 100644 index 00000000000..b3b4155369f --- /dev/null +++ b/src/lib/pubkey/dl_algo/dl_scheme.h @@ -0,0 +1,95 @@ +/* +* (C) 2023 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_DL_SCHEME_H_ +#define BOTAN_DL_SCHEME_H_ + +#include +#include +#include + +namespace Botan { + +class AlgorithmIdentifier; +class RandomNumberGenerator; + +class DL_PublicKey final + { + public: + DL_PublicKey(const DL_Group& group, + const BigInt& public_key); + + DL_PublicKey(const AlgorithmIdentifier& alg_id, + const std::vector& key_bits, + DL_Group_Format format); + + bool check_key(RandomNumberGenerator& rng, bool strong) const; + + const DL_Group& group() const { return m_group; } + const BigInt& public_key() const { return m_public_key; } + + // Return the binary representation of the integer public key + std::vector public_key_as_bytes() const; + + const BigInt& get_int_field(const std::string& algo_name, + const std::string& field) const; + + std::vector DER_encode() const; + + size_t estimated_strength() const; + + size_t p_bits() const; + private: + const DL_Group m_group; + const BigInt m_public_key; + }; + +class DL_PrivateKey final + { + public: + DL_PrivateKey(const DL_Group& group, + const BigInt& private_key); + + DL_PrivateKey(const DL_Group& group, + RandomNumberGenerator& rng); + + DL_PrivateKey(const AlgorithmIdentifier& alg_id, + const secure_vector& key_bits, + DL_Group_Format format); + + bool check_key(RandomNumberGenerator& rng, bool strong) const; + + /** + * Return a new shared_ptr of the associated public key + */ + std::shared_ptr public_key() const; + + /** + * Return the group this key operates in + */ + const DL_Group& group() const { return m_group; } + + /** + * Return the integer value of the private key + */ + const BigInt& private_key() const { return m_private_key; } + + /** + * DER encode the private key + */ + secure_vector DER_encode() const; + + const BigInt& get_int_field(const std::string& algo_name, + const std::string& field) const; + private: + const DL_Group m_group; + const BigInt m_private_key; + const BigInt m_public_key; + }; + +} + +#endif diff --git a/src/lib/pubkey/dl_algo/info.txt b/src/lib/pubkey/dl_algo/info.txt index 1d946e8a7b9..819a19f1bb9 100644 --- a/src/lib/pubkey/dl_algo/info.txt +++ b/src/lib/pubkey/dl_algo/info.txt @@ -1,10 +1,10 @@ -DL_PUBLIC_KEY_FAMILY -> 20131128 +DL_SCHEME -> 20230101 name -> "Discrete Logarithm" -brief -> "Base classes for discrete logarithm based schemes" +brief -> "Classes for discrete logarithm based schemes" @@ -14,6 +14,6 @@ numbertheory rng - -dl_algo.h - + +dl_scheme.h + diff --git a/src/lib/pubkey/dl_group/dl_group.cpp b/src/lib/pubkey/dl_group/dl_group.cpp index 38c4ebd59f4..15d251b9346 100644 --- a/src/lib/pubkey/dl_group/dl_group.cpp +++ b/src/lib/pubkey/dl_group/dl_group.cpp @@ -379,6 +379,20 @@ bool DL_Group::verify_public_element(const BigInt& y) const return true; } +bool DL_Group::verify_private_element(const BigInt& x) const + { + const BigInt& p = get_p(); + const BigInt& q = get_q(); + + if(x <= 1 || x >= p) + return false; + + if(q > 0 && x > q) + return false; + + return true; + } + bool DL_Group::verify_element_pair(const BigInt& y, const BigInt& x) const { const BigInt& p = get_p(); @@ -484,6 +498,11 @@ std::shared_ptr DL_Group::monty_params_p() const return data().monty_params_p(); } +bool DL_Group::has_q() const + { + return data().q_is_set(); + } + size_t DL_Group::p_bits() const { return data().p_bits(); @@ -578,6 +597,11 @@ BigInt DL_Group::power_g_p(const BigInt& x, size_t max_x_bits) const return data().power_g_p(x, max_x_bits); } +BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x) const + { + return this->power_b_p(b, x, data().p_bits()); + } + BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x, size_t max_x_bits) const { return data().power_b_p(b, x, max_x_bits); diff --git a/src/lib/pubkey/dl_group/dl_group.h b/src/lib/pubkey/dl_group/dl_group.h index b9355da6f5e..2eededa8e8f 100644 --- a/src/lib/pubkey/dl_group/dl_group.h +++ b/src/lib/pubkey/dl_group/dl_group.h @@ -160,6 +160,14 @@ class BOTAN_PUBLIC_API(2,0) DL_Group final */ bool verify_public_element(const BigInt& y) const; + /** + * Verify a private element + * + * Specifically this checks that x is > 1 and < p, and additionally if + * q is set then x must be < q + */ + bool verify_private_element(const BigInt& x) const; + /** * Verify a pair of elements y = g^x * @@ -262,6 +270,15 @@ class BOTAN_PUBLIC_API(2,0) DL_Group final */ BigInt power_b_p(const BigInt& b, const BigInt& x, size_t max_x_bits) const; + /** + * Modular exponentiation + * @param b the base + * @param x the exponent + * + * @return (b^x) % p + */ + BigInt power_b_p(const BigInt& b, const BigInt& x) const; + /** * Multi-exponentiate * Return (g^x * y^z) % p @@ -299,6 +316,11 @@ class BOTAN_PUBLIC_API(2,0) DL_Group final */ size_t q_bytes() const; + /** + * Return if the q value is set + */ + bool has_q() const; + /** * Return size in bits of a secret exponent * diff --git a/src/lib/pubkey/dsa/dsa.cpp b/src/lib/pubkey/dsa/dsa.cpp index 6af71f21d6b..9629b3e862c 100644 --- a/src/lib/pubkey/dsa/dsa.cpp +++ b/src/lib/pubkey/dsa/dsa.cpp @@ -1,6 +1,6 @@ /* * DSA -* (C) 1999-2010,2014,2016 Jack Lloyd +* (C) 1999-2010,2014,2016,2023 Jack Lloyd * (C) 2016 René Korthaus * * Botan is released under the Simplified BSD License (see license.txt) @@ -8,10 +8,10 @@ #include #include -#include -#include -#include +#include #include +#include +#include #if defined(BOTAN_HAS_RFC6979_GENERATOR) #include @@ -19,73 +19,106 @@ namespace Botan { -/* -* DSA_PublicKey Constructor -*/ +size_t DSA_PublicKey::message_part_size() const + { + return m_public_key->group().q_bytes(); + } -DSA_PublicKey::DSA_PublicKey(const AlgorithmIdentifier& alg_id, - const std::vector& key_bits) : - DL_Scheme_PublicKey(alg_id, key_bits, DL_Group_Format::ANSI_X9_57) +size_t DSA_PublicKey::estimated_strength() const { - BOTAN_ARG_CHECK(group_q().bytes() > 0, "Q parameter must be set for DSA"); + return m_public_key->estimated_strength(); } +size_t DSA_PublicKey::key_length() const + { + return m_public_key->p_bits(); + } -DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1) +const BigInt& DSA_PublicKey::get_int_field(const std::string& field) const { - m_group = grp; - m_y = y1; + return m_public_key->get_int_field(algo_name(), field); + } - BOTAN_ARG_CHECK(grp.q_bytes() > 0, "Q parameter must be set for DSA"); +AlgorithmIdentifier DSA_PublicKey::algorithm_identifier() const + { + return AlgorithmIdentifier( + object_identifier(), + m_public_key->group().DER_encode(DL_Group_Format::ANSI_X9_57)); + } + +std::vector DSA_PublicKey::public_key_bits() const + { + return m_public_key->DER_encode(); + } + +bool DSA_PublicKey::check_key(RandomNumberGenerator& rng, bool strong) const + { + return m_public_key->check_key(rng, strong); + } + +DSA_PublicKey::DSA_PublicKey(const AlgorithmIdentifier& alg_id, + const std::vector& key_bits) + { + m_public_key = std::make_shared(alg_id, key_bits, DL_Group_Format::ANSI_X9_57); + + BOTAN_ARG_CHECK(m_public_key->group().has_q(), + "Q parameter must be set for DSA"); + } + +DSA_PublicKey::DSA_PublicKey(const DL_Group& group, const BigInt& y) + { + m_public_key = std::make_shared(group, y); + + BOTAN_ARG_CHECK(m_public_key->group().has_q(), + "Q parameter must be set for DSA"); } -/* -* Create a DSA private key -*/ DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng, - const DL_Group& grp, - const BigInt& x_arg) + const DL_Group& group) + { + m_private_key = std::make_shared(group, rng); + m_public_key = m_private_key->public_key(); + } + +DSA_PrivateKey::DSA_PrivateKey(const DL_Group& group, + const BigInt& x) { - m_group = grp; - BOTAN_ARG_CHECK(x_arg.is_positive(), "x must be positive"); - - if(x_arg == 0) - m_x = BigInt::random_integer(rng, 2, group_q()); - else - { - BOTAN_ARG_CHECK(m_x < m_group.get_q(), "x must not be larger than q"); - m_x = x_arg; - } - - m_y = m_group.power_g_p(m_x, m_group.q_bits()); + m_private_key = std::make_shared(group, x); + m_public_key = m_private_key->public_key(); } DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id, - const secure_vector& key_bits) : - DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group_Format::ANSI_X9_57) + const secure_vector& key_bits) { - BOTAN_ARG_CHECK(m_x > 0, "x must be greater than zero"); - BOTAN_ARG_CHECK(m_x < m_group.get_q(), "x must not be larger than q"); - m_y = m_group.power_g_p(m_x, m_group.q_bits()); + m_private_key = std::make_shared(alg_id, key_bits, DL_Group_Format::ANSI_X9_57); + m_public_key = m_private_key->public_key(); } -/* -* Check Private DSA Parameters -*/ bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const { - if(!DL_Scheme_PrivateKey::check_key(rng, strong) || m_x >= group_q()) + if(!m_private_key->check_key(rng, strong)) return false; - if(!strong) - return true; + if(m_private_key->private_key() >= m_private_key->group().get_q()) + return false; return KeyPair::signature_consistency_check(rng, *this, "SHA-256"); } +secure_vector DSA_PrivateKey::private_key_bits() const + { + return m_private_key->DER_encode(); + } + +const BigInt& DSA_PrivateKey::get_int_field(const std::string& field) const + { + return m_private_key->get_int_field(algo_name(), field); + } + std::unique_ptr DSA_PrivateKey::public_key() const { - return std::make_unique(get_group(), get_y()); + // can't use make_unique here due to private constructor + return std::unique_ptr(new DSA_PublicKey(m_public_key)); } namespace { @@ -96,26 +129,24 @@ namespace { class DSA_Signature_Operation final : public PK_Ops::Signature_with_Hash { public: - DSA_Signature_Operation(const DSA_PrivateKey& dsa, + DSA_Signature_Operation(std::shared_ptr key, const std::string& emsa, RandomNumberGenerator& rng) : PK_Ops::Signature_with_Hash(emsa), - m_group(dsa.get_group()), - m_x(dsa.get_x()) + m_key(key) { - m_b = BigInt::random_integer(rng, 2, dsa.group_q()); - m_b_inv = m_group.inverse_mod_q(m_b); + m_b = BigInt::random_integer(rng, 2, key->group().get_q()); + m_b_inv = m_key->group().inverse_mod_q(m_b); } - size_t signature_length() const override { return 2*m_group.q_bytes(); } + size_t signature_length() const override { return 2*m_key->group().q_bytes(); } secure_vector raw_sign(const uint8_t msg[], size_t msg_len, - RandomNumberGenerator& rng) override; + RandomNumberGenerator& rng) override; AlgorithmIdentifier algorithm_identifier() const override; private: - const DL_Group m_group; - const BigInt& m_x; + std::shared_ptr m_key; BigInt m_b, m_b_inv; }; @@ -130,21 +161,23 @@ secure_vector DSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, RandomNumberGenerator& rng) { - const BigInt& q = m_group.get_q(); + const DL_Group& group = m_key->group(); + const BigInt& q = group.get_q(); - BigInt m = BigInt::from_bytes_with_max_bits(msg, msg_len, m_group.q_bits()); + BigInt m = BigInt::from_bytes_with_max_bits(msg, msg_len, group.q_bits()); if(m >= q) m -= q; #if defined(BOTAN_HAS_RFC6979_GENERATOR) BOTAN_UNUSED(rng); - const BigInt k = generate_rfc6979_nonce(m_x, q, m, this->rfc6979_hash_function()); + const BigInt k = generate_rfc6979_nonce(m_key->private_key(), q, m, + this->rfc6979_hash_function()); #else const BigInt k = BigInt::random_integer(rng, 1, q); #endif - const BigInt k_inv = m_group.inverse_mod_q(k); + const BigInt k_inv = group.inverse_mod_q(k); /* * It may not be strictly necessary for the reduction (g^k mod p) mod q to be @@ -155,18 +188,18 @@ DSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, * However it only increases the cost of signatures by about 7-10%, and DSA is * only for legacy use anyway so we don't care about the performance so much. */ - const BigInt r = ct_modulo(m_group.power_g_p(k, m_group.q_bits()), m_group.get_q()); + const BigInt r = ct_modulo(group.power_g_p(k, group.q_bits()), group.get_q()); /* * Blind the input message and compute x*r+m as (x*r*b + m*b)/b */ - m_b = m_group.square_mod_q(m_b); - m_b_inv = m_group.square_mod_q(m_b_inv); + m_b = group.square_mod_q(m_b); + m_b_inv = group.square_mod_q(m_b_inv); - m = m_group.multiply_mod_q(m_b, m); - const BigInt xr = m_group.multiply_mod_q(m_b, m_x, r); + m = group.multiply_mod_q(m_b, m); + const BigInt xr = group.multiply_mod_q(m_b, m_key->private_key(), r); - const BigInt s = m_group.multiply_mod_q(m_b_inv, k_inv, m_group.mod_q(xr+m)); + const BigInt s = group.multiply_mod_q(m_b_inv, k_inv, group.mod_q(xr+m)); // With overwhelming probability, a bug rather than actual zero r/s if(r.is_zero() || s.is_zero()) @@ -181,33 +214,32 @@ DSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len, class DSA_Verification_Operation final : public PK_Ops::Verification_with_Hash { public: - DSA_Verification_Operation(const DSA_PublicKey& dsa, + DSA_Verification_Operation(std::shared_ptr key, const std::string& emsa) : PK_Ops::Verification_with_Hash(emsa), - m_group(dsa.get_group()), - m_y(dsa.get_y()) + m_key(key) { } - DSA_Verification_Operation(const DSA_PublicKey& dsa, + DSA_Verification_Operation(std::shared_ptr key, const AlgorithmIdentifier& alg_id) : PK_Ops::Verification_with_Hash(alg_id, "DSA"), - m_group(dsa.get_group()), - m_y(dsa.get_y()) + m_key(key) { } bool verify(const uint8_t msg[], size_t msg_len, const uint8_t sig[], size_t sig_len) override; private: - const DL_Group m_group; - const BigInt& m_y; + std::shared_ptr m_key; }; bool DSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len, const uint8_t sig[], size_t sig_len) { - const BigInt& q = m_group.get_q(); + const auto group = m_key->group(); + + const BigInt& q = group.get_q(); const size_t q_bytes = q.bytes(); if(sig_len != 2*q_bytes) @@ -215,7 +247,7 @@ bool DSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len, BigInt r(sig, q_bytes); BigInt s(sig + q_bytes, q_bytes); - BigInt i = BigInt::from_bytes_with_max_bits(msg, msg_len, m_group.q_bits()); + BigInt i = BigInt::from_bytes_with_max_bits(msg, msg_len, group.q_bits()); if(i >= q) i -= q; @@ -224,13 +256,13 @@ bool DSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len, s = inverse_mod(s, q); - const BigInt sr = m_group.multiply_mod_q(s, r); - const BigInt si = m_group.multiply_mod_q(s, i); + const BigInt sr = group.multiply_mod_q(s, r); + const BigInt si = group.multiply_mod_q(s, i); - s = m_group.multi_exponentiate(si, m_y, sr); + s = group.multi_exponentiate(si, m_key->public_key(), sr); // s is too big for Barrett, and verification doesn't need to be const-time - return (s % m_group.get_q() == r); + return (s % group.get_q() == r); } } @@ -240,7 +272,7 @@ DSA_PublicKey::create_verification_op(const std::string& params, const std::string& provider) const { if(provider == "base" || provider.empty()) - return std::make_unique(*this, params); + return std::make_unique(this->m_public_key, params); throw Provider_Not_Found(algo_name(), provider); } @@ -249,7 +281,7 @@ DSA_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& signature_ const std::string& provider) const { if(provider == "base" || provider.empty()) - return std::make_unique(*this, signature_algorithm); + return std::make_unique(this->m_public_key, signature_algorithm); throw Provider_Not_Found(algo_name(), provider); } @@ -260,7 +292,7 @@ DSA_PrivateKey::create_signature_op(RandomNumberGenerator& rng, const std::string& provider) const { if(provider == "base" || provider.empty()) - return std::make_unique(*this, params, rng); + return std::make_unique(this->m_private_key, params, rng); throw Provider_Not_Found(algo_name(), provider); } diff --git a/src/lib/pubkey/dsa/dsa.h b/src/lib/pubkey/dsa/dsa.h index bde52e76d84..9afacbd7ede 100644 --- a/src/lib/pubkey/dsa/dsa.h +++ b/src/lib/pubkey/dsa/dsa.h @@ -1,6 +1,6 @@ /* * DSA -* (C) 1999-2010 Jack Lloyd +* (C) 1999-2010,2023 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -8,29 +8,29 @@ #ifndef BOTAN_DSA_H_ #define BOTAN_DSA_H_ -#include +#include +#include namespace Botan { +class BigInt; +class DL_Group; +class DL_PublicKey; +class DL_PrivateKey; + /** * DSA Public Key */ -class BOTAN_PUBLIC_API(2,0) DSA_PublicKey : public virtual DL_Scheme_PublicKey +class BOTAN_PUBLIC_API(2,0) DSA_PublicKey : public virtual Public_Key { public: - std::string algo_name() const override { return "DSA"; } - - DL_Group_Format group_format() const override { return DL_Group_Format::ANSI_X9_57; } - size_t message_parts() const override { return 2; } - size_t message_part_size() const override { return group_q().bytes(); } - bool supports_operation(PublicKeyOperation op) const override { return (op == PublicKeyOperation::Signature); } /** - * Load a public key. + * Load a public key from the ASN.1 encoding * @param alg_id the X.509 algorithm identifier * @param key_bits DER encoded public key bits */ @@ -38,12 +38,27 @@ class BOTAN_PUBLIC_API(2,0) DSA_PublicKey : public virtual DL_Scheme_PublicKey const std::vector& key_bits); /** - * Create a public key. + * Load a public key from the integer value * @param group the underlying DL group * @param y the public value y = g^x mod p */ DSA_PublicKey(const DL_Group& group, const BigInt& y); + std::string algo_name() const override { return "DSA"; } + + size_t message_parts() const override { return 2; } + size_t message_part_size() const override; + + AlgorithmIdentifier algorithm_identifier() const override; + std::vector public_key_bits() const override; + + bool check_key(RandomNumberGenerator& rng, bool strong) const override; + + size_t estimated_strength() const override; + size_t key_length() const override; + + const BigInt& get_int_field(const std::string& field) const override; + std::unique_ptr create_verification_op(const std::string& params, const std::string& provider) const override; @@ -51,19 +66,27 @@ class BOTAN_PUBLIC_API(2,0) DSA_PublicKey : public virtual DL_Scheme_PublicKey std::unique_ptr create_x509_verification_op(const AlgorithmIdentifier& signature_algorithm, const std::string& provider) const override; - protected: + private: + friend class DSA_PrivateKey; + DSA_PublicKey() = default; + + DSA_PublicKey(std::shared_ptr key) : + m_public_key(key) {} + + std::shared_ptr m_public_key; }; /** * DSA Private Key */ -class BOTAN_PUBLIC_API(2,0) DSA_PrivateKey final : public DSA_PublicKey, - public virtual DL_Scheme_PrivateKey +class BOTAN_PUBLIC_API(2,0) DSA_PrivateKey final : + public DSA_PublicKey, + public virtual Private_Key { public: /** - * Load a private key. + * Load a private key from the ASN.1 encoding * @param alg_id the X.509 algorithm identifier * @param key_bits DER encoded key bits in ANSI X9.57 format */ @@ -71,23 +94,35 @@ class BOTAN_PUBLIC_API(2,0) DSA_PrivateKey final : public DSA_PublicKey, const secure_vector& key_bits); /** - * Create a private key. - * @param rng the RNG to use + * Create a new private key. * @param group the underlying DL group - * @param private_key the private key (if zero, a new random key is generated) + * @param rng the RNG to use */ DSA_PrivateKey(RandomNumberGenerator& rng, - const DL_Group& group, - const BigInt& private_key = BigInt::zero()); + const DL_Group& group); + + /** + * Load a private key + * @param group the underlying DL group + * @param private_key the private key + */ + DSA_PrivateKey(const DL_Group& group, + const BigInt& private_key); std::unique_ptr public_key() const override; bool check_key(RandomNumberGenerator& rng, bool strong) const override; + secure_vector private_key_bits() const override; + + const BigInt& get_int_field(const std::string& field) const override; + std::unique_ptr create_signature_op(RandomNumberGenerator& rng, const std::string& params, const std::string& provider) const override; + private: + std::shared_ptr m_private_key; }; } diff --git a/src/lib/pubkey/elgamal/elgamal.cpp b/src/lib/pubkey/elgamal/elgamal.cpp index 11a2c2aaace..73fff8be2db 100644 --- a/src/lib/pubkey/elgamal/elgamal.cpp +++ b/src/lib/pubkey/elgamal/elgamal.cpp @@ -1,11 +1,12 @@ /* * ElGamal -* (C) 1999-2007,2018,2019 Jack Lloyd +* (C) 1999-2007,2018,2019,2023 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include +#include #include #include #include @@ -13,60 +14,91 @@ namespace Botan { -/* -* ElGamal_PublicKey Constructor -*/ -ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& group, const BigInt& y) : - DL_Scheme_PublicKey(group, y) +ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& group, const BigInt& y) { + m_public_key = std::make_shared(group, y); + } + +ElGamal_PublicKey::ElGamal_PublicKey(const AlgorithmIdentifier& alg_id, + const std::vector& key_bits) + { + m_public_key = std::make_shared(alg_id, key_bits, DL_Group_Format::ANSI_X9_42); + } + +size_t ElGamal_PublicKey::estimated_strength() const + { + return m_public_key->estimated_strength(); + } + +size_t ElGamal_PublicKey::key_length() const + { + return m_public_key->p_bits(); + } + +AlgorithmIdentifier ElGamal_PublicKey::algorithm_identifier() const + { + return AlgorithmIdentifier( + object_identifier(), + m_public_key->group().DER_encode(DL_Group_Format::ANSI_X9_42)); + } + +std::vector ElGamal_PublicKey::public_key_bits() const + { + return m_public_key->DER_encode(); + } + +const BigInt& ElGamal_PublicKey::get_int_field(const std::string& field) const + { + return m_public_key->get_int_field(algo_name(), field); + } + +bool ElGamal_PublicKey::check_key(RandomNumberGenerator& rng, bool strong) const + { + return m_public_key->check_key(rng, strong); } -/* -* ElGamal_PrivateKey Constructor -*/ ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, - const DL_Group& group, - const BigInt& x) + const DL_Group& group) { - m_x = x; - m_group = group; + m_private_key = std::make_shared(group, rng); + m_public_key = m_private_key->public_key(); + } - if(m_x.is_zero()) - { - const size_t exp_bits = m_group.exponent_bits(); - m_x.randomize(rng, exp_bits); - m_y = m_group.power_g_p(m_x, exp_bits); - } - else - { - m_y = m_group.power_g_p(m_x, m_group.p_bits()); - } +ElGamal_PrivateKey::ElGamal_PrivateKey(const DL_Group& group, + const BigInt& x) + { + m_private_key = std::make_shared(group, x); + m_public_key = m_private_key->public_key(); } ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, - const secure_vector& key_bits) : - DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group_Format::ANSI_X9_42) + const secure_vector& key_bits) { - m_y = m_group.power_g_p(m_x, m_group.p_bits()); + m_private_key = std::make_shared(alg_id, key_bits, DL_Group_Format::ANSI_X9_42); + m_public_key = m_private_key->public_key(); } std::unique_ptr ElGamal_PrivateKey::public_key() const { - return std::make_unique(get_group(), get_y()); + return std::unique_ptr(new ElGamal_PublicKey(m_public_key)); + } + +const BigInt& ElGamal_PrivateKey::get_int_field(const std::string& field) const + { + return m_private_key->get_int_field(algo_name(), field); + } + +secure_vector ElGamal_PrivateKey::private_key_bits() const + { + return m_private_key->DER_encode(); } -/* -* Check Private ElGamal Parameters -*/ bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const { - if(!DL_Scheme_PrivateKey::check_key(rng, strong)) + if(!m_private_key->check_key(rng, strong)) return false; - if(!strong) - return true; - return KeyPair::encryption_consistency_check(rng, *this, "OAEP(SHA-256)"); } @@ -79,38 +111,44 @@ class ElGamal_Encryption_Operation final : public PK_Ops::Encryption_with_EME { public: - size_t ciphertext_length(size_t /*ptext_len*/) const override { return 2*m_group.p_bytes(); } + ElGamal_Encryption_Operation(const std::shared_ptr key, + const std::string& eme) : + PK_Ops::Encryption_with_EME(eme), + m_key(key) + { + const size_t powm_window = 4; + m_monty_y_p = monty_precompute(m_key->group().monty_params_p(), + m_key->public_key(), + powm_window); + } - size_t max_ptext_input_bits() const override { return m_group.p_bits() - 1; } + size_t ciphertext_length(size_t /*ptext_len*/) const override + { + return 2*m_key->group().p_bytes(); + } - ElGamal_Encryption_Operation(const ElGamal_PublicKey& key, const std::string& eme); + size_t max_ptext_input_bits() const override + { + return m_key->group().p_bits() - 1; + } secure_vector raw_encrypt(const uint8_t msg[], size_t msg_len, RandomNumberGenerator& rng) override; private: - const DL_Group m_group; + std::shared_ptr m_key; std::shared_ptr m_monty_y_p; }; -ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key, - const std::string& eme) : - PK_Ops::Encryption_with_EME(eme), - m_group(key.get_group()) - { - const size_t powm_window = 4; - m_monty_y_p = monty_precompute(key.get_group().monty_params_p(), - key.get_y(), - powm_window); - } - secure_vector ElGamal_Encryption_Operation::raw_encrypt(const uint8_t msg[], size_t msg_len, RandomNumberGenerator& rng) { BigInt m(msg, msg_len); - if(m >= m_group.get_p()) + const auto& group = m_key->group(); + + if(m >= group.get_p()) throw Invalid_Argument("ElGamal encryption: Input is too large"); /* @@ -121,13 +159,13 @@ ElGamal_Encryption_Operation::raw_encrypt(const uint8_t msg[], size_t msg_len, See https://eprint.iacr.org/2021/923 */ - const size_t k_bits = m_group.p_bits() - 1; + const size_t k_bits = group.p_bits() - 1; const BigInt k(rng, k_bits, false); - const BigInt a = m_group.power_g_p(k, k_bits); - const BigInt b = m_group.multiply_mod_p(m, monty_execute(*m_monty_y_p, k, k_bits)); + const BigInt a = group.power_g_p(k, k_bits); + const BigInt b = group.multiply_mod_p(m, monty_execute(*m_monty_y_p, k, k_bits)); - return BigInt::encode_fixed_length_int_pair(a, b, m_group.p_bytes()); + return BigInt::encode_fixed_length_int_pair(a, b, group.p_bytes()); } /** @@ -137,47 +175,39 @@ class ElGamal_Decryption_Operation final : public PK_Ops::Decryption_with_EME { public: - ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key, + ElGamal_Decryption_Operation(const std::shared_ptr key, const std::string& eme, - RandomNumberGenerator& rng); - - size_t plaintext_length(size_t /*ctext_len*/) const override { return m_group.p_bytes(); } + RandomNumberGenerator& rng) : + PK_Ops::Decryption_with_EME(eme), + m_key(key), + m_blinder(m_key->group().get_p(), + rng, + [](const BigInt& k) { return k; }, + [this](const BigInt& k) { return powermod_x_p(k); }) + {} + + size_t plaintext_length(size_t /*ctext_len*/) const override + { + return m_key->group().p_bytes(); + } secure_vector raw_decrypt(const uint8_t msg[], size_t msg_len) override; private: BigInt powermod_x_p(const BigInt& v) const { - const size_t powm_window = 4; - auto powm_v_p = monty_precompute(m_monty_p, v, powm_window); - return monty_execute(*powm_v_p, m_x, m_x_bits); + return m_key->group().power_b_p(v, m_key->private_key()); } - const DL_Group m_group; - const BigInt& m_x; - const size_t m_x_bits; - std::shared_ptr m_monty_p; + std::shared_ptr m_key; Blinder m_blinder; }; -ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key, - const std::string& eme, - RandomNumberGenerator& rng) : - PK_Ops::Decryption_with_EME(eme), - m_group(key.get_group()), - m_x(key.get_x()), - m_x_bits(m_x.bits()), - m_monty_p(key.get_group().monty_params_p()), - m_blinder(m_group.get_p(), - rng, - [](const BigInt& k) { return k; }, - [this](const BigInt& k) { return powermod_x_p(k); }) - { - } - secure_vector ElGamal_Decryption_Operation::raw_decrypt(const uint8_t msg[], size_t msg_len) { - const size_t p_bytes = m_group.p_bytes(); + const auto& group = m_key->group(); + + const size_t p_bytes = group.p_bytes(); if(msg_len != 2 * p_bytes) throw Invalid_Argument("ElGamal decryption: Invalid message"); @@ -185,12 +215,12 @@ ElGamal_Decryption_Operation::raw_decrypt(const uint8_t msg[], size_t msg_len) BigInt a(msg, p_bytes); const BigInt b(msg + p_bytes, p_bytes); - if(a >= m_group.get_p() || b >= m_group.get_p()) + if(a >= group.get_p() || b >= group.get_p()) throw Invalid_Argument("ElGamal decryption: Invalid message"); a = m_blinder.blind(a); - const BigInt r = m_group.multiply_mod_p(m_group.inverse_mod_p(powermod_x_p(a)), b); + const BigInt r = group.multiply_mod_p(group.inverse_mod_p(powermod_x_p(a)), b); return BigInt::encode_1363(m_blinder.unblind(r), p_bytes); } @@ -203,7 +233,7 @@ ElGamal_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/, const std::string& provider) const { if(provider == "base" || provider.empty()) - return std::make_unique(*this, params); + return std::make_unique(this->m_public_key, params); throw Provider_Not_Found(algo_name(), provider); } @@ -213,7 +243,7 @@ ElGamal_PrivateKey::create_decryption_op(RandomNumberGenerator& rng, const std::string& provider) const { if(provider == "base" || provider.empty()) - return std::make_unique(*this, params, rng); + return std::make_unique(this->m_private_key, params, rng); throw Provider_Not_Found(algo_name(), provider); } diff --git a/src/lib/pubkey/elgamal/elgamal.h b/src/lib/pubkey/elgamal/elgamal.h index 430ff3591ec..2f4faba3d49 100644 --- a/src/lib/pubkey/elgamal/elgamal.h +++ b/src/lib/pubkey/elgamal/elgamal.h @@ -1,6 +1,6 @@ /* * ElGamal -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2007,2023 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -8,33 +8,34 @@ #ifndef BOTAN_ELGAMAL_H_ #define BOTAN_ELGAMAL_H_ -#include +#include +#include namespace Botan { +class BigInt; +class DL_Group; +class DL_PublicKey; +class DL_PrivateKey; + /** * ElGamal Public Key */ -class BOTAN_PUBLIC_API(2,0) ElGamal_PublicKey : public virtual DL_Scheme_PublicKey +class BOTAN_PUBLIC_API(2,0) ElGamal_PublicKey : public virtual Public_Key { public: - std::string algo_name() const override { return "ElGamal"; } - DL_Group_Format group_format() const override { return DL_Group_Format::ANSI_X9_42; } - bool supports_operation(PublicKeyOperation op) const override { return (op == PublicKeyOperation::Encryption); } /** - * Load a public key. + * Load a public key from the ASN.1 encoding * @param alg_id the X.509 algorithm identifier * @param key_bits DER encoded public key bits */ ElGamal_PublicKey(const AlgorithmIdentifier& alg_id, - const std::vector& key_bits) : - DL_Scheme_PublicKey(alg_id, key_bits, DL_Group_Format::ANSI_X9_42) - {} + const std::vector& key_bits); /** * Create a public key. @@ -43,26 +44,44 @@ class BOTAN_PUBLIC_API(2,0) ElGamal_PublicKey : public virtual DL_Scheme_PublicK */ ElGamal_PublicKey(const DL_Group& group, const BigInt& y); + AlgorithmIdentifier algorithm_identifier() const override; + std::vector public_key_bits() const override; + + bool check_key(RandomNumberGenerator& rng, bool strong) const override; + + size_t estimated_strength() const override; + size_t key_length() const override; + + std::string algo_name() const override { return "ElGamal"; } + + const BigInt& get_int_field(const std::string& field) const override; + std::unique_ptr create_encryption_op(RandomNumberGenerator& rng, const std::string& params, const std::string& provider) const override; - protected: + private: + friend class ElGamal_PrivateKey; + ElGamal_PublicKey() = default; + + ElGamal_PublicKey(std::shared_ptr key) : + m_public_key(key) {} + + std::shared_ptr m_public_key; }; /** * ElGamal Private Key */ -class BOTAN_PUBLIC_API(2,0) ElGamal_PrivateKey final : public ElGamal_PublicKey, - public virtual DL_Scheme_PrivateKey +class BOTAN_PUBLIC_API(2,0) ElGamal_PrivateKey final : + public ElGamal_PublicKey, + public virtual Private_Key { public: - bool check_key(RandomNumberGenerator& rng, bool) const override; - /** - * Load a private key. + * Load a private key from the ASN.1 encoding * @param alg_id the X.509 algorithm identifier * @param key_bits DER encoded key bits in ANSI X9.42 format */ @@ -70,21 +89,35 @@ class BOTAN_PUBLIC_API(2,0) ElGamal_PrivateKey final : public ElGamal_PublicKey, const secure_vector& key_bits); /** - * Create a private key. + * Create a new random private key. * @param rng random number generator to use * @param group the group to be used in the key - * @param priv_key the key's secret value (or if zero, generate a new key) */ ElGamal_PrivateKey(RandomNumberGenerator& rng, - const DL_Group& group, - const BigInt& priv_key = BigInt::zero()); + const DL_Group& group); + + /** + * Load a private key from the integer encoding + * @param group the group to be used in the key + * @param private_key the key's secret value + */ + ElGamal_PrivateKey(const DL_Group& group, + const BigInt& private_key); + + bool check_key(RandomNumberGenerator& rng, bool) const override; std::unique_ptr public_key() const override; + secure_vector private_key_bits() const override; + + const BigInt& get_int_field(const std::string& field) const override; + std::unique_ptr create_decryption_op(RandomNumberGenerator& rng, const std::string& params, const std::string& provider) const override; + private: + std::shared_ptr m_private_key; }; } diff --git a/src/lib/pubkey/pk_algs.cpp b/src/lib/pubkey/pk_algs.cpp index ad08b06b2a0..53fc58da03f 100644 --- a/src/lib/pubkey/pk_algs.cpp +++ b/src/lib/pubkey/pk_algs.cpp @@ -291,6 +291,9 @@ create_ec_private_key(const std::string& alg_name, const EC_Group& ec_group, RandomNumberGenerator& rng) { + // Potentially unused if all EC algorthms are disabled + BOTAN_UNUSED(alg_name, ec_group, rng); + #if defined(BOTAN_HAS_ECDSA) if(alg_name == "ECDSA") return std::make_unique(rng, ec_group); diff --git a/src/lib/tls/tls12/msg_server_kex.cpp b/src/lib/tls/tls12/msg_server_kex.cpp index dc605969fd5..551460c47c6 100644 --- a/src/lib/tls/tls12/msg_server_kex.cpp +++ b/src/lib/tls/tls12/msg_server_kex.cpp @@ -14,7 +14,9 @@ #include #include #include +#include +#include #include #include @@ -74,8 +76,8 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io, const std::string group_name = state.callbacks().tls_decode_group_param(shared_group); auto dh = std::make_unique(rng, DL_Group(group_name)); - append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2); - append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2); + append_tls_length_value(m_params, BigInt::encode(dh->get_int_field("p")), 2); + append_tls_length_value(m_params, BigInt::encode(dh->get_int_field("g")), 2); append_tls_length_value(m_params, dh->public_value(), 2); m_kex_key.reset(dh.release()); } diff --git a/src/lib/tls/tls13/tls_extensions_key_share.cpp b/src/lib/tls/tls13/tls_extensions_key_share.cpp index a4298b5771c..8b7b7008e17 100644 --- a/src/lib/tls/tls13/tls_extensions_key_share.cpp +++ b/src/lib/tls/tls13/tls_extensions_key_share.cpp @@ -25,6 +25,7 @@ #include #include +#include namespace Botan::TLS { diff --git a/src/lib/tls/tls_callbacks.cpp b/src/lib/tls/tls_callbacks.cpp index b5bb8b1a1d8..da4dc5994b1 100644 --- a/src/lib/tls/tls_callbacks.cpp +++ b/src/lib/tls/tls_callbacks.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/src/tests/test_dh.cpp b/src/tests/test_dh.cpp index 4e47157e4a1..8fc7dd82a58 100644 --- a/src/tests/test_dh.cpp +++ b/src/tests/test_dh.cpp @@ -10,6 +10,7 @@ #include "test_pubkey.h" #include #include + #include #endif namespace Botan_Tests { @@ -40,17 +41,17 @@ class Diffie_Hellman_KAT_Tests final : public PK_Key_Agreement_Test const Botan::BigInt g = vars.get_req_bn("G"); const Botan::BigInt x = vars.get_req_bn("X"); - Botan::DL_Group grp; + Botan::DL_Group group; if(q == 0) { - grp = Botan::DL_Group(p, g); + group = Botan::DL_Group(p, g); } else { - grp = Botan::DL_Group(p, q, g); + group = Botan::DL_Group(p, q, g); } - return std::make_unique(Test::rng(), grp, x); + return std::make_unique(group, x); } std::vector load_their_key(const std::string& /*header*/, const VarMap& vars) override @@ -60,17 +61,17 @@ class Diffie_Hellman_KAT_Tests final : public PK_Key_Agreement_Test const Botan::BigInt g = vars.get_req_bn("G"); const Botan::BigInt y = vars.get_req_bn("Y"); - Botan::DL_Group grp; + Botan::DL_Group group; if(q == 0) { - grp = Botan::DL_Group(p, g); + group = Botan::DL_Group(p, g); } else { - grp = Botan::DL_Group(p, q, g); + group = Botan::DL_Group(p, q, g); } - Botan::DH_PublicKey key(grp, y); + Botan::DH_PublicKey key(group, y); return key.public_value(); } @@ -80,10 +81,10 @@ class Diffie_Hellman_KAT_Tests final : public PK_Key_Agreement_Test const BigInt g("2"); const BigInt p("58458002095536094658683755258523362961421200751439456159756164191494576279467"); - const Botan::DL_Group grp(p, g); + const Botan::DL_Group group(p, g); const Botan::BigInt x("46205663093589612668746163860870963912226379131190812163519349848291472898748"); - auto privkey = std::make_unique(Test::rng(), grp, x); + auto privkey = std::make_unique(group, x); auto kas = std::make_unique(*privkey, rng(), "Raw"); @@ -128,8 +129,9 @@ class DH_Invalid_Key_Tests final : public Text_Based_Test const Botan::BigInt g = vars.get_req_bn("G"); const Botan::BigInt pubkey = vars.get_req_bn("InvalidKey"); - Botan::DL_Group grp(p, q, g); - auto key = std::make_unique(grp, pubkey); + Botan::DL_Group group(p, q, g); + + auto key = std::make_unique(group, pubkey); result.test_eq("public key fails check", key->check_key(Test::rng(), false), false); return result; } diff --git a/src/tests/test_dlies.cpp b/src/tests/test_dlies.cpp index 641eb9fa22c..cf1dbc31c96 100644 --- a/src/tests/test_dlies.cpp +++ b/src/tests/test_dlies.cpp @@ -11,6 +11,7 @@ #include "test_pubkey.h" #include #include + #include #endif namespace Botan_Tests { @@ -78,8 +79,8 @@ class DLIES_KAT_Tests final : public Text_Based_Test Botan::DL_Group domain(group_name); - Botan::DH_PrivateKey from(Test::rng(), domain, x1); - Botan::DH_PrivateKey to(Test::rng(), domain, x2); + Botan::DH_PrivateKey from(domain, x1); + Botan::DH_PrivateKey to(domain, x2); Botan::DLIES_Encryptor encryptor(from, Test::rng(), kdf->new_object(), diff --git a/src/tests/test_dsa.cpp b/src/tests/test_dsa.cpp index 4054e64c066..e97a8f23f0a 100644 --- a/src/tests/test_dsa.cpp +++ b/src/tests/test_dsa.cpp @@ -8,6 +8,8 @@ #if defined(BOTAN_HAS_DSA) #include + #include + #include #include "test_pubkey.h" #endif @@ -43,9 +45,9 @@ class DSA_KAT_Tests final : public PK_Signature_Generation_Test const Botan::BigInt g = vars.get_req_bn("G"); const Botan::BigInt x = vars.get_req_bn("X"); - const Botan::DL_Group grp(p, q, g); + const Botan::DL_Group group(p, q, g); - return std::make_unique(Test::rng(), grp, x); + return std::make_unique(group, x); } std::string default_padding(const VarMap& vars) const override @@ -82,7 +84,7 @@ class DSA_KAT_Verification_Tests final : public PK_Signature_Verification_Test const Botan::DL_Group grp(p, q, g); - const Botan::DSA_PrivateKey priv_key(Test::rng(), grp, x); + const Botan::DSA_PrivateKey priv_key(grp, x); return priv_key.public_key(); } @@ -113,9 +115,9 @@ class DSA_Verification_Tests final : public PK_Signature_Verification_Test const Botan::BigInt g = vars.get_req_bn("G"); const Botan::BigInt y = vars.get_req_bn("Y"); - const Botan::DL_Group grp(p, q, g); + const Botan::DL_Group group(p, q, g); - return std::make_unique(grp, y); + return std::make_unique(group, y); } std::string default_padding(const VarMap& /*unused*/) const override diff --git a/src/tests/test_elgamal.cpp b/src/tests/test_elgamal.cpp index 283c742fc77..6cf72507ea5 100644 --- a/src/tests/test_elgamal.cpp +++ b/src/tests/test_elgamal.cpp @@ -8,6 +8,7 @@ #if defined(BOTAN_HAS_ELGAMAL) #include + #include #include "test_pubkey.h" #endif @@ -29,9 +30,9 @@ class ElGamal_Encrypt_Tests final : public PK_Encryption_Decryption_Test std::unique_ptr load_private_key(const VarMap& vars) override { const Botan::BigInt x = vars.get_req_bn("Secret"); - const Botan::DL_Group grp(vars.get_req_str("Group")); + const Botan::DL_Group group(vars.get_req_str("Group")); - return std::make_unique(Test::rng(), grp, x); + return std::make_unique(group, x); } }; @@ -50,9 +51,9 @@ class ElGamal_Decrypt_Tests final : public PK_Decryption_Test const Botan::BigInt g = vars.get_req_bn("G"); const Botan::BigInt x = vars.get_req_bn("X"); - const Botan::DL_Group grp(p, g); + const Botan::DL_Group group(p, g); - return std::make_unique(Test::rng(), grp, x); + return std::make_unique(group, x); } }; diff --git a/src/tests/unit_tls_policy.cpp b/src/tests/unit_tls_policy.cpp index 6276b042f47..61d34556460 100644 --- a/src/tests/unit_tls_policy.cpp +++ b/src/tests/unit_tls_policy.cpp @@ -26,6 +26,7 @@ #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) + #include #include #endif @@ -134,7 +135,7 @@ class TLS_Policy_Unit_Tests final : public Test const BigInt p("58458002095536094658683755258523362961421200751439456159756164191494576279467"); const Botan::DL_Group grp(p, g); const Botan::BigInt x("46205663093589612668746163860870963912226379131190812163519349848291472898748"); - auto dhkey = std::make_unique(Test::rng(), grp, x); + auto dhkey = std::make_unique(grp, x); Botan::TLS::Policy policy; try