diff options
Diffstat (limited to 'src/lib/pubkey')
41 files changed, 979 insertions, 215 deletions
diff --git a/src/lib/pubkey/blinding.cpp b/src/lib/pubkey/blinding.cpp index b20a30fa1..47436bcb0 100644 --- a/src/lib/pubkey/blinding.cpp +++ b/src/lib/pubkey/blinding.cpp @@ -8,25 +8,21 @@ #include <botan/blinding.h> #include <botan/numthry.h> -#if defined(BOTAN_HAS_SYSTEM_RNG) - #include <botan/system_rng.h> -#else - #include <botan/auto_rng.h> -#endif - namespace Botan { Blinder::Blinder(const BigInt& modulus, + RandomNumberGenerator& rng, std::function<BigInt (const BigInt&)> fwd, std::function<BigInt (const BigInt&)> inv) : - m_reducer{Modular_Reducer(modulus)}, m_rng{}, m_fwd_fn(fwd), m_inv_fn(inv), m_modulus_bits{modulus.bits()}, m_e{}, m_d{}, m_counter{} + m_reducer(modulus), + m_rng(rng), + m_fwd_fn(fwd), + m_inv_fn(inv), + m_modulus_bits(modulus.bits()), + m_e{}, + m_d{}, + m_counter{} { -#if defined(BOTAN_HAS_SYSTEM_RNG) - m_rng.reset(new System_RNG); -#else - m_rng.reset(new AutoSeeded_RNG); -#endif - const BigInt k = blinding_nonce(); m_e = m_fwd_fn(k); m_d = m_inv_fn(k); @@ -34,7 +30,7 @@ Blinder::Blinder(const BigInt& modulus, BigInt Blinder::blinding_nonce() const { - return BigInt(*m_rng, m_modulus_bits - 1); + return BigInt(m_rng, m_modulus_bits - 1); } BigInt Blinder::blind(const BigInt& i) const @@ -44,11 +40,12 @@ BigInt Blinder::blind(const BigInt& i) const ++m_counter; - if(BOTAN_BLINDING_REINIT_INTERVAL > 0 && (m_counter % BOTAN_BLINDING_REINIT_INTERVAL == 0)) + if((BOTAN_BLINDING_REINIT_INTERVAL > 0) && (m_counter > BOTAN_BLINDING_REINIT_INTERVAL)) { const BigInt k = blinding_nonce(); m_e = m_fwd_fn(k); m_d = m_inv_fn(k); + m_counter = 0; } else { diff --git a/src/lib/pubkey/blinding.h b/src/lib/pubkey/blinding.h index c1999feb7..a6b266807 100644 --- a/src/lib/pubkey/blinding.h +++ b/src/lib/pubkey/blinding.h @@ -26,11 +26,8 @@ class BOTAN_DLL Blinder BigInt unblind(const BigInt& x) const; - bool initialized() const { return m_reducer.initialized(); } - - Blinder() {} - Blinder(const BigInt& modulus, + RandomNumberGenerator& rng, std::function<BigInt (const BigInt&)> fwd_func, std::function<BigInt (const BigInt&)> inv_func); @@ -42,7 +39,7 @@ class BOTAN_DLL Blinder BigInt blinding_nonce() const; Modular_Reducer m_reducer; - std::unique_ptr<RandomNumberGenerator> m_rng; + RandomNumberGenerator& m_rng; std::function<BigInt (const BigInt&)> m_fwd_fn; std::function<BigInt (const BigInt&)> m_inv_fn; size_t m_modulus_bits = 0; diff --git a/src/lib/pubkey/curve25519/curve25519.cpp b/src/lib/pubkey/curve25519/curve25519.cpp index aa0646d04..02ee516de 100644 --- a/src/lib/pubkey/curve25519/curve25519.cpp +++ b/src/lib/pubkey/curve25519/curve25519.cpp @@ -5,8 +5,8 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/curve25519.h> +#include <botan/internal/pk_ops_impl.h> #include <botan/ber_dec.h> #include <botan/der_enc.h> @@ -134,9 +134,16 @@ class Curve25519_KA_Operation : public PK_Ops::Key_Agreement_with_KDF const Curve25519_PrivateKey& m_key; }; -BOTAN_REGISTER_PK_KEY_AGREE_OP("Curve25519", Curve25519_KA_Operation); - } +std::unique_ptr<PK_Ops::Key_Agreement> +Curve25519_PrivateKey::create_key_agreement_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Key_Agreement>(new Curve25519_KA_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } } diff --git a/src/lib/pubkey/curve25519/curve25519.h b/src/lib/pubkey/curve25519/curve25519.h index 9d2868d6d..fe39d9dd6 100644 --- a/src/lib/pubkey/curve25519/curve25519.h +++ b/src/lib/pubkey/curve25519/curve25519.h @@ -33,6 +33,7 @@ class BOTAN_DLL Curve25519_PublicKey : public virtual Public_Key const secure_vector<byte>& key_bits); explicit Curve25519_PublicKey(const secure_vector<byte>& pub) : m_public(pub) {} + protected: Curve25519_PublicKey() {} secure_vector<byte> m_public; @@ -60,6 +61,12 @@ class BOTAN_DLL Curve25519_PrivateKey : public Curve25519_PublicKey, secure_vector<byte> pkcs8_private_key() const override; bool check_key(RandomNumberGenerator& rng, bool strong) const override; + + std::unique_ptr<PK_Ops::Key_Agreement> + create_key_agreement_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + private: secure_vector<byte> m_private; }; diff --git a/src/lib/pubkey/curve25519/donna.cpp b/src/lib/pubkey/curve25519/donna.cpp index a0e4d249f..86b92b0bf 100644 --- a/src/lib/pubkey/curve25519/donna.cpp +++ b/src/lib/pubkey/curve25519/donna.cpp @@ -374,8 +374,8 @@ cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { swap_conditional(nqx, nqpqx, bit); swap_conditional(nqz, nqpqz, bit); - fmonty_out_t result { nqx2, nqz2, nqpqx2, nqpqz2 }; - fmonty_in_t in { nqx, nqz, nqpqx, nqpqz, q }; + fmonty_out_t result { {nqx2, nqz2}, {nqpqx2, nqpqz2} }; + fmonty_in_t in { { nqx, nqz }, { nqpqx, nqpqz }, q }; fmonty(result, in); swap_conditional(nqx2, nqpqx2, bit); swap_conditional(nqz2, nqpqz2, bit); diff --git a/src/lib/pubkey/dh/dh.cpp b/src/lib/pubkey/dh/dh.cpp index 8ed79aa3d..19ead1b11 100644 --- a/src/lib/pubkey/dh/dh.cpp +++ b/src/lib/pubkey/dh/dh.cpp @@ -1,12 +1,12 @@ /* * Diffie-Hellman -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2007,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/dh.h> +#include <botan/internal/pk_ops_impl.h> #include <botan/workfactor.h> #include <botan/pow_mod.h> #include <botan/blinding.h> @@ -41,7 +41,7 @@ DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, m_group = grp; m_x = x_arg; - if(m_x == 0) + if(generate) { const BigInt& p = group_p(); m_x.randomize(rng, dl_exponent_size(p.bits())); @@ -93,7 +93,16 @@ class DH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF { public: typedef DH_PrivateKey Key_Type; - DH_KA_Operation(const DH_PrivateKey& key, const std::string& kdf); + + DH_KA_Operation(const DH_PrivateKey& key, const std::string& kdf, RandomNumberGenerator& rng) : + PK_Ops::Key_Agreement_with_KDF(kdf), + m_p(key.group_p()), + m_powermod_x_p(key.get_x(), m_p), + m_blinder(m_p, + rng, + [](const BigInt& k) { return k; }, + [this](const BigInt& k) { return m_powermod_x_p(inverse_mod(k, m_p)); }) + {} secure_vector<byte> raw_agree(const byte w[], size_t w_len) override; private: @@ -103,16 +112,6 @@ class DH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF Blinder m_blinder; }; -DH_KA_Operation::DH_KA_Operation(const DH_PrivateKey& dh, const std::string& kdf) : - PK_Ops::Key_Agreement_with_KDF(kdf), - m_p(dh.group_p()), - m_powermod_x_p(dh.get_x(), m_p), - m_blinder(m_p, - [](const BigInt& k) { return k; }, - [this](const BigInt& k) { return m_powermod_x_p(inverse_mod(k, m_p)); }) - { - } - secure_vector<byte> DH_KA_Operation::raw_agree(const byte w[], size_t w_len) { BigInt input = BigInt::decode(w, w_len); @@ -127,6 +126,14 @@ secure_vector<byte> DH_KA_Operation::raw_agree(const byte w[], size_t w_len) } -BOTAN_REGISTER_PK_KEY_AGREE_OP("DH", DH_KA_Operation); +std::unique_ptr<PK_Ops::Key_Agreement> +DH_PrivateKey::create_key_agreement_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Key_Agreement>(new DH_KA_Operation(*this, 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 9911453fb..d15bc5eb3 100644 --- a/src/lib/pubkey/dh/dh.h +++ b/src/lib/pubkey/dh/dh.h @@ -67,6 +67,11 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey, */ DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& grp, const BigInt& x = 0); + + std::unique_ptr<PK_Ops::Key_Agreement> + create_key_agreement_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; }; } diff --git a/src/lib/pubkey/dlies/dlies.cpp b/src/lib/pubkey/dlies/dlies.cpp index 9666a1c23..09f24adb7 100644 --- a/src/lib/pubkey/dlies/dlies.cpp +++ b/src/lib/pubkey/dlies/dlies.cpp @@ -12,14 +12,16 @@ namespace Botan { DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key, + RandomNumberGenerator& rng, KDF* kdf, MessageAuthenticationCode* mac, size_t mac_key_length) : - DLIES_Encryptor(own_priv_key, kdf, nullptr, 0, mac, mac_key_length) + DLIES_Encryptor(own_priv_key, rng, kdf, nullptr, 0, mac, mac_key_length) { } DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key, + RandomNumberGenerator& rng, KDF* kdf, Cipher_Mode* cipher, size_t cipher_key_len, @@ -27,7 +29,7 @@ DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key, size_t mac_key_length) : m_other_pub_key(), m_own_pub_key(own_priv_key.public_value()), - m_ka(own_priv_key, "Raw"), + m_ka(own_priv_key, rng, "Raw"), m_kdf(kdf), m_cipher(cipher), m_cipher_key_len(cipher_key_len), @@ -111,13 +113,14 @@ size_t DLIES_Encryptor::maximum_input_size() const } DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key, + RandomNumberGenerator& rng, KDF* kdf, Cipher_Mode* cipher, size_t cipher_key_len, MessageAuthenticationCode* mac, size_t mac_key_length) : m_pub_key_size(own_priv_key.public_value().size()), - m_ka(own_priv_key, "Raw"), + m_ka(own_priv_key, rng, "Raw"), m_kdf(kdf), m_cipher(cipher), m_cipher_key_len(cipher_key_len), @@ -130,10 +133,11 @@ DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key, } DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key, + RandomNumberGenerator& rng, KDF* kdf, MessageAuthenticationCode* mac, size_t mac_key_length) : - DLIES_Decryptor(own_priv_key, kdf, nullptr, 0, mac, mac_key_length) + DLIES_Decryptor(own_priv_key, rng, kdf, nullptr, 0, mac, mac_key_length) {} secure_vector<byte> DLIES_Decryptor::do_decrypt(byte& valid_mask, diff --git a/src/lib/pubkey/dlies/dlies.h b/src/lib/pubkey/dlies/dlies.h index 5f7251d03..f6bf9c6dd 100644 --- a/src/lib/pubkey/dlies/dlies.h +++ b/src/lib/pubkey/dlies/dlies.h @@ -34,6 +34,7 @@ class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor * output = (ephemeral) public key + ciphertext + tag */ DLIES_Encryptor(const DH_PrivateKey& own_priv_key, + RandomNumberGenerator& rng, KDF* kdf, MessageAuthenticationCode* mac, size_t mac_key_len = 20); @@ -51,6 +52,7 @@ class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor * output = (ephemeral) public key + ciphertext + tag */ DLIES_Encryptor(const DH_PrivateKey& own_priv_key, + RandomNumberGenerator& rng, KDF* kdf, Cipher_Mode* cipher, size_t cipher_key_len, @@ -103,6 +105,7 @@ class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor * input = (ephemeral) public key + ciphertext + tag */ DLIES_Decryptor(const DH_PrivateKey& own_priv_key, + RandomNumberGenerator& rng, KDF* kdf, MessageAuthenticationCode* mac, size_t mac_key_len = 20); @@ -120,6 +123,7 @@ class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor * input = (ephemeral) public key + ciphertext + tag */ DLIES_Decryptor(const DH_PrivateKey& own_priv_key, + RandomNumberGenerator& rng, KDF* kdf, Cipher_Mode* cipher, size_t cipher_key_len, diff --git a/src/lib/pubkey/dsa/dsa.cpp b/src/lib/pubkey/dsa/dsa.cpp index 399756b1a..15dc45373 100644 --- a/src/lib/pubkey/dsa/dsa.cpp +++ b/src/lib/pubkey/dsa/dsa.cpp @@ -1,20 +1,22 @@ /* * DSA -* (C) 1999-2010,2014 Jack Lloyd +* (C) 1999-2010,2014,2016 Jack Lloyd * (C) 2016 René Korthaus * * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/dsa.h> #include <botan/keypair.h> #include <botan/pow_mod.h> #include <botan/reducer.h> +#include <botan/internal/pk_ops_impl.h> + #if defined(BOTAN_HAS_RFC6979_GENERATOR) - #include <botan/rfc6979.h> #include <botan/emsa.h> + #include <botan/rfc6979.h> #endif + #include <future> namespace Botan { @@ -193,9 +195,25 @@ bool DSA_Verification_Operation::verify(const byte msg[], size_t msg_len, return (m_mod_q.reduce(s) == r); } -BOTAN_REGISTER_PK_SIGNATURE_OP("DSA", DSA_Signature_Operation); -BOTAN_REGISTER_PK_VERIFY_OP("DSA", DSA_Verification_Operation); - } +std::unique_ptr<PK_Ops::Verification> +DSA_PublicKey::create_verification_op(const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Verification>(new DSA_Verification_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::Signature> +DSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Signature>(new DSA_Signature_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + } diff --git a/src/lib/pubkey/dsa/dsa.h b/src/lib/pubkey/dsa/dsa.h index 2653c9229..57c7b7c5c 100644 --- a/src/lib/pubkey/dsa/dsa.h +++ b/src/lib/pubkey/dsa/dsa.h @@ -32,6 +32,10 @@ class BOTAN_DLL DSA_PublicKey : public virtual DL_Scheme_PublicKey } DSA_PublicKey(const DL_Group& group, const BigInt& y); + + std::unique_ptr<PK_Ops::Verification> + create_verification_op(const std::string& params, + const std::string& provider) const override; protected: DSA_PublicKey() {} }; @@ -52,6 +56,11 @@ class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey, const BigInt& private_key = 0); bool check_key(RandomNumberGenerator& rng, bool strong) const override; + + std::unique_ptr<PK_Ops::Signature> + create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; }; } diff --git a/src/lib/pubkey/ecdh/ecdh.cpp b/src/lib/pubkey/ecdh/ecdh.cpp index 55e215bc1..f3da737bb 100644 --- a/src/lib/pubkey/ecdh/ecdh.cpp +++ b/src/lib/pubkey/ecdh/ecdh.cpp @@ -7,8 +7,12 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/ecdh.h> +#include <botan/internal/pk_ops_impl.h> + +#if defined(BOTAN_HAS_OPENSSL) + #include <botan/internal/openssl.h> +#endif namespace Botan { @@ -35,6 +39,7 @@ class ECDH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF secure_vector<byte> raw_agree(const byte w[], size_t w_len) override { PointGFp point = OS2ECP(w, w_len, m_curve); + // TODO: add blinding PointGFp S = (m_cofactor * point) * m_l_times_priv; BOTAN_ASSERT(S.on_the_curve(), "ECDH agreed value was on the curve"); return BigInt::encode_1363(S.get_affine_x(), m_curve.get_p().bytes()); @@ -47,6 +52,31 @@ class ECDH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF } -BOTAN_REGISTER_PK_KEY_AGREE_OP("ECDH", ECDH_KA_Operation); +std::unique_ptr<PK_Ops::Key_Agreement> +ECDH_PrivateKey::create_key_agreement_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { +#if defined(BOTAN_HAS_OPENSSL) + if(provider == "openssl" || provider.empty()) + { + try + { + return make_openssl_ecdh_ka_op(*this, params); + } + catch(Lookup_Error&) + { + if(provider == "openssl") + throw; + } + } +#endif + + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Key_Agreement>(new ECDH_KA_Operation(*this, params)); + + throw Provider_Not_Found(algo_name(), provider); + } + } diff --git a/src/lib/pubkey/ecdh/ecdh.h b/src/lib/pubkey/ecdh/ecdh.h index bdd9ea047..5b6ec7261 100644 --- a/src/lib/pubkey/ecdh/ecdh.h +++ b/src/lib/pubkey/ecdh/ecdh.h @@ -94,6 +94,11 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, std::vector<byte> public_value(PointGFp::Compression_Type type) const { return ECDH_PublicKey::public_value(type); } + + std::unique_ptr<PK_Ops::Key_Agreement> + create_key_agreement_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; }; } diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp index 264a36963..48d16caca 100644 --- a/src/lib/pubkey/ecdsa/ecdsa.cpp +++ b/src/lib/pubkey/ecdsa/ecdsa.cpp @@ -2,18 +2,24 @@ * ECDSA implemenation * (C) 2007 Manuel Hartl, FlexSecure GmbH * 2007 Falko Strenzke, FlexSecure GmbH -* 2008-2010,2015 Jack Lloyd +* 2008-2010,2015,2016 Jack Lloyd * 2016 René Korthaus * * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/ecdsa.h> +#include <botan/internal/pk_ops_impl.h> #include <botan/keypair.h> +#include <botan/reducer.h> +#include <botan/emsa.h> + #if defined(BOTAN_HAS_RFC6979_GENERATOR) #include <botan/rfc6979.h> - #include <botan/emsa.h> +#endif + +#if defined(BOTAN_HAS_OPENSSL) + #include <botan/internal/openssl.h> #endif namespace Botan { @@ -150,9 +156,57 @@ bool ECDSA_Verification_Operation::verify(const byte msg[], size_t msg_len, return (v == r); } -BOTAN_REGISTER_PK_SIGNATURE_OP("ECDSA", ECDSA_Signature_Operation); -BOTAN_REGISTER_PK_VERIFY_OP("ECDSA", ECDSA_Verification_Operation); - } +std::unique_ptr<PK_Ops::Verification> +ECDSA_PublicKey::create_verification_op(const std::string& params, + const std::string& provider) const + { +#if defined(BOTAN_HAS_OPENSSL) + if(provider == "openssl" || provider.empty()) + { + try + { + return make_openssl_ecdsa_ver_op(*this, params); + } + catch(Lookup_Error& e) + { + if(provider == "openssl") + throw; + } + } +#endif + + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Verification>(new ECDSA_Verification_Operation(*this, params)); + + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::Signature> +ECDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { +#if defined(BOTAN_HAS_OPENSSL) + if(provider == "openssl" || provider.empty()) + { + try + { + return make_openssl_ecdsa_sig_op(*this, params); + } + catch(Lookup_Error& e) + { + if(provider == "openssl") + throw; + } + } +#endif + + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Signature>(new ECDSA_Signature_Operation(*this, params)); + + throw Provider_Not_Found(algo_name(), provider); + } + } diff --git a/src/lib/pubkey/ecdsa/ecdsa.h b/src/lib/pubkey/ecdsa/ecdsa.h index eed09afe6..d9dcacd06 100644 --- a/src/lib/pubkey/ecdsa/ecdsa.h +++ b/src/lib/pubkey/ecdsa/ecdsa.h @@ -53,6 +53,9 @@ class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey size_t message_part_size() const override { return domain().get_order().bytes(); } + std::unique_ptr<PK_Ops::Verification> + create_verification_op(const std::string& params, + const std::string& provider) const override; protected: ECDSA_PublicKey() {} }; @@ -86,6 +89,11 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey, EC_PrivateKey(rng, domain, x) {} bool check_key(RandomNumberGenerator& rng, bool) const override; + + std::unique_ptr<PK_Ops::Signature> + create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; }; } diff --git a/src/lib/pubkey/ecgdsa/ecgdsa.cpp b/src/lib/pubkey/ecgdsa/ecgdsa.cpp index 30ea32817..136f2159a 100644 --- a/src/lib/pubkey/ecgdsa/ecgdsa.cpp +++ b/src/lib/pubkey/ecgdsa/ecgdsa.cpp @@ -5,9 +5,10 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/ecgdsa.h> #include <botan/keypair.h> +#include <botan/reducer.h> +#include <botan/internal/pk_ops_impl.h> namespace Botan { @@ -137,9 +138,25 @@ bool ECGDSA_Verification_Operation::verify(const byte msg[], size_t msg_len, return (v == r); } -BOTAN_REGISTER_PK_SIGNATURE_OP("ECGDSA", ECGDSA_Signature_Operation); -BOTAN_REGISTER_PK_VERIFY_OP("ECGDSA", ECGDSA_Verification_Operation); - } +std::unique_ptr<PK_Ops::Verification> +ECGDSA_PublicKey::create_verification_op(const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Verification>(new ECGDSA_Verification_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::Signature> +ECGDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Signature>(new ECGDSA_Signature_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + } diff --git a/src/lib/pubkey/ecgdsa/ecgdsa.h b/src/lib/pubkey/ecgdsa/ecgdsa.h index 518adeeab..203e8d0a8 100644 --- a/src/lib/pubkey/ecgdsa/ecgdsa.h +++ b/src/lib/pubkey/ecgdsa/ecgdsa.h @@ -51,6 +51,9 @@ class BOTAN_DLL ECGDSA_PublicKey : public virtual EC_PublicKey size_t message_part_size() const override { return domain().get_order().bytes(); } + std::unique_ptr<PK_Ops::Verification> + create_verification_op(const std::string& params, + const std::string& provider) const override; protected: ECGDSA_PublicKey() {} }; @@ -84,6 +87,11 @@ class BOTAN_DLL ECGDSA_PrivateKey : public ECGDSA_PublicKey, EC_PrivateKey(rng, domain, x, true) {} bool check_key(RandomNumberGenerator& rng, bool) const override; + + std::unique_ptr<PK_Ops::Signature> + create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; }; } diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp index d44d14803..ba7140bd0 100644 --- a/src/lib/pubkey/ecies/ecies.cpp +++ b/src/lib/pubkey/ecies/ecies.cpp @@ -10,7 +10,7 @@ #include <botan/cipher_mode.h> #include <botan/internal/ct_utils.h> -#include <botan/internal/pk_utils.h> +#include <botan/internal/pk_ops_impl.h> namespace Botan { @@ -45,6 +45,11 @@ class ECIES_PrivateKey : public EC_PrivateKey, public PK_Key_Agreement_Key return m_key.max_input_bits(); } + std::unique_ptr<PK_Ops::Key_Agreement> + create_key_agreement_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + private: ECDH_PrivateKey m_key; }; @@ -55,9 +60,7 @@ class ECIES_PrivateKey : public EC_PrivateKey, public PK_Key_Agreement_Key class ECIES_ECDH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF { public: - typedef ECIES_PrivateKey Key_Type; - - ECIES_ECDH_KA_Operation(const ECIES_PrivateKey& private_key, const std::string&) : + ECIES_ECDH_KA_Operation(const ECIES_PrivateKey& private_key) : PK_Ops::Key_Agreement_with_KDF("Raw"), m_key(private_key) { @@ -76,6 +79,14 @@ class ECIES_ECDH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF ECIES_PrivateKey m_key; }; +std::unique_ptr<PK_Ops::Key_Agreement> +ECIES_PrivateKey::create_key_agreement_op(RandomNumberGenerator& /*rng*/, + const std::string& /*params*/, + const std::string& /*provider*/) const + { + return std::unique_ptr<PK_Ops::Key_Agreement>(new ECIES_ECDH_KA_Operation(*this)); + } + /** * Creates a PK_Key_Agreement instance for the given key and ecies_params * Returns either ECIES_ECDH_KA_Operation or the default implementation for the given key, @@ -85,8 +96,10 @@ class ECIES_ECDH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF * @param for_encryption disable cofactor mode if the secret will be used for encryption * (according to ISO 18033 cofactor mode is only used during decryption) */ -PK_Key_Agreement create_key_agreement(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, - bool for_encryption) +PK_Key_Agreement create_key_agreement(const PK_Key_Agreement_Key& private_key, + const ECIES_KA_Params& ecies_params, + bool for_encryption, + RandomNumberGenerator& rng) { const ECDH_PrivateKey* ecdh_key = dynamic_cast<const ECDH_PrivateKey*>(&private_key); @@ -103,18 +116,18 @@ PK_Key_Agreement create_key_agreement(const PK_Key_Agreement_Key& private_key, c if(ecdh_key && (for_encryption || !ecies_params.cofactor_mode())) { // ECDH_KA_Operation uses cofactor mode: use own key agreement method if cofactor should not be used. - return PK_Key_Agreement(ECIES_PrivateKey(*ecdh_key), "Raw"); + return PK_Key_Agreement(ECIES_PrivateKey(*ecdh_key), rng, "Raw"); } - return PK_Key_Agreement(private_key, "Raw"); // use default implementation + return PK_Key_Agreement(private_key, rng, "Raw"); // use default implementation } } -BOTAN_REGISTER_PK_KEY_AGREE_OP("ECIES", ECIES_ECDH_KA_Operation); - -ECIES_KA_Operation::ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, - bool for_encryption) : - m_ka(create_key_agreement(private_key, ecies_params, for_encryption)), +ECIES_KA_Operation::ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, + const ECIES_KA_Params& ecies_params, + bool for_encryption, + RandomNumberGenerator& rng) : + m_ka(create_key_agreement(private_key, ecies_params, for_encryption, rng)), m_params(ecies_params) { } @@ -231,8 +244,10 @@ std::unique_ptr<Cipher_Mode> ECIES_System_Params::create_cipher(Botan::Cipher_Di /* * ECIES_Encryptor Constructor */ -ECIES_Encryptor::ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params) : - m_ka(private_key, ecies_params, true), +ECIES_Encryptor::ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, + const ECIES_System_Params& ecies_params, + RandomNumberGenerator& rng) : + m_ka(private_key, ecies_params, true, rng), m_params(ecies_params), m_eph_public_key_bin(private_key.public_value()), // returns the uncompressed public key, see conversion below m_iv(), @@ -252,7 +267,7 @@ ECIES_Encryptor::ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const * ECIES_Encryptor Constructor */ ECIES_Encryptor::ECIES_Encryptor(RandomNumberGenerator& rng, const ECIES_System_Params& ecies_params) : - ECIES_Encryptor(ECDH_PrivateKey(rng, ecies_params.domain()), ecies_params) + ECIES_Encryptor(ECDH_PrivateKey(rng, ecies_params.domain()), ecies_params, rng) { } @@ -302,8 +317,10 @@ std::vector<byte> ECIES_Encryptor::enc(const byte data[], size_t length, RandomN } -ECIES_Decryptor::ECIES_Decryptor(const PK_Key_Agreement_Key& key, const ECIES_System_Params& ecies_params) : - m_ka(key, ecies_params, false), +ECIES_Decryptor::ECIES_Decryptor(const PK_Key_Agreement_Key& key, + const ECIES_System_Params& ecies_params, + RandomNumberGenerator& rng) : + m_ka(key, ecies_params, false, rng), m_params(ecies_params), m_iv(), m_label() diff --git a/src/lib/pubkey/ecies/ecies.h b/src/lib/pubkey/ecies/ecies.h index 0bc0bf76e..6b9eba31d 100644 --- a/src/lib/pubkey/ecies/ecies.h +++ b/src/lib/pubkey/ecies/ecies.h @@ -184,8 +184,10 @@ class BOTAN_DLL ECIES_KA_Operation * @param for_encryption disable cofactor mode if the secret will be used for encryption * (according to ISO 18033 cofactor mode is only used during decryption) */ - ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, - bool for_encryption); + ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, + const ECIES_KA_Params& ecies_params, + bool for_encryption, + RandomNumberGenerator& rng); /** * Performs a key agreement with the provided keys and derives the secret from the result @@ -211,7 +213,9 @@ class BOTAN_DLL ECIES_Encryptor : public PK_Encryptor * @param private_key the (ephemeral) private key which is used for the key agreement * @param ecies_params settings for ecies */ - ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params); + ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, + const ECIES_System_Params& ecies_params, + RandomNumberGenerator& rng); /** * Creates an ephemeral private key which is used for the key agreement @@ -265,7 +269,9 @@ class BOTAN_DLL ECIES_Decryptor : public PK_Decryptor * @param private_key the private key which is used for the key agreement * @param ecies_params settings for ecies */ - ECIES_Decryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params); + ECIES_Decryptor(const PK_Key_Agreement_Key& private_key, + const ECIES_System_Params& ecies_params, + RandomNumberGenerator& rng); /// Set the initialization vector for the data encryption method inline void set_initialization_vector(const InitializationVector& iv) diff --git a/src/lib/pubkey/ecies/info.txt b/src/lib/pubkey/ecies/info.txt index 12776f8c2..fb35e7b97 100644 --- a/src/lib/pubkey/ecies/info.txt +++ b/src/lib/pubkey/ecies/info.txt @@ -5,4 +5,4 @@ kdf mac ecdh modes -</requires>
\ No newline at end of file +</requires> diff --git a/src/lib/pubkey/eckcdsa/eckcdsa.cpp b/src/lib/pubkey/eckcdsa/eckcdsa.cpp index 5ca89675c..5375d047a 100644 --- a/src/lib/pubkey/eckcdsa/eckcdsa.cpp +++ b/src/lib/pubkey/eckcdsa/eckcdsa.cpp @@ -5,9 +5,10 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/eckcdsa.h> +#include <botan/internal/pk_ops_impl.h> #include <botan/keypair.h> +#include <botan/reducer.h> #include <botan/emsa.h> #include <botan/hash.h> @@ -192,9 +193,25 @@ bool ECKCDSA_Verification_Operation::verify(const byte msg[], size_t, return (v == r); } -BOTAN_REGISTER_PK_SIGNATURE_OP("ECKCDSA", ECKCDSA_Signature_Operation); -BOTAN_REGISTER_PK_VERIFY_OP("ECKCDSA", ECKCDSA_Verification_Operation); - } +std::unique_ptr<PK_Ops::Verification> +ECKCDSA_PublicKey::create_verification_op(const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Verification>(new ECKCDSA_Verification_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::Signature> +ECKCDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Signature>(new ECKCDSA_Signature_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + } diff --git a/src/lib/pubkey/eckcdsa/eckcdsa.h b/src/lib/pubkey/eckcdsa/eckcdsa.h index b85c4025e..09ee34ed5 100644 --- a/src/lib/pubkey/eckcdsa/eckcdsa.h +++ b/src/lib/pubkey/eckcdsa/eckcdsa.h @@ -51,6 +51,9 @@ class BOTAN_DLL ECKCDSA_PublicKey : public virtual EC_PublicKey size_t message_part_size() const override { return domain().get_order().bytes(); } + std::unique_ptr<PK_Ops::Verification> + create_verification_op(const std::string& params, + const std::string& provider) const override; protected: ECKCDSA_PublicKey() {} }; @@ -84,6 +87,11 @@ class BOTAN_DLL ECKCDSA_PrivateKey : public ECKCDSA_PublicKey, EC_PrivateKey(rng, domain, x, true) {} bool check_key(RandomNumberGenerator& rng, bool) const override; + + std::unique_ptr<PK_Ops::Signature> + create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; }; } diff --git a/src/lib/pubkey/elgamal/elgamal.cpp b/src/lib/pubkey/elgamal/elgamal.cpp index 37dfe89cf..046c2c3f6 100644 --- a/src/lib/pubkey/elgamal/elgamal.cpp +++ b/src/lib/pubkey/elgamal/elgamal.cpp @@ -5,8 +5,8 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/elgamal.h> +#include <botan/internal/pk_ops_impl.h> #include <botan/keypair.h> #include <botan/reducer.h> #include <botan/blinding.h> @@ -134,7 +134,9 @@ class ElGamal_Decryption_Operation : public PK_Ops::Decryption_with_EME size_t max_raw_input_bits() const override { return m_mod_p.get_modulus().bits() - 1; } - ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key, const std::string& eme); + ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key, + const std::string& eme, + RandomNumberGenerator& rng); secure_vector<byte> raw_decrypt(const byte msg[], size_t msg_len) override; private: @@ -144,13 +146,15 @@ class ElGamal_Decryption_Operation : public PK_Ops::Decryption_with_EME }; ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key, - const std::string& eme) : + const std::string& eme, + RandomNumberGenerator& rng) : PK_Ops::Decryption_with_EME(eme), m_powermod_x_p(Fixed_Exponent_Power_Mod(key.get_x(), key.group_p())), m_mod_p(Modular_Reducer(key.group_p())), m_blinder(key.group_p(), - [](const BigInt& k) { return k; }, - [this](const BigInt& k) { return m_powermod_x_p(k); }) + rng, + [](const BigInt& k) { return k; }, + [this](const BigInt& k) { return m_powermod_x_p(k); }) { } @@ -177,9 +181,26 @@ ElGamal_Decryption_Operation::raw_decrypt(const byte msg[], size_t msg_len) return BigInt::encode_1363(m_blinder.unblind(r), p_bytes); } -BOTAN_REGISTER_PK_ENCRYPTION_OP("ElGamal", ElGamal_Encryption_Operation); -BOTAN_REGISTER_PK_DECRYPTION_OP("ElGamal", ElGamal_Decryption_Operation); - } +std::unique_ptr<PK_Ops::Encryption> +ElGamal_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Encryption>(new ElGamal_Encryption_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::Decryption> +ElGamal_PrivateKey::create_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Decryption>(new ElGamal_Decryption_Operation(*this, 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 9f287158d..8ca4facc2 100644 --- a/src/lib/pubkey/elgamal/elgamal.h +++ b/src/lib/pubkey/elgamal/elgamal.h @@ -29,6 +29,12 @@ class BOTAN_DLL ElGamal_PublicKey : public virtual DL_Scheme_PublicKey {} ElGamal_PublicKey(const DL_Group& group, const BigInt& y); + + std::unique_ptr<PK_Ops::Encryption> + create_encryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + protected: ElGamal_PublicKey() {} }; @@ -49,6 +55,11 @@ class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey, ElGamal_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& priv_key = 0); + + std::unique_ptr<PK_Ops::Decryption> + create_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; }; } diff --git a/src/lib/pubkey/gost_3410/gost_3410.cpp b/src/lib/pubkey/gost_3410/gost_3410.cpp index 51db47619..7fde29bc5 100644 --- a/src/lib/pubkey/gost_3410/gost_3410.cpp +++ b/src/lib/pubkey/gost_3410/gost_3410.cpp @@ -7,8 +7,9 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/gost_3410.h> +#include <botan/internal/pk_ops_impl.h> +#include <botan/reducer.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> @@ -212,7 +213,23 @@ bool GOST_3410_Verification_Operation::verify(const byte msg[], size_t msg_len, } -BOTAN_REGISTER_PK_SIGNATURE_OP("GOST-34.10", GOST_3410_Signature_Operation); -BOTAN_REGISTER_PK_VERIFY_OP("GOST-34.10", GOST_3410_Verification_Operation); +std::unique_ptr<PK_Ops::Verification> +GOST_3410_PublicKey::create_verification_op(const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Verification>(new GOST_3410_Verification_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::Signature> +GOST_3410_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Signature>(new GOST_3410_Signature_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } } diff --git a/src/lib/pubkey/gost_3410/gost_3410.h b/src/lib/pubkey/gost_3410/gost_3410.h index 62a627c37..cca811896 100644 --- a/src/lib/pubkey/gost_3410/gost_3410.h +++ b/src/lib/pubkey/gost_3410/gost_3410.h @@ -59,6 +59,10 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey size_t message_part_size() const override { return domain().get_order().bytes(); } + std::unique_ptr<PK_Ops::Verification> + create_verification_op(const std::string& params, + const std::string& provider) const override; + protected: GOST_3410_PublicKey() {} }; @@ -88,6 +92,11 @@ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey, AlgorithmIdentifier pkcs8_algorithm_identifier() const override { return EC_PublicKey::algorithm_identifier(); } + + std::unique_ptr<PK_Ops::Signature> + create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; }; } diff --git a/src/lib/pubkey/info.txt b/src/lib/pubkey/info.txt index 10eb12567..0e799f372 100644 --- a/src/lib/pubkey/info.txt +++ b/src/lib/pubkey/info.txt @@ -14,16 +14,16 @@ x509_key.cpp <header:public> blinding.h pk_keys.h -pk_ops.h +pk_ops_fwd.h pkcs8.h pubkey.h -x509_key.h workfactor.h +x509_key.h </header:public> <header:internal> pk_algs.h -pk_utils.h +pk_ops.h pk_ops_impl.h </header:internal> diff --git a/src/lib/pubkey/keypair/keypair.cpp b/src/lib/pubkey/keypair/keypair.cpp index 0f5a48541..2efd40b6e 100644 --- a/src/lib/pubkey/keypair/keypair.cpp +++ b/src/lib/pubkey/keypair/keypair.cpp @@ -19,8 +19,8 @@ bool encryption_consistency_check(RandomNumberGenerator& rng, const Private_Key& key, const std::string& padding) { - PK_Encryptor_EME encryptor(key, padding); - PK_Decryptor_EME decryptor(key, padding); + PK_Encryptor_EME encryptor(key, rng, padding); + PK_Decryptor_EME decryptor(key, rng, padding); /* Weird corner case, if the key is too small to encrypt anything at @@ -48,7 +48,7 @@ bool signature_consistency_check(RandomNumberGenerator& rng, const Private_Key& key, const std::string& padding) { - PK_Signer signer(key, padding); + PK_Signer signer(key, rng, padding); PK_Verifier verifier(key, padding); std::vector<byte> message = unlock(rng.random_vec(16)); diff --git a/src/lib/pubkey/mce/mce_internal.h b/src/lib/pubkey/mce/mce_internal.h index d35479080..526552944 100644 --- a/src/lib/pubkey/mce/mce_internal.h +++ b/src/lib/pubkey/mce/mce_internal.h @@ -14,7 +14,7 @@ #include <botan/secmem.h> #include <botan/types.h> -#include <botan/pk_ops.h> +#include <botan/internal/pk_ops.h> #include <botan/mceliece.h> namespace Botan { diff --git a/src/lib/pubkey/mce/mceliece.h b/src/lib/pubkey/mce/mceliece.h index 311f0f253..c8b2606c5 100644 --- a/src/lib/pubkey/mce/mceliece.h +++ b/src/lib/pubkey/mce/mceliece.h @@ -58,6 +58,11 @@ class BOTAN_DLL McEliece_PublicKey : public virtual Public_Key bool operator==(const McEliece_PublicKey& other) const; bool operator!=(const McEliece_PublicKey& other) const { return !(*this == other); } + std::unique_ptr<PK_Ops::KEM_Encryption> + create_kem_encryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + protected: McEliece_PublicKey() : m_t(0), m_code_length(0) {} @@ -115,6 +120,10 @@ class BOTAN_DLL McEliece_PrivateKey : public virtual McEliece_PublicKey, bool operator!=(const McEliece_PrivateKey& other) const { return !(*this == other); } + std::unique_ptr<PK_Ops::KEM_Decryption> + create_kem_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; private: polyn_gf2m m_g; std::vector<polyn_gf2m> m_sqrtmod; diff --git a/src/lib/pubkey/mce/mceliece_key.cpp b/src/lib/pubkey/mce/mceliece_key.cpp index 455d1f381..c65322348 100644 --- a/src/lib/pubkey/mce/mceliece_key.cpp +++ b/src/lib/pubkey/mce/mceliece_key.cpp @@ -15,7 +15,6 @@ #include <botan/internal/bit_ops.h> #include <botan/internal/code_based_util.h> #include <botan/internal/pk_ops_impl.h> -#include <botan/internal/pk_utils.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> @@ -352,11 +351,28 @@ class MCE_KEM_Decryptor : public PK_Ops::KEM_Decryption_with_KDF const McEliece_PrivateKey& m_key; }; -BOTAN_REGISTER_PK_KEM_ENCRYPTION_OP("McEliece", MCE_KEM_Encryptor); -BOTAN_REGISTER_PK_KEM_DECRYPTION_OP("McEliece", MCE_KEM_Decryptor); - } +std::unique_ptr<PK_Ops::KEM_Encryption> +McEliece_PublicKey::create_kem_encryption_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::KEM_Encryption>(new MCE_KEM_Encryptor(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::KEM_Decryption> +McEliece_PrivateKey::create_kem_decryption_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::KEM_Decryption>(new MCE_KEM_Decryptor(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } + } diff --git a/src/lib/pubkey/mceies/mceies.cpp b/src/lib/pubkey/mceies/mceies.cpp index 95042e529..253e9ddee 100644 --- a/src/lib/pubkey/mceies/mceies.cpp +++ b/src/lib/pubkey/mceies/mceies.cpp @@ -36,7 +36,7 @@ mceies_encrypt(const McEliece_PublicKey& pubkey, RandomNumberGenerator& rng, const std::string& algo) { - PK_KEM_Encryptor kem_op(pubkey, "KDF1(SHA-512)"); + PK_KEM_Encryptor kem_op(pubkey, rng, "KDF1(SHA-512)"); secure_vector<byte> mce_ciphertext, mce_key; kem_op.encrypt(mce_ciphertext, mce_key, 64, rng); @@ -74,7 +74,8 @@ mceies_decrypt(const McEliece_PrivateKey& privkey, { try { - PK_KEM_Decryptor kem_op(privkey, "KDF1(SHA-512)"); + Null_RNG null_rng; + PK_KEM_Decryptor kem_op(privkey, null_rng, "KDF1(SHA-512)"); const size_t mce_code_bytes = (privkey.get_code_length() + 7) / 8; diff --git a/src/lib/pubkey/pk_keys.cpp b/src/lib/pubkey/pk_keys.cpp index 9597ed08d..2c846d623 100644 --- a/src/lib/pubkey/pk_keys.cpp +++ b/src/lib/pubkey/pk_keys.cpp @@ -6,6 +6,7 @@ */ #include <botan/pk_keys.h> +#include <botan/internal/pk_ops.h> #include <botan/der_enc.h> #include <botan/oids.h> #include <botan/hash.h> @@ -78,4 +79,59 @@ std::string Private_Key::fingerprint(const std::string& alg) const return formatted_print; } +std::unique_ptr<PK_Ops::Encryption> +Public_Key::create_encryption_op(RandomNumberGenerator& /*rng*/, + const std::string& /*params*/, + const std::string& /*provider*/) const + { + throw Lookup_Error(algo_name() + " does not support encryption"); + } + +std::unique_ptr<PK_Ops::KEM_Encryption> +Public_Key::create_kem_encryption_op(RandomNumberGenerator& /*rng*/, + const std::string& /*params*/, + const std::string& /*provider*/) const + { + throw Lookup_Error(algo_name() + " does not support KEM encryption"); + } + +std::unique_ptr<PK_Ops::Verification> +Public_Key::create_verification_op(const std::string& /*params*/, + const std::string& /*provider*/) const + { + throw Lookup_Error(algo_name() + " does not support verification"); + } + +std::unique_ptr<PK_Ops::Decryption> +Private_Key::create_decryption_op(RandomNumberGenerator& /*rng*/, + const std::string& /*params*/, + const std::string& /*provider*/) const + { + throw Lookup_Error(algo_name() + " does not support decryption"); + } + +std::unique_ptr<PK_Ops::KEM_Decryption> +Private_Key::create_kem_decryption_op(RandomNumberGenerator& /*rng*/, + const std::string& /*params*/, + const std::string& /*provider*/) const + { + throw Lookup_Error(algo_name() + " does not support KEM decryption"); + } + +std::unique_ptr<PK_Ops::Signature> +Private_Key::create_signature_op(RandomNumberGenerator& /*rng*/, + const std::string& /*params*/, + const std::string& /*provider*/) const + { + throw Lookup_Error(algo_name() + " does not support signatures"); + } + +std::unique_ptr<PK_Ops::Key_Agreement> +Private_Key::create_key_agreement_op(RandomNumberGenerator& /*rng*/, + const std::string& /*params*/, + const std::string& /*provider*/) const + { + throw Lookup_Error(algo_name() + " does not support key agreement"); + } + } diff --git a/src/lib/pubkey/pk_keys.h b/src/lib/pubkey/pk_keys.h index 1a3047a57..5521f5b2c 100644 --- a/src/lib/pubkey/pk_keys.h +++ b/src/lib/pubkey/pk_keys.h @@ -15,12 +15,28 @@ namespace Botan { +class RandomNumberGenerator; + +namespace PK_Ops { + +class Encryption; +class Decryption; +class Key_Agreement; +class KEM_Encryption; +class KEM_Decryption; +class Verification; +class Signature; + +} + /** * Public Key Base Class. */ class BOTAN_DLL Public_Key { public: + virtual ~Public_Key() {} + /** * Get the name of the underlying public key scheme. * @return name of the public key scheme @@ -82,7 +98,48 @@ class BOTAN_DLL Public_Key */ virtual std::vector<byte> x509_subject_public_key() const = 0; - virtual ~Public_Key() {} + // Internal or non-public declarations follow + + /** + * This is an internal library function exposed on key types. + * In almost all cases applications should use wrappers in pubkey.h + * + * Return an encryption operation for this key/params or throw + * + * @param rng a random number generator. The PK_Op may maintain a + * reference to the RNG and use it many times. The rng must outlive + * any operations which reference it. + */ + virtual std::unique_ptr<PK_Ops::Encryption> + create_encryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const; + + /** + * This is an internal library function exposed on key types. + * In almost all cases applications should use wrappers in pubkey.h + * + * Return a KEM encryption operation for this key/params or throw + * + * @param rng a random number generator. The PK_Op may maintain a + * reference to the RNG and use it many times. The rng must outlive + * any operations which reference it. + */ + virtual std::unique_ptr<PK_Ops::KEM_Encryption> + create_kem_encryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const; + + /** + * This is an internal library function exposed on key types. + * In almost all cases applications should use wrappers in pubkey.h + * + * Return a verification operation for this key/params or throw + */ + virtual std::unique_ptr<PK_Ops::Verification> + create_verification_op(const std::string& params, + const std::string& provider) const; + protected: /** * Self-test after loading a key @@ -109,10 +166,73 @@ class BOTAN_DLL Private_Key : public virtual Public_Key virtual AlgorithmIdentifier pkcs8_algorithm_identifier() const { return algorithm_identifier(); } + // Internal or non-public declarations follow + /** * @return Hash of the PKCS #8 encoding for this key object */ std::string fingerprint(const std::string& alg = "SHA") const; + + /** + * This is an internal library function exposed on key types. + * In almost all cases applications should use wrappers in pubkey.h + * + * Return an decryption operation for this key/params or throw + * + * @param rng a random number generator. The PK_Op may maintain a + * reference to the RNG and use it many times. The rng must outlive + * any operations which reference it. + */ + virtual std::unique_ptr<PK_Ops::Decryption> + create_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const; + + /** + * This is an internal library function exposed on key types. + * In almost all cases applications should use wrappers in pubkey.h + * + * Return a KEM decryption operation for this key/params or throw + * + * @param rng a random number generator. The PK_Op may maintain a + * reference to the RNG and use it many times. The rng must outlive + * any operations which reference it. + */ + virtual std::unique_ptr<PK_Ops::KEM_Decryption> + create_kem_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const; + + /** + * This is an internal library function exposed on key types. + * In almost all cases applications should use wrappers in pubkey.h + * + * Return a signature operation for this key/params or throw + * + * @param rng a random number generator. The PK_Op may maintain a + * reference to the RNG and use it many times. The rng must outlive + * any operations which reference it. + */ + virtual std::unique_ptr<PK_Ops::Signature> + create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const; + + /** + * This is an internal library function exposed on key types. + * In almost all cases applications should use wrappers in pubkey.h + * + * Return a key agreement operation for this key/params or throw + * + * @param rng a random number generator. The PK_Op may maintain a + * reference to the RNG and use it many times. The rng must outlive + * any operations which reference it. + */ + virtual std::unique_ptr<PK_Ops::Key_Agreement> + create_key_agreement_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const; + protected: /** * Self-test after loading a key @@ -142,7 +262,8 @@ class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key }; /* -* Typedefs +* Old compat typedefs +* TODO: remove these? */ typedef PK_Key_Agreement_Key PK_KA_Key; typedef Public_Key X509_PublicKey; diff --git a/src/lib/pubkey/pk_ops_fwd.h b/src/lib/pubkey/pk_ops_fwd.h new file mode 100644 index 000000000..16c2124fb --- /dev/null +++ b/src/lib/pubkey/pk_ops_fwd.h @@ -0,0 +1,27 @@ +/* +* PK Operation Types Forward Decls +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_PK_OPERATIONS_FWD_H__ +#define BOTAN_PK_OPERATIONS_FWD_H__ + +namespace Botan { + +namespace PK_Ops { + +class Encryption; +class Decryption; +class Verification; +class Signature; +class Key_Agreement; +class KEM_Encryption; +class KEM_Decryption; + +} + +} + +#endif diff --git a/src/lib/pubkey/pk_ops_impl.h b/src/lib/pubkey/pk_ops_impl.h index 9d02de5e5..5fe5623e7 100644 --- a/src/lib/pubkey/pk_ops_impl.h +++ b/src/lib/pubkey/pk_ops_impl.h @@ -7,7 +7,7 @@ #ifndef BOTAN_PK_OPERATION_IMPL_H__ #define BOTAN_PK_OPERATION_IMPL_H__ -#include <botan/pk_ops.h> +#include <botan/internal/pk_ops.h> namespace Botan { diff --git a/src/lib/pubkey/pk_utils.h b/src/lib/pubkey/pk_utils.h deleted file mode 100644 index 04a0bf5ca..000000000 --- a/src/lib/pubkey/pk_utils.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Public Key Algos Utility Header -* (C) 2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_PK_UTILS_H__ -#define BOTAN_PK_UTILS_H__ - -#include <botan/internal/algo_registry.h> -#include <botan/internal/pk_ops_impl.h> -#include <botan/numthry.h> -#include <botan/reducer.h> -#include <algorithm> - -namespace Botan { - -template<typename OP, typename T> -OP* make_pk_op(const typename T::Spec& spec) - { - if(auto* key = dynamic_cast<const typename T::Key_Type*>(&spec.key())) - return new T(*key, spec.padding()); - return nullptr; - } - -#define BOTAN_REGISTER_PK_OP(T, NAME, TYPE) BOTAN_REGISTER_NAMED_T(T, NAME, TYPE, (make_pk_op<T, TYPE>)) - -#define BOTAN_REGISTER_PK_ENCRYPTION_OP(NAME, TYPE) BOTAN_REGISTER_PK_OP(PK_Ops::Encryption, NAME, TYPE) -#define BOTAN_REGISTER_PK_DECRYPTION_OP(NAME, TYPE) BOTAN_REGISTER_PK_OP(PK_Ops::Decryption, NAME, TYPE) -#define BOTAN_REGISTER_PK_SIGNATURE_OP(NAME, TYPE) BOTAN_REGISTER_PK_OP(PK_Ops::Signature, NAME, TYPE) -#define BOTAN_REGISTER_PK_VERIFY_OP(NAME, TYPE) BOTAN_REGISTER_PK_OP(PK_Ops::Verification, NAME, TYPE) -#define BOTAN_REGISTER_PK_KEY_AGREE_OP(NAME, TYPE) BOTAN_REGISTER_PK_OP(PK_Ops::Key_Agreement, NAME, TYPE) - -#define BOTAN_REGISTER_PK_KEM_ENCRYPTION_OP(NAME, TYPE) BOTAN_REGISTER_PK_OP(PK_Ops::KEM_Encryption, NAME, TYPE) -#define BOTAN_REGISTER_PK_KEM_DECRYPTION_OP(NAME, TYPE) BOTAN_REGISTER_PK_OP(PK_Ops::KEM_Decryption, NAME, TYPE) - -} - -#endif diff --git a/src/lib/pubkey/pubkey.cpp b/src/lib/pubkey/pubkey.cpp index 8b24ee983..bb76bf68e 100644 --- a/src/lib/pubkey/pubkey.cpp +++ b/src/lib/pubkey/pubkey.cpp @@ -8,29 +8,11 @@ #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/bigint.h> -#include <botan/internal/algo_registry.h> +#include <botan/internal/pk_ops.h> #include <botan/internal/ct_utils.h> namespace Botan { -namespace { - -template<typename T, typename Key> -T* get_pk_op(const std::string& what, const Key& key, const std::string& pad, - const std::string& provider = "") - { - if(T* p = Algo_Registry<T>::global_registry().make(typename T::Spec(key, pad), provider)) - return p; - - const std::string err = what + " with " + key.algo_name() + "/" + pad + " not supported"; - if(!provider.empty()) - throw Lookup_Error(err + " with provider " + provider); - else - throw Lookup_Error(err); - } - -} - secure_vector<byte> PK_Decryptor::decrypt(const byte in[], size_t length) const { byte valid_mask = 0; @@ -54,8 +36,6 @@ PK_Decryptor::decrypt_or_random(const byte in[], { const secure_vector<byte> fake_pms = rng.random_vec(expected_pt_len); - //CT::poison(in, length); - byte valid_mask = 0; secure_vector<byte> decoded = do_decrypt(valid_mask, in, length); @@ -90,9 +70,6 @@ PK_Decryptor::decrypt_or_random(const byte in[], /*from1*/fake_pms.data(), expected_pt_len); - //CT::unpoison(in, length); - //CT::unpoison(decoded.data(), decoded.size()); - return decoded; } @@ -107,12 +84,17 @@ PK_Decryptor::decrypt_or_random(const byte in[], } PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key, + RandomNumberGenerator& rng, const std::string& padding, const std::string& provider) { - m_op.reset(get_pk_op<PK_Ops::Encryption>("Encryption", key, padding, provider)); + m_op = key.create_encryption_op(rng, padding, provider); + if(!m_op) + throw Invalid_Argument("Key type " + key.algo_name() + " does not support encryption"); } +PK_Encryptor_EME::~PK_Encryptor_EME() { /* for unique_ptr */ } + std::vector<byte> PK_Encryptor_EME::enc(const byte in[], size_t length, RandomNumberGenerator& rng) const { @@ -124,12 +106,18 @@ size_t PK_Encryptor_EME::maximum_input_size() const return m_op->max_input_bits() / 8; } -PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key, const std::string& padding, +PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& padding, const std::string& provider) { - m_op.reset(get_pk_op<PK_Ops::Decryption>("Decryption", key, padding, provider)); + m_op = key.create_decryption_op(rng, padding, provider); + if(!m_op) + throw Invalid_Argument("Key type " + key.algo_name() + " does not support decryption"); } +PK_Decryptor_EME::~PK_Decryptor_EME() { /* for unique_ptr */ } + secure_vector<byte> PK_Decryptor_EME::do_decrypt(byte& valid_mask, const byte in[], size_t in_len) const { @@ -137,12 +125,17 @@ secure_vector<byte> PK_Decryptor_EME::do_decrypt(byte& valid_mask, } PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key, + RandomNumberGenerator& rng, const std::string& param, const std::string& provider) { - m_op.reset(get_pk_op<PK_Ops::KEM_Encryption>("KEM", key, param, provider)); + m_op = key.create_kem_encryption_op(rng, param, provider); + if(!m_op) + throw Invalid_Argument("Key type " + key.algo_name() + " does not support KEM encryption"); } +PK_KEM_Encryptor::~PK_KEM_Encryptor() { /* for unique_ptr */ } + void PK_KEM_Encryptor::encrypt(secure_vector<byte>& out_encapsulated_key, secure_vector<byte>& out_shared_key, size_t desired_shared_key_len, @@ -159,12 +152,17 @@ void PK_KEM_Encryptor::encrypt(secure_vector<byte>& out_encapsulated_key, } PK_KEM_Decryptor::PK_KEM_Decryptor(const Private_Key& key, + RandomNumberGenerator& rng, const std::string& param, const std::string& provider) { - m_op.reset(get_pk_op<PK_Ops::KEM_Decryption>("KEM", key, param, provider)); + m_op = key.create_kem_decryption_op(rng, param, provider); + if(!m_op) + throw Invalid_Argument("Key type " + key.algo_name() + " does not support KEM decryption"); } +PK_KEM_Decryptor::~PK_KEM_Decryptor() { /* for unique_ptr */ } + secure_vector<byte> PK_KEM_Decryptor::decrypt(const byte encap_key[], size_t encap_key_len, size_t desired_shared_key_len, @@ -177,12 +175,30 @@ secure_vector<byte> PK_KEM_Decryptor::decrypt(const byte encap_key[], } PK_Key_Agreement::PK_Key_Agreement(const Private_Key& key, + RandomNumberGenerator& rng, const std::string& kdf, const std::string& provider) { - m_op.reset(get_pk_op<PK_Ops::Key_Agreement>("Key agreement", key, kdf, provider)); + m_op = key.create_key_agreement_op(rng, kdf, provider); + if(!m_op) + throw Invalid_Argument("Key type " + key.algo_name() + " does not support key agreement"); + } + +PK_Key_Agreement::~PK_Key_Agreement() { /* for unique_ptr */ } + +PK_Key_Agreement& PK_Key_Agreement::operator=(PK_Key_Agreement&& other) + { + if(this != &other) + { + m_op = std::move(other.m_op); + } + return (*this); } +PK_Key_Agreement::PK_Key_Agreement(PK_Key_Agreement&& other) : + m_op(std::move(other.m_op)) + {} + SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, const byte in[], size_t in_len, const byte salt[], @@ -234,14 +250,19 @@ std::vector<byte> der_decode_signature(const byte sig[], size_t len, } PK_Signer::PK_Signer(const Private_Key& key, + RandomNumberGenerator& rng, const std::string& emsa, Signature_Format format, const std::string& provider) { - m_op.reset(get_pk_op<PK_Ops::Signature>("Signing", key, emsa, provider)); + m_op = key.create_signature_op(rng, emsa, provider); + if(!m_op) + throw Invalid_Argument("Key type " + key.algo_name() + " does not support signature generation"); m_sig_format = format; } +PK_Signer::~PK_Signer() { /* for unique_ptr */ } + void PK_Signer::update(const byte in[], size_t length) { m_op->update(in, length); @@ -262,14 +283,18 @@ std::vector<byte> PK_Signer::signature(RandomNumberGenerator& rng) } PK_Verifier::PK_Verifier(const Public_Key& key, - const std::string& emsa_name, + const std::string& emsa, Signature_Format format, const std::string& provider) { - m_op.reset(get_pk_op<PK_Ops::Verification>("Verification", key, emsa_name, provider)); + m_op = key.create_verification_op(emsa, provider); + if(!m_op) + throw Invalid_Argument("Key type " + key.algo_name() + " does not support signature verification"); m_sig_format = format; } +PK_Verifier::~PK_Verifier() { /* for unique_ptr */ } + void PK_Verifier::set_input_format(Signature_Format format) { if(m_op->message_parts() == 1 && format != IEEE_1363) diff --git a/src/lib/pubkey/pubkey.h b/src/lib/pubkey/pubkey.h index 26cbb1790..94332c8f0 100644 --- a/src/lib/pubkey/pubkey.h +++ b/src/lib/pubkey/pubkey.h @@ -9,13 +9,18 @@ #define BOTAN_PUBKEY_H__ #include <botan/pk_keys.h> -#include <botan/pk_ops.h> +#include <botan/pk_ops_fwd.h> #include <botan/symkey.h> #include <botan/rng.h> #include <botan/eme.h> #include <botan/emsa.h> #include <botan/kdf.h> +#if defined(BOTAN_HAS_SYSTEM_RNG) + #include <botan/system_rng.h> + #define BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS +#endif + namespace Botan { /** @@ -66,7 +71,6 @@ class BOTAN_DLL PK_Encryptor virtual ~PK_Encryptor() {} PK_Encryptor(const PK_Encryptor&) = delete; - PK_Encryptor& operator=(const PK_Encryptor&) = delete; private: @@ -153,7 +157,7 @@ class BOTAN_DLL PK_Decryptor * messages. Use multiple calls update() to process large messages and * generate the signature by finally calling signature(). */ -class BOTAN_DLL PK_Signer +class BOTAN_DLL PK_Signer final { public: @@ -165,10 +169,33 @@ class BOTAN_DLL PK_Signer * @param format the signature format to use */ PK_Signer(const Private_Key& key, + RandomNumberGenerator& rng, const std::string& emsa, Signature_Format format = IEEE_1363, const std::string& provider = ""); +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + /** + * Construct a PK Signer. + * @param key the key to use inside this signer + * @param emsa the EMSA to use + * An example would be "EMSA1(SHA-224)". + * @param format the signature format to use + */ + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_Signer(const Private_Key& key, + const std::string& emsa, + Signature_Format format = IEEE_1363, + const std::string& provider = "") : + PK_Signer(key, system_rng(), emsa, format, provider) + {} +#endif + + ~PK_Signer(); + + PK_Signer(const PK_Signer&) = delete; + PK_Signer& operator=(const PK_Signer&) = delete; + /** * Sign a message all in one go * @param in the message to sign as a byte array @@ -248,7 +275,7 @@ class BOTAN_DLL PK_Signer * messages. Use multiple calls update() to process large messages and * verify the signature by finally calling check_signature(). */ -class BOTAN_DLL PK_Verifier +class BOTAN_DLL PK_Verifier final { public: /** @@ -262,6 +289,11 @@ class BOTAN_DLL PK_Verifier Signature_Format format = IEEE_1363, const std::string& provider = ""); + ~PK_Verifier(); + + PK_Verifier& operator=(const PK_Verifier&) = delete; + PK_Verifier(const PK_Verifier&) = delete; + /** * Verify a signature. * @param msg the message that the signature belongs to, as a byte array @@ -353,7 +385,7 @@ class BOTAN_DLL PK_Verifier /** * Key used for key agreement */ -class BOTAN_DLL PK_Key_Agreement +class BOTAN_DLL PK_Key_Agreement final { public: @@ -364,9 +396,34 @@ class BOTAN_DLL PK_Key_Agreement * @param provider the algo provider to use (or empty for default) */ PK_Key_Agreement(const Private_Key& key, + RandomNumberGenerator& rng, const std::string& kdf, const std::string& provider = ""); +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + /** + * Construct a PK Key Agreement. + * @param key the key to use + * @param kdf name of the KDF to use (or 'Raw' for no KDF) + * @param provider the algo provider to use (or empty for default) + */ + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_Key_Agreement(const Private_Key& key, + const std::string& kdf, + const std::string& provider = "") : + PK_Key_Agreement(key, system_rng(), kdf, provider) + {} +#endif + + ~PK_Key_Agreement(); + + // For ECIES + PK_Key_Agreement& operator=(PK_Key_Agreement&&); + PK_Key_Agreement(PK_Key_Agreement&&); + + PK_Key_Agreement& operator=(const PK_Key_Agreement&) = delete; + PK_Key_Agreement(const PK_Key_Agreement&) = delete; + /* * Perform Key Agreement Operation * @param key_len the desired key output size @@ -437,19 +494,38 @@ class BOTAN_DLL PK_Key_Agreement * Encryption using a standard message recovery algorithm like RSA or * ElGamal, paired with an encoding scheme like OAEP. */ -class BOTAN_DLL PK_Encryptor_EME : public PK_Encryptor +class BOTAN_DLL PK_Encryptor_EME final : public PK_Encryptor { public: size_t maximum_input_size() const override; /** * Construct an instance. - * @param key the key to use inside the decryptor + * @param key the key to use inside the encryptor * @param padding the message encoding scheme to use (eg "OAEP(SHA-256)") */ PK_Encryptor_EME(const Public_Key& key, + RandomNumberGenerator& rng, const std::string& padding, const std::string& provider = ""); + +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + /** + * Construct an instance. + * @param key the key to use inside the encryptor + * @param padding the message encoding scheme to use (eg "OAEP(SHA-256)") + */ + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_Encryptor_EME(const Public_Key& key, + const std::string& padding, + const std::string& provider = "") : + PK_Encryptor_EME(key, system_rng(), padding, provider) {} +#endif + + ~PK_Encryptor_EME(); + + PK_Encryptor_EME& operator=(const PK_Encryptor_EME&) = delete; + PK_Encryptor_EME(const PK_Encryptor_EME&) = delete; private: std::vector<byte> enc(const byte[], size_t, RandomNumberGenerator& rng) const override; @@ -460,17 +536,37 @@ class BOTAN_DLL PK_Encryptor_EME : public PK_Encryptor /** * Decryption with an MR algorithm and an EME. */ -class BOTAN_DLL PK_Decryptor_EME : public PK_Decryptor +class BOTAN_DLL PK_Decryptor_EME final : public PK_Decryptor { public: /** * Construct an instance. - * @param key the key to use inside the encryptor + * @param key the key to use inside the decryptor * @param eme the EME to use + * @param provider */ PK_Decryptor_EME(const Private_Key& key, + RandomNumberGenerator& rng, const std::string& eme, const std::string& provider = ""); + + +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + /** + * Construct an instance. + * @param key the key to use inside the decryptor + * @param padding the message encoding scheme to use (eg "OAEP(SHA-256)") + */ + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_Decryptor_EME(const Private_Key& key, + const std::string& eme, + const std::string& provider = "") : + PK_Decryptor_EME(key, system_rng(), eme, provider) {} +#endif + + ~PK_Decryptor_EME(); + PK_Decryptor_EME& operator=(const PK_Decryptor_EME&) = delete; + PK_Decryptor_EME(const PK_Decryptor_EME&) = delete; private: secure_vector<byte> do_decrypt(byte& valid_mask, const byte in[], @@ -479,13 +575,27 @@ class BOTAN_DLL PK_Decryptor_EME : public PK_Decryptor std::unique_ptr<PK_Ops::Decryption> m_op; }; -class BOTAN_DLL PK_KEM_Encryptor +class BOTAN_DLL PK_KEM_Encryptor final { public: PK_KEM_Encryptor(const Public_Key& key, + RandomNumberGenerator& rng, const std::string& kem_param = "", const std::string& provider = ""); +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_KEM_Encryptor(const Public_Key& key, + const std::string& kem_param = "", + const std::string& provider = "") : + PK_KEM_Encryptor(key, system_rng(), kem_param, provider) {} +#endif + + ~PK_KEM_Encryptor(); + + PK_KEM_Encryptor& operator=(const PK_KEM_Encryptor&) = delete; + PK_KEM_Encryptor(const PK_KEM_Encryptor&) = delete; + void encrypt(secure_vector<byte>& out_encapsulated_key, secure_vector<byte>& out_shared_key, size_t desired_shared_key_len, @@ -524,13 +634,27 @@ class BOTAN_DLL PK_KEM_Encryptor std::unique_ptr<PK_Ops::KEM_Encryption> m_op; }; -class BOTAN_DLL PK_KEM_Decryptor +class BOTAN_DLL PK_KEM_Decryptor final { public: PK_KEM_Decryptor(const Private_Key& key, + RandomNumberGenerator& rng, const std::string& kem_param = "", const std::string& provider = ""); +#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS) + BOTAN_DEPRECATED("Use constructor taking a RNG object") + PK_KEM_Decryptor(const Private_Key& key, + const std::string& kem_param = "", + const std::string& provider = "") : + PK_KEM_Decryptor(key, system_rng(), kem_param, provider) + {} +#endif + + ~PK_KEM_Decryptor(); + PK_KEM_Decryptor& operator=(const PK_KEM_Decryptor&) = delete; + PK_KEM_Decryptor(const PK_KEM_Decryptor&) = delete; + secure_vector<byte> decrypt(const byte encap_key[], size_t encap_key_len, size_t desired_shared_key_len, diff --git a/src/lib/pubkey/rsa/rsa.cpp b/src/lib/pubkey/rsa/rsa.cpp index 7f72ba210..b40f485e3 100644 --- a/src/lib/pubkey/rsa/rsa.cpp +++ b/src/lib/pubkey/rsa/rsa.cpp @@ -5,8 +5,8 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_utils.h> #include <botan/rsa.h> +#include <botan/internal/pk_ops_impl.h> #include <botan/parsing.h> #include <botan/keypair.h> #include <botan/blinding.h> @@ -16,6 +16,10 @@ #include <botan/ber_dec.h> #include <future> +#if defined(BOTAN_HAS_OPENSSL) + #include <botan/internal/openssl.h> +#endif + namespace Botan { size_t RSA_PublicKey::estimated_strength() const @@ -189,7 +193,7 @@ class RSA_Private_Operation protected: size_t get_max_input_bits() const { return (m_n.bits() - 1); } - explicit RSA_Private_Operation(const RSA_PrivateKey& rsa) : + explicit RSA_Private_Operation(const RSA_PrivateKey& rsa, RandomNumberGenerator& rng) : m_n(rsa.get_n()), m_q(rsa.get_q()), m_c(rsa.get_c()), @@ -198,6 +202,7 @@ class RSA_Private_Operation m_powermod_d2_q(rsa.get_d2(), rsa.get_q()), m_mod_p(rsa.get_p()), m_blinder(m_n, + rng, [this](const BigInt& k) { return m_powermod_e_n(k); }, [this](const BigInt& k) { return inverse_mod(k, m_n); }) { @@ -238,9 +243,9 @@ class RSA_Signature_Operation : public PK_Ops::Signature_with_EMSA, size_t max_input_bits() const override { return get_max_input_bits(); }; - RSA_Signature_Operation(const RSA_PrivateKey& rsa, const std::string& emsa) : + RSA_Signature_Operation(const RSA_PrivateKey& rsa, const std::string& emsa, RandomNumberGenerator& rng) : PK_Ops::Signature_with_EMSA(emsa), - RSA_Private_Operation(rsa) + RSA_Private_Operation(rsa, rng) { } @@ -263,9 +268,9 @@ class RSA_Decryption_Operation : public PK_Ops::Decryption_with_EME, size_t max_raw_input_bits() const override { return get_max_input_bits(); }; - RSA_Decryption_Operation(const RSA_PrivateKey& rsa, const std::string& eme) : + RSA_Decryption_Operation(const RSA_PrivateKey& rsa, const std::string& eme, RandomNumberGenerator& rng) : PK_Ops::Decryption_with_EME(eme), - RSA_Private_Operation(rsa) + RSA_Private_Operation(rsa, rng) { } @@ -286,9 +291,10 @@ class RSA_KEM_Decryption_Operation : public PK_Ops::KEM_Decryption_with_KDF, typedef RSA_PrivateKey Key_Type; RSA_KEM_Decryption_Operation(const RSA_PrivateKey& key, - const std::string& kdf) : + const std::string& kdf, + RandomNumberGenerator& rng) : PK_Ops::KEM_Decryption_with_KDF(kdf), - RSA_Private_Operation(key) + RSA_Private_Operation(key, rng) {} secure_vector<byte> @@ -397,16 +403,122 @@ class RSA_KEM_Encryption_Operation : public PK_Ops::KEM_Encryption_with_KDF, } }; +} -BOTAN_REGISTER_PK_ENCRYPTION_OP("RSA", RSA_Encryption_Operation); -BOTAN_REGISTER_PK_DECRYPTION_OP("RSA", RSA_Decryption_Operation); +std::unique_ptr<PK_Ops::Encryption> +RSA_PublicKey::create_encryption_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { +#if defined(BOTAN_HAS_OPENSSL) + if(provider == "openssl" || provider.empty()) + { + try + { + return make_openssl_rsa_enc_op(*this, params); + } + catch(Exception& e) + { + /* + * If OpenSSL for some reason could not handle this (eg due to OAEP params), + * throw if openssl was specifically requested but otherwise just fall back + * to the normal version. + */ + if(provider == "openssl") + throw Exception("OpenSSL RSA provider rejected key:", e.what()); + } + } +#endif -BOTAN_REGISTER_PK_SIGNATURE_OP("RSA", RSA_Signature_Operation); -BOTAN_REGISTER_PK_VERIFY_OP("RSA", RSA_Verify_Operation); + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Encryption>(new RSA_Encryption_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } -BOTAN_REGISTER_PK_KEM_ENCRYPTION_OP("RSA", RSA_KEM_Encryption_Operation); -BOTAN_REGISTER_PK_KEM_DECRYPTION_OP("RSA", RSA_KEM_Decryption_Operation); +std::unique_ptr<PK_Ops::KEM_Encryption> +RSA_PublicKey::create_kem_encryption_op(RandomNumberGenerator& /*rng*/, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::KEM_Encryption>(new RSA_KEM_Encryption_Operation(*this, params)); + throw Provider_Not_Found(algo_name(), provider); + } -} +std::unique_ptr<PK_Ops::Verification> +RSA_PublicKey::create_verification_op(const std::string& params, + const std::string& provider) const + { +#if defined(BOTAN_HAS_OPENSSL) + if(provider == "openssl" || provider.empty()) + { + std::unique_ptr<PK_Ops::Verification> res = make_openssl_rsa_ver_op(*this, params); + if(res) + return res; + } +#endif + + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Verification>(new RSA_Verify_Operation(*this, params)); + + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::Decryption> +RSA_PrivateKey::create_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const + { +#if defined(BOTAN_HAS_OPENSSL) + if(provider == "openssl" || provider.empty()) + { + try + { + return make_openssl_rsa_dec_op(*this, params); + } + catch(Exception& e) + { + if(provider == "openssl") + throw Exception("OpenSSL RSA provider rejected key:", e.what()); + } + } +#endif + + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Decryption>(new RSA_Decryption_Operation(*this, params, rng)); + + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::KEM_Decryption> +RSA_PrivateKey::create_kem_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const + { + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::KEM_Decryption>(new RSA_KEM_Decryption_Operation(*this, params, rng)); + + throw Provider_Not_Found(algo_name(), provider); + } + +std::unique_ptr<PK_Ops::Signature> +RSA_PrivateKey::create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const + { +#if defined(BOTAN_HAS_OPENSSL) + if(provider == "openssl" || provider.empty()) + { + std::unique_ptr<PK_Ops::Signature> res = make_openssl_rsa_sig_op(*this, params); + if(res) + return res; + } +#endif + + if(provider == "base" || provider.empty()) + return std::unique_ptr<PK_Ops::Signature>(new RSA_Signature_Operation(*this, params, rng)); + + throw Provider_Not_Found(algo_name(), provider); + } } diff --git a/src/lib/pubkey/rsa/rsa.h b/src/lib/pubkey/rsa/rsa.h index 85bd7ce58..ddfd23b05 100644 --- a/src/lib/pubkey/rsa/rsa.h +++ b/src/lib/pubkey/rsa/rsa.h @@ -52,6 +52,20 @@ class BOTAN_DLL RSA_PublicKey : public virtual Public_Key size_t estimated_strength() const override; + std::unique_ptr<PK_Ops::Encryption> + create_encryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + + std::unique_ptr<PK_Ops::KEM_Encryption> + create_kem_encryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + + std::unique_ptr<PK_Ops::Verification> + create_verification_op(const std::string& params, + const std::string& provider) const override; + protected: RSA_PublicKey() {} @@ -119,6 +133,22 @@ class BOTAN_DLL RSA_PrivateKey : public Private_Key, public RSA_PublicKey const BigInt& get_d2() const { return m_d2; } secure_vector<byte> pkcs8_private_key() const override; + + std::unique_ptr<PK_Ops::Decryption> + create_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + + std::unique_ptr<PK_Ops::KEM_Decryption> + create_kem_decryption_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + + std::unique_ptr<PK_Ops::Signature> + create_signature_op(RandomNumberGenerator& rng, + const std::string& params, + const std::string& provider) const override; + private: BigInt m_d, m_p, m_q, m_d1, m_d2, m_c; }; |