aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/botan/src/lib/pubkey
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/3rdparty/botan/src/lib/pubkey')
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/blinding.cpp66
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/blinding.h78
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dh/dh.cpp130
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dh/dh.h81
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dh/info.txt13
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/dl_algo.cpp84
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/dl_algo.h140
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/info.txt10
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_group.cpp610
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_group.h332
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_named.cpp175
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dl_group/info.txt10
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dsa/dsa.cpp218
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dsa/dsa.h87
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/dsa/info.txt12
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/curve_gfp.cpp576
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/curve_gfp.h269
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_group.cpp765
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_group.h372
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_named.cpp289
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/info.txt20
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_gfp.cpp727
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_gfp.h444
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_mul.cpp375
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_mul.h84
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/ecc_key.cpp201
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/ecc_key.h172
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/info.txt10
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecdh/ecdh.cpp85
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecdh/ecdh.h106
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecdh/info.txt10
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/ecdsa.cpp256
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/ecdsa.h98
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/info.txt14
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/info.txt31
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/keypair/info.txt6
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/keypair/keypair.cpp85
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/keypair/keypair.h83
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pbes2/info.txt10
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pbes2/pbes2.cpp312
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pbes2/pbes2.h85
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pem/info.txt7
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pem/pem.cpp169
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pem/pem.h91
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pk_algs.cpp434
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pk_algs.h46
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pk_keys.cpp148
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pk_keys.h317
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pk_ops.cpp173
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pk_ops.h150
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pk_ops_fwd.h27
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pk_ops_impl.h231
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pkcs8.cpp468
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pkcs8.h288
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pubkey.cpp350
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/pubkey.h771
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/rsa/info.txt10
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/rsa/rsa.cpp579
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/rsa/rsa.h164
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/workfactor.cpp64
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/workfactor.h50
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/x509_key.cpp106
-rw-r--r--src/libs/3rdparty/botan/src/lib/pubkey/x509_key.h80
63 files changed, 12254 insertions, 0 deletions
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/blinding.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/blinding.cpp
new file mode 100644
index 0000000000..ecd420780c
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/blinding.cpp
@@ -0,0 +1,66 @@
+/*
+* Blinding for public key operations
+* (C) 1999-2010,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/blinding.h>
+
+namespace Botan {
+
+Blinder::Blinder(const BigInt& modulus,
+ RandomNumberGenerator& rng,
+ std::function<BigInt (const BigInt&)> fwd,
+ std::function<BigInt (const BigInt&)> inv) :
+ 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{}
+ {
+ const BigInt k = blinding_nonce();
+ m_e = m_fwd_fn(k);
+ m_d = m_inv_fn(k);
+ }
+
+BigInt Blinder::blinding_nonce() const
+ {
+ return BigInt(m_rng, m_modulus_bits - 1);
+ }
+
+BigInt Blinder::blind(const BigInt& i) const
+ {
+ if(!m_reducer.initialized())
+ throw Exception("Blinder not initialized, cannot blind");
+
+ ++m_counter;
+
+ 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
+ {
+ m_e = m_reducer.square(m_e);
+ m_d = m_reducer.square(m_d);
+ }
+
+ return m_reducer.multiply(i, m_e);
+ }
+
+BigInt Blinder::unblind(const BigInt& i) const
+ {
+ if(!m_reducer.initialized())
+ throw Exception("Blinder not initialized, cannot unblind");
+
+ return m_reducer.multiply(i, m_d);
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/blinding.h b/src/libs/3rdparty/botan/src/lib/pubkey/blinding.h
new file mode 100644
index 0000000000..1bdd235f0f
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/blinding.h
@@ -0,0 +1,78 @@
+/*
+* Blinding for public key operations
+* (C) 1999-2010,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_BLINDER_H_
+#define BOTAN_BLINDER_H_
+
+#include <botan/bigint.h>
+#include <botan/reducer.h>
+#include <functional>
+
+namespace Botan {
+
+class RandomNumberGenerator;
+
+/**
+* Blinding Function Object.
+*/
+class BOTAN_PUBLIC_API(2,0) Blinder final
+ {
+ public:
+ /**
+ * Blind a value.
+ * The blinding nonce k is freshly generated after
+ * BOTAN_BLINDING_REINIT_INTERVAL calls to blind().
+ * BOTAN_BLINDING_REINIT_INTERVAL = 0 means a fresh
+ * nonce is only generated once. On every other call,
+ * an updated nonce is used for blinding: k' = k*k mod n.
+ * @param x value to blind
+ * @return blinded value
+ */
+ BigInt blind(const BigInt& x) const;
+
+ /**
+ * Unblind a value.
+ * @param x value to unblind
+ * @return unblinded value
+ */
+ BigInt unblind(const BigInt& x) const;
+
+ /**
+ * @param modulus the modulus
+ * @param rng the RNG to use for generating the nonce
+ * @param fwd_func a function that calculates the modular
+ * exponentiation of the public exponent and the given value (the nonce)
+ * @param inv_func a function that calculates the modular inverse
+ * of the given value (the nonce)
+ */
+ Blinder(const BigInt& modulus,
+ RandomNumberGenerator& rng,
+ std::function<BigInt (const BigInt&)> fwd_func,
+ std::function<BigInt (const BigInt&)> inv_func);
+
+ Blinder(const Blinder&) = delete;
+
+ Blinder& operator=(const Blinder&) = delete;
+
+ RandomNumberGenerator& rng() const { return m_rng; }
+
+ private:
+ BigInt blinding_nonce() const;
+
+ Modular_Reducer m_reducer;
+ 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;
+
+ mutable BigInt m_e, m_d;
+ mutable size_t m_counter = 0;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dh/dh.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/dh/dh.cpp
new file mode 100644
index 0000000000..ae6e9c589b
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dh/dh.cpp
@@ -0,0 +1,130 @@
+/*
+* Diffie-Hellman
+* (C) 1999-2007,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/dh.h>
+#include <botan/internal/pk_ops_impl.h>
+#include <botan/pow_mod.h>
+#include <botan/blinding.h>
+
+namespace Botan {
+
+/*
+* DH_PublicKey Constructor
+*/
+DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ m_group = grp;
+ m_y = y1;
+ }
+
+/*
+* Return the public value for key agreement
+*/
+std::vector<uint8_t> DH_PublicKey::public_value() const
+ {
+ return unlock(BigInt::encode_1363(m_y, group_p().bytes()));
+ }
+
+/*
+* Create a DH private key
+*/
+DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ m_group = grp;
+
+ 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;
+
+ if(m_y == 0)
+ m_y = m_group.power_g_p(m_x, grp.p_bits());
+ }
+ }
+
+/*
+* Load a DH private key
+*/
+DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits) :
+ DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
+ {
+ if(m_y.is_zero())
+ {
+ m_y = m_group.power_g_p(m_x, m_group.p_bits());
+ }
+ }
+
+/*
+* Return the public value for key agreement
+*/
+std::vector<uint8_t> DH_PrivateKey::public_value() const
+ {
+ return DH_PublicKey::public_value();
+ }
+
+namespace {
+
+/**
+* DH operation
+*/
+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) :
+ 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<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override;
+ private:
+ const BigInt& m_p;
+
+ Fixed_Exponent_Power_Mod m_powermod_x_p;
+ Blinder m_blinder;
+ };
+
+secure_vector<uint8_t> DH_KA_Operation::raw_agree(const uint8_t w[], size_t w_len)
+ {
+ BigInt v = BigInt::decode(w, w_len);
+
+ if(v <= 1 || v >= m_p - 1)
+ throw Invalid_Argument("DH agreement - invalid key provided");
+
+ v = m_blinder.blind(v);
+ v = m_powermod_x_p(v);
+ v = m_blinder.unblind(v);
+
+ return BigInt::encode_1363(v, m_p.bytes());
+ }
+
+}
+
+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/libs/3rdparty/botan/src/lib/pubkey/dh/dh.h b/src/libs/3rdparty/botan/src/lib/pubkey/dh/dh.h
new file mode 100644
index 0000000000..e3aa0d2c5b
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dh/dh.h
@@ -0,0 +1,81 @@
+/*
+* Diffie-Hellman
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_DIFFIE_HELLMAN_H_
+#define BOTAN_DIFFIE_HELLMAN_H_
+
+#include <botan/dl_algo.h>
+
+namespace Botan {
+
+/**
+* This class represents Diffie-Hellman public keys.
+*/
+class BOTAN_PUBLIC_API(2,0) DH_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const override { return "DH"; }
+
+ std::vector<uint8_t> public_value() const;
+
+ DL_Group::Format group_format() const override { return DL_Group::ANSI_X9_42; }
+
+ /**
+ * 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<uint8_t>& key_bits) :
+ DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) {}
+
+ /**
+ * Construct a public key with the specified parameters.
+ * @param grp 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() = default;
+ };
+
+/**
+* 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
+ {
+ public:
+ std::vector<uint8_t> public_value() const override;
+
+ /**
+ * Load a private key.
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits PKCS #8 structure
+ */
+ DH_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& 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)
+ */
+ 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;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dh/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/dh/info.txt
new file mode 100644
index 0000000000..1b9ba24948
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dh/info.txt
@@ -0,0 +1,13 @@
+<defines>
+DIFFIE_HELLMAN -> 20131128
+</defines>
+
+<header:public>
+dh.h
+</header:public>
+
+<requires>
+dl_algo
+dl_group
+numbertheory
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/dl_algo.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/dl_algo.cpp
new file mode 100644
index 0000000000..15b0b175e4
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/dl_algo.cpp
@@ -0,0 +1,84 @@
+/*
+* DL Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/dl_algo.h>
+#include <botan/numthry.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+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(get_oid(),
+ m_group.DER_encode(group_format()));
+ }
+
+std::vector<uint8_t> DL_Scheme_PublicKey::public_key_bits() const
+ {
+ std::vector<uint8_t> 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<uint8_t>& key_bits,
+ DL_Group::Format format) :
+ m_group(alg_id.get_parameters(), format)
+ {
+ BER_Decoder(key_bits).decode(m_y);
+ }
+
+secure_vector<uint8_t> 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<uint8_t>& key_bits,
+ DL_Group::Format format)
+ {
+ m_group.BER_decode(alg_id.get_parameters(), format);
+
+ BER_Decoder(key_bits).decode(m_x);
+ }
+
+/*
+* Check Public DL Parameters
+*/
+bool DL_Scheme_PublicKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ return m_group.verify_group(rng, strong) && m_group.verify_public_element(m_y);
+ }
+
+/*
+* 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);
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/dl_algo.h b/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/dl_algo.h
new file mode 100644
index 0000000000..af01bc217a
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/dl_algo.h
@@ -0,0 +1,140 @@
+/*
+* 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 <botan/dl_group.h>
+#include <botan/pk_keys.h>
+
+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<uint8_t> 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;
+
+ 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<uint8_t>& 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<uint8_t> private_key_bits() const override;
+
+ DL_Scheme_PrivateKey& operator=(const DL_Scheme_PrivateKey& other) = default;
+
+ 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<uint8_t>& key_bits,
+ DL_Group::Format group_format);
+
+ DL_Scheme_PrivateKey() = default;
+
+ /**
+ * The DL private key
+ */
+ BigInt m_x;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/info.txt
new file mode 100644
index 0000000000..44e649cd67
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dl_algo/info.txt
@@ -0,0 +1,10 @@
+<defines>
+DL_PUBLIC_KEY_FAMILY -> 20131128
+</defines>
+
+<requires>
+asn1
+dl_group
+numbertheory
+rng
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_group.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_group.cpp
new file mode 100644
index 0000000000..abc14ec0c7
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_group.cpp
@@ -0,0 +1,610 @@
+/*
+* Discrete Logarithm Parameters
+* (C) 1999-2008,2015,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/dl_group.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+#include <botan/monty.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pem.h>
+#include <botan/workfactor.h>
+#include <botan/internal/monty_exp.h>
+
+namespace Botan {
+
+class DL_Group_Data final
+ {
+ public:
+ DL_Group_Data(const BigInt& p, const BigInt& q, const BigInt& g) :
+ m_p(p), m_q(q), m_g(g),
+ m_mod_p(p),
+ m_mod_q(q),
+ m_monty_params(std::make_shared<Montgomery_Params>(m_p, m_mod_p)),
+ m_monty(monty_precompute(m_monty_params, m_g, /*window bits=*/4)),
+ m_p_bits(p.bits()),
+ m_q_bits(q.bits()),
+ m_estimated_strength(dl_work_factor(m_p_bits)),
+ m_exponent_bits(dl_exponent_size(m_p_bits))
+ {
+ }
+
+ ~DL_Group_Data() = default;
+
+ DL_Group_Data(const DL_Group_Data& other) = delete;
+ DL_Group_Data& operator=(const DL_Group_Data& other) = delete;
+
+ const BigInt& p() const { return m_p; }
+ const BigInt& q() const { return m_q; }
+ const BigInt& g() const { return m_g; }
+
+ BigInt mod_p(const BigInt& x) const { return m_mod_p.reduce(x); }
+
+ BigInt multiply_mod_p(const BigInt& x, const BigInt& y) const
+ {
+ return m_mod_p.multiply(x, y);
+ }
+
+ BigInt mod_q(const BigInt& x) const { return m_mod_q.reduce(x); }
+
+ BigInt multiply_mod_q(const BigInt& x, const BigInt& y) const
+ {
+ return m_mod_q.multiply(x, y);
+ }
+
+ BigInt square_mod_q(const BigInt& x) const
+ {
+ return m_mod_q.square(x);
+ }
+
+ std::shared_ptr<const Montgomery_Params> monty_params_p() const
+ { return m_monty_params; }
+
+ size_t p_bits() const { return m_p_bits; }
+ size_t q_bits() const { return m_q_bits; }
+ size_t p_bytes() const { return (m_p_bits + 7) / 8; }
+
+ size_t estimated_strength() const { return m_estimated_strength; }
+
+ size_t exponent_bits() const { return m_exponent_bits; }
+
+ BigInt power_g_p(const BigInt& k, size_t max_k_bits) const
+ {
+ return monty_execute(*m_monty, k, max_k_bits);
+ }
+
+ bool q_is_set() const { return m_q_bits > 0; }
+
+ void assert_q_is_set(const std::string& function) const
+ {
+ if(q_is_set() == false)
+ throw Invalid_State("DL_Group::" + function + " q is not set for this group");
+ }
+
+ private:
+ BigInt m_p;
+ BigInt m_q;
+ BigInt m_g;
+ Modular_Reducer m_mod_p;
+ Modular_Reducer m_mod_q;
+ std::shared_ptr<const Montgomery_Params> m_monty_params;
+ std::shared_ptr<const Montgomery_Exponentation_State> m_monty;
+ size_t m_p_bits;
+ size_t m_q_bits;
+ size_t m_estimated_strength;
+ size_t m_exponent_bits;
+ };
+
+//static
+std::shared_ptr<DL_Group_Data> DL_Group::BER_decode_DL_group(const uint8_t data[], size_t data_len, DL_Group::Format format)
+ {
+ BigInt p, q, g;
+
+ BER_Decoder decoder(data, data_len);
+ BER_Decoder ber = decoder.start_cons(SEQUENCE);
+
+ if(format == DL_Group::ANSI_X9_57)
+ {
+ ber.decode(p)
+ .decode(q)
+ .decode(g)
+ .verify_end();
+ }
+ else if(format == DL_Group::ANSI_X9_42)
+ {
+ ber.decode(p)
+ .decode(g)
+ .decode(q)
+ .discard_remaining();
+ }
+ else if(format == DL_Group::PKCS_3)
+ {
+ // q is left as zero
+ ber.decode(p)
+ .decode(g)
+ .discard_remaining();
+ }
+ else
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
+
+ return std::make_shared<DL_Group_Data>(p, q, g);
+ }
+
+//static
+std::shared_ptr<DL_Group_Data>
+DL_Group::load_DL_group_info(const char* p_str,
+ const char* q_str,
+ const char* g_str)
+ {
+ const BigInt p(p_str);
+ const BigInt q(q_str);
+ const BigInt g(g_str);
+
+ return std::make_shared<DL_Group_Data>(p, q, g);
+ }
+
+//static
+std::shared_ptr<DL_Group_Data>
+DL_Group::load_DL_group_info(const char* p_str,
+ const char* g_str)
+ {
+ const BigInt p(p_str);
+ const BigInt q = (p - 1) / 2;
+ const BigInt g(g_str);
+
+ return std::make_shared<DL_Group_Data>(p, q, g);
+ }
+
+namespace {
+
+DL_Group::Format pem_label_to_dl_format(const std::string& label)
+ {
+ if(label == "DH PARAMETERS")
+ return DL_Group::PKCS_3;
+ else if(label == "DSA PARAMETERS")
+ return DL_Group::ANSI_X9_57;
+ else if(label == "X942 DH PARAMETERS" || label == "X9.42 DH PARAMETERS")
+ return DL_Group::ANSI_X9_42;
+ else
+ throw Decoding_Error("DL_Group: Invalid PEM label " + label);
+ }
+
+}
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const std::string& str)
+ {
+ // Either a name or a PEM block, try name first
+ m_data = DL_group_info(str);
+
+ if(m_data == nullptr)
+ {
+ try
+ {
+ std::string label;
+ const std::vector<uint8_t> ber = unlock(PEM_Code::decode(str, label));
+ Format format = pem_label_to_dl_format(label);
+
+ m_data = BER_decode_DL_group(ber.data(), ber.size(), format);
+ }
+ catch(...) {}
+ }
+
+ if(m_data == nullptr)
+ throw Invalid_Argument("DL_Group: Unknown group " + str);
+ }
+
+namespace {
+
+/*
+* Create generator of the q-sized subgroup (DSA style generator)
+*/
+BigInt make_dsa_generator(const BigInt& p, const BigInt& q)
+ {
+ const BigInt e = (p - 1) / q;
+
+ if(e == 0 || (p - 1) % q > 0)
+ throw Invalid_Argument("make_dsa_generator q does not divide p-1");
+
+ for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i)
+ {
+ // TODO precompute!
+ BigInt g = power_mod(PRIMES[i], e, p);
+ if(g > 1)
+ return g;
+ }
+
+ throw Internal_Error("DL_Group: Couldn't create a suitable generator");
+ }
+
+}
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(RandomNumberGenerator& rng,
+ PrimeType type, size_t pbits, size_t qbits)
+ {
+ if(pbits < 1024)
+ throw Invalid_Argument("DL_Group: prime size " + std::to_string(pbits) + " is too small");
+
+ if(type == Strong)
+ {
+ if(qbits != 0 && qbits != pbits - 1)
+ throw Invalid_Argument("Cannot create strong-prime DL_Group with specified q bits");
+
+ const BigInt p = random_safe_prime(rng, pbits);
+ const BigInt q = (p - 1) / 2;
+
+ /*
+ Always choose a generator that is quadratic reside mod p,
+ this forces g to be a generator of the subgroup of size q.
+ */
+ BigInt g = 2;
+ if(jacobi(g, p) != 1)
+ {
+ // prime table does not contain 2
+ for(size_t i = 0; i < PRIME_TABLE_SIZE; ++i)
+ {
+ g = PRIMES[i];
+ if(jacobi(g, p) == 1)
+ break;
+ }
+ }
+
+ m_data = std::make_shared<DL_Group_Data>(p, q, g);
+ }
+ else if(type == Prime_Subgroup)
+ {
+ if(qbits == 0)
+ qbits = dl_exponent_size(pbits);
+
+ const BigInt q = random_prime(rng, qbits);
+ Modular_Reducer mod_2q(2*q);
+ BigInt X;
+ BigInt p;
+ while(p.bits() != pbits || !is_prime(p, rng, 128, true))
+ {
+ X.randomize(rng, pbits);
+ p = X - mod_2q.reduce(X) + 1;
+ }
+
+ const BigInt g = make_dsa_generator(p, q);
+ m_data = std::make_shared<DL_Group_Data>(p, q, g);
+ }
+ else if(type == DSA_Kosherizer)
+ {
+ if(qbits == 0)
+ qbits = ((pbits <= 1024) ? 160 : 256);
+
+ BigInt p, q;
+ generate_dsa_primes(rng, p, q, pbits, qbits);
+ const BigInt g = make_dsa_generator(p, q);
+ m_data = std::make_shared<DL_Group_Data>(p, q, g);
+ }
+ else
+ {
+ throw Invalid_Argument("DL_Group unknown PrimeType");
+ }
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(RandomNumberGenerator& rng,
+ const std::vector<uint8_t>& seed,
+ size_t pbits, size_t qbits)
+ {
+ BigInt p, q;
+
+ if(!generate_dsa_primes(rng, p, q, pbits, qbits, seed))
+ throw Invalid_Argument("DL_Group: The seed given does not generate a DSA group");
+
+ BigInt g = make_dsa_generator(p, q);
+
+ m_data = std::make_shared<DL_Group_Data>(p, q, g);
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const BigInt& p, const BigInt& g)
+ {
+ m_data = std::make_shared<DL_Group_Data>(p, 0, g);
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const BigInt& p, const BigInt& q, const BigInt& g)
+ {
+ m_data = std::make_shared<DL_Group_Data>(p, q, g);
+ }
+
+const DL_Group_Data& DL_Group::data() const
+ {
+ if(m_data)
+ return *m_data;
+
+ throw Invalid_State("DL_Group uninitialized");
+ }
+
+bool DL_Group::verify_public_element(const BigInt& y) const
+ {
+ const BigInt& p = get_p();
+ const BigInt& q = get_q();
+
+ if(y <= 1 || y >= p)
+ return false;
+
+ if(q.is_zero() == false)
+ {
+ if(power_mod(y, q, p) != 1)
+ return false;
+ }
+
+ return true;
+ }
+
+bool DL_Group::verify_element_pair(const BigInt& y, const BigInt& x) const
+ {
+ const BigInt& p = get_p();
+
+ if(y <= 1 || y >= p || x <= 1 || x >= p)
+ return false;
+
+ if(y != power_g_p(x))
+ return false;
+
+ return true;
+ }
+
+/*
+* Verify the parameters
+*/
+bool DL_Group::verify_group(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ const BigInt& p = get_p();
+ const BigInt& q = get_q();
+ const BigInt& g = get_g();
+
+ if(g < 2 || p < 3 || q < 0)
+ return false;
+
+ const size_t prob = (strong) ? 128 : 10;
+
+ if(q != 0)
+ {
+ if((p - 1) % q != 0)
+ {
+ return false;
+ }
+ if(this->power_g_p(q) != 1)
+ {
+ return false;
+ }
+ if(!is_prime(q, rng, prob))
+ {
+ return false;
+ }
+ }
+
+ if(!is_prime(p, rng, prob))
+ {
+ return false;
+ }
+ return true;
+ }
+
+/*
+* Return the prime
+*/
+const BigInt& DL_Group::get_p() const
+ {
+ return data().p();
+ }
+
+/*
+* Return the generator
+*/
+const BigInt& DL_Group::get_g() const
+ {
+ return data().g();
+ }
+
+/*
+* Return the subgroup
+*/
+const BigInt& DL_Group::get_q() const
+ {
+ return data().q();
+ }
+
+std::shared_ptr<const Montgomery_Params> DL_Group::monty_params_p() const
+ {
+ return data().monty_params_p();
+ }
+
+size_t DL_Group::p_bits() const
+ {
+ return data().p_bits();
+ }
+
+size_t DL_Group::p_bytes() const
+ {
+ return data().p_bytes();
+ }
+
+size_t DL_Group::q_bits() const
+ {
+ data().assert_q_is_set("q_bits");
+ return data().q_bits();
+ }
+
+size_t DL_Group::estimated_strength() const
+ {
+ return data().estimated_strength();
+ }
+
+size_t DL_Group::exponent_bits() const
+ {
+ return data().exponent_bits();
+ }
+
+BigInt DL_Group::inverse_mod_p(const BigInt& x) const
+ {
+ // precompute??
+ return inverse_mod(x, get_p());
+ }
+
+BigInt DL_Group::mod_p(const BigInt& x) const
+ {
+ return data().mod_p(x);
+ }
+
+BigInt DL_Group::multiply_mod_p(const BigInt& x, const BigInt& y) const
+ {
+ return data().multiply_mod_p(x, y);
+ }
+
+BigInt DL_Group::inverse_mod_q(const BigInt& x) const
+ {
+ data().assert_q_is_set("inverse_mod_q");
+ // precompute??
+ return inverse_mod(x, get_q());
+ }
+
+BigInt DL_Group::mod_q(const BigInt& x) const
+ {
+ data().assert_q_is_set("mod_q");
+ return data().mod_q(x);
+ }
+
+BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y) const
+ {
+ data().assert_q_is_set("multiply_mod_q");
+ return data().multiply_mod_q(x, y);
+ }
+
+BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y, const BigInt& z) const
+ {
+ data().assert_q_is_set("multiply_mod_q");
+ return data().multiply_mod_q(data().multiply_mod_q(x, y), z);
+ }
+
+BigInt DL_Group::square_mod_q(const BigInt& x) const
+ {
+ data().assert_q_is_set("square_mod_q");
+ return data().square_mod_q(x);
+ }
+
+BigInt DL_Group::multi_exponentiate(const BigInt& x, const BigInt& y, const BigInt& z) const
+ {
+ return monty_multi_exp(data().monty_params_p(), get_g(), x, y, z);
+ }
+
+BigInt DL_Group::power_g_p(const BigInt& x) const
+ {
+ return data().power_g_p(x, x.bits());
+ }
+
+BigInt DL_Group::power_g_p(const BigInt& x, size_t max_x_bits) const
+ {
+ return data().power_g_p(x, max_x_bits);
+ }
+
+/*
+* DER encode the parameters
+*/
+std::vector<uint8_t> DL_Group::DER_encode(Format format) const
+ {
+ if(get_q().is_zero() && (format == ANSI_X9_57 || format == ANSI_X9_42))
+ throw Encoding_Error("Cannot encode DL_Group in ANSI formats when q param is missing");
+
+ std::vector<uint8_t> output;
+ DER_Encoder der(output);
+
+ if(format == ANSI_X9_57)
+ {
+ der.start_cons(SEQUENCE)
+ .encode(get_p())
+ .encode(get_q())
+ .encode(get_g())
+ .end_cons();
+ }
+ else if(format == ANSI_X9_42)
+ {
+ der.start_cons(SEQUENCE)
+ .encode(get_p())
+ .encode(get_g())
+ .encode(get_q())
+ .end_cons();
+ }
+ else if(format == PKCS_3)
+ {
+ der.start_cons(SEQUENCE)
+ .encode(get_p())
+ .encode(get_g())
+ .end_cons();
+ }
+ else
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
+
+ return output;
+ }
+
+/*
+* PEM encode the parameters
+*/
+std::string DL_Group::PEM_encode(Format format) const
+ {
+ const std::vector<uint8_t> encoding = DER_encode(format);
+
+ if(format == PKCS_3)
+ return PEM_Code::encode(encoding, "DH PARAMETERS");
+ else if(format == ANSI_X9_57)
+ return PEM_Code::encode(encoding, "DSA PARAMETERS");
+ else if(format == ANSI_X9_42)
+ return PEM_Code::encode(encoding, "X9.42 DH PARAMETERS");
+ else
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
+ }
+
+DL_Group::DL_Group(const uint8_t ber[], size_t ber_len, Format format)
+ {
+ m_data = BER_decode_DL_group(ber, ber_len, format);
+ }
+
+void DL_Group::BER_decode(const std::vector<uint8_t>& ber, Format format)
+ {
+ m_data = BER_decode_DL_group(ber.data(), ber.size(), format);
+ }
+
+/*
+* Decode PEM encoded parameters
+*/
+void DL_Group::PEM_decode(const std::string& pem)
+ {
+ std::string label;
+ const std::vector<uint8_t> ber = unlock(PEM_Code::decode(pem, label));
+ Format format = pem_label_to_dl_format(label);
+
+ m_data = BER_decode_DL_group(ber.data(), ber.size(), format);
+ }
+
+//static
+std::string DL_Group::PEM_for_named_group(const std::string& name)
+ {
+ DL_Group group(name);
+ DL_Group::Format format = group.get_q().is_zero() ? DL_Group::PKCS_3 : DL_Group::ANSI_X9_42;
+ return group.PEM_encode(format);
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_group.h b/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_group.h
new file mode 100644
index 0000000000..6bc9187613
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_group.h
@@ -0,0 +1,332 @@
+/*
+* Discrete Logarithm Group
+* (C) 1999-2008,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_DL_PARAM_H_
+#define BOTAN_DL_PARAM_H_
+
+#include <botan/bigint.h>
+
+namespace Botan {
+
+class Montgomery_Params;
+class DL_Group_Data;
+
+/**
+* This class represents discrete logarithm groups. It holds a prime
+* modulus p, a generator g, and (optionally) a prime q which is a
+* factor of (p-1). In most cases g generates the order-q subgroup.
+*/
+class BOTAN_PUBLIC_API(2,0) DL_Group final
+ {
+ public:
+ /**
+ * Determine the prime creation for DL groups.
+ */
+ enum PrimeType { Strong, Prime_Subgroup, DSA_Kosherizer };
+
+ /**
+ * The DL group encoding format variants.
+ */
+ enum Format {
+ ANSI_X9_42,
+ ANSI_X9_57,
+ PKCS_3,
+
+ DSA_PARAMETERS = ANSI_X9_57,
+ DH_PARAMETERS = ANSI_X9_42,
+ ANSI_X9_42_DH_PARAMETERS = ANSI_X9_42,
+ PKCS3_DH_PARAMETERS = PKCS_3
+ };
+
+ /**
+ * Construct a DL group with uninitialized internal value.
+ * Use this constructor is you wish to set the groups values
+ * from a DER or PEM encoded group.
+ */
+ DL_Group() = default;
+
+ /**
+ * Construct a DL group that is registered in the configuration.
+ * @param name the name that is configured in the global configuration
+ * for the desired group. If no configuration file is specified,
+ * the default values from the file policy.cpp will be used. For instance,
+ * use "modp/ietf/3072".
+ */
+ DL_Group(const std::string& name);
+
+ /**
+ * Create a new group randomly.
+ * @param rng the random number generator to use
+ * @param type specifies how the creation of primes p and q shall
+ * be performed. If type=Strong, then p will be determined as a
+ * safe prime, and q will be chosen as (p-1)/2. If
+ * type=Prime_Subgroup and qbits = 0, then the size of q will be
+ * determined according to the estimated difficulty of the DL
+ * problem. If type=DSA_Kosherizer, DSA primes will be created.
+ * @param pbits the number of bits of p
+ * @param qbits the number of bits of q. Leave it as 0 to have
+ * the value determined according to pbits.
+ */
+ DL_Group(RandomNumberGenerator& rng, PrimeType type,
+ size_t pbits, size_t qbits = 0);
+
+ /**
+ * Create a DSA group with a given seed.
+ * @param rng the random number generator to use
+ * @param seed the seed to use to create the random primes
+ * @param pbits the desired bit size of the prime p
+ * @param qbits the desired bit size of the prime q.
+ */
+ DL_Group(RandomNumberGenerator& rng,
+ const std::vector<uint8_t>& seed,
+ size_t pbits = 1024, size_t qbits = 0);
+
+ /**
+ * Create a DL group.
+ * @param p the prime p
+ * @param g the base g
+ */
+ DL_Group(const BigInt& p, const BigInt& g);
+
+ /**
+ * Create a DL group.
+ * @param p the prime p
+ * @param q the prime q
+ * @param g the base g
+ */
+ DL_Group(const BigInt& p, const BigInt& q, const BigInt& g);
+
+ /**
+ * Decode a BER-encoded DL group param
+ */
+ DL_Group(const uint8_t ber[], size_t ber_len, Format format);
+
+ /**
+ * Decode a BER-encoded DL group param
+ */
+ template<typename Alloc>
+ DL_Group(const std::vector<uint8_t, Alloc>& ber, Format format) :
+ DL_Group(ber.data(), ber.size(), format) {}
+
+ /**
+ * Get the prime p.
+ * @return prime p
+ */
+ const BigInt& get_p() const;
+
+ /**
+ * Get the prime q, returns zero if q is not used
+ * @return prime q
+ */
+ const BigInt& get_q() const;
+
+ /**
+ * Get the base g.
+ * @return base g
+ */
+ const BigInt& get_g() const;
+
+ /**
+ * Perform validity checks on the group.
+ * @param rng the rng to use
+ * @param strong whether to perform stronger by lengthier tests
+ * @return true if the object is consistent, false otherwise
+ */
+ bool verify_group(RandomNumberGenerator& rng, bool strong = true) const;
+
+ /**
+ * Verify a public element, ie check if y = g^x for some x.
+ *
+ * This is not a perfect test. It verifies that 1 < y < p and (if q is set)
+ * that y is in the subgroup of size q.
+ */
+ bool verify_public_element(const BigInt& y) const;
+
+ /**
+ * Verify a pair of elements y = g^x
+ *
+ * This verifies that 1 < x,y < p and that y=g^x mod p
+ */
+ bool verify_element_pair(const BigInt& y, const BigInt& x) const;
+
+ /**
+ * Encode this group into a string using PEM encoding.
+ * @param format the encoding format
+ * @return string holding the PEM encoded group
+ */
+ std::string PEM_encode(Format format) const;
+
+ /**
+ * Encode this group into a string using DER encoding.
+ * @param format the encoding format
+ * @return string holding the DER encoded group
+ */
+ std::vector<uint8_t> DER_encode(Format format) const;
+
+ /**
+ * Reduce an integer modulo p
+ * @return x % p
+ */
+ BigInt mod_p(const BigInt& x) const;
+
+ /**
+ * Multiply and reduce an integer modulo p
+ * @return (x*y) % p
+ */
+ BigInt multiply_mod_p(const BigInt& x, const BigInt& y) const;
+
+ /**
+ * Return the inverse of x mod p
+ */
+ BigInt inverse_mod_p(const BigInt& x) const;
+
+ /**
+ * Reduce an integer modulo q
+ * Throws if q is unset on this DL_Group
+ * @return x % q
+ */
+ BigInt mod_q(const BigInt& x) const;
+
+ /**
+ * Multiply and reduce an integer modulo q
+ * Throws if q is unset on this DL_Group
+ * @return (x*y) % q
+ */
+ BigInt multiply_mod_q(const BigInt& x, const BigInt& y) const;
+
+ /**
+ * Multiply and reduce an integer modulo q
+ * Throws if q is unset on this DL_Group
+ * @return (x*y*z) % q
+ */
+ BigInt multiply_mod_q(const BigInt& x, const BigInt& y, const BigInt& z) const;
+
+ /**
+ * Square and reduce an integer modulo q
+ * Throws if q is unset on this DL_Group
+ * @return (x*x) % q
+ */
+ BigInt square_mod_q(const BigInt& x) const;
+
+ /**
+ * Return the inverse of x mod q
+ * Throws if q is unset on this DL_Group
+ */
+ BigInt inverse_mod_q(const BigInt& x) const;
+
+ /**
+ * Modular exponentiation
+ *
+ * @warning this function leaks the size of x via the number of
+ * loop iterations. Use the version taking the maximum size to
+ * avoid this.
+ *
+ * @return (g^x) % p
+ */
+ BigInt power_g_p(const BigInt& x) const;
+
+ /**
+ * Modular exponentiation
+ * @param x the exponent
+ * @param max_x_bits x is assumed to be at most this many bits long.
+ *
+ * @return (g^x) % p
+ */
+ BigInt power_g_p(const BigInt& x, size_t max_x_bits) const;
+
+ /**
+ * Multi-exponentiate
+ * Return (g^x * y^z) % p
+ */
+ BigInt multi_exponentiate(const BigInt& x, const BigInt& y, const BigInt& z) const;
+
+ /**
+ * Return parameters for Montgomery reduction/exponentiation mod p
+ */
+ std::shared_ptr<const Montgomery_Params> monty_params_p() const;
+
+ /**
+ * Return the size of p in bits
+ * Same as get_p().bits()
+ */
+ size_t p_bits() const;
+
+ /**
+ * Return the size of p in bytes
+ * Same as get_p().bytes()
+ */
+ size_t p_bytes() const;
+
+ /**
+ * Return the size of q in bits
+ * Same as get_q().bits()
+ * Throws if q is unset
+ */
+ size_t q_bits() const;
+
+ /**
+ * Return size in bits of a secret exponent
+ *
+ * This attempts to balance between the attack costs of NFS
+ * (which depends on the size of the modulus) and Pollard's rho
+ * (which depends on the size of the exponent).
+ *
+ * It may vary over time for a particular group, if the attack
+ * costs change.
+ */
+ size_t exponent_bits() const;
+
+ /**
+ * Return an estimate of the strength of this group against
+ * discrete logarithm attacks (eg NFS). Warning: since this only
+ * takes into account known attacks it is by necessity an
+ * overestimate of the actual strength.
+ */
+ size_t estimated_strength() const;
+
+ /**
+ * Decode a DER/BER encoded group into this instance.
+ * @param ber a vector containing the DER/BER encoded group
+ * @param format the format of the encoded group
+ */
+ void BER_decode(const std::vector<uint8_t>& ber, Format format);
+
+ /**
+ * Decode a PEM encoded group into this instance.
+ * @param pem the PEM encoding of the group
+ */
+ void PEM_decode(const std::string& pem);
+
+ /**
+ * Return PEM representation of named DL group
+ */
+ static std::string BOTAN_DEPRECATED("Use DL_Group(name).PEM_encode()")
+ PEM_for_named_group(const std::string& name);
+
+ /*
+ * For internal use only
+ */
+ static std::shared_ptr<DL_Group_Data> DL_group_info(const std::string& name);
+
+ private:
+ static std::shared_ptr<DL_Group_Data> load_DL_group_info(const char* p_str,
+ const char* q_str,
+ const char* g_str);
+
+ static std::shared_ptr<DL_Group_Data> load_DL_group_info(const char* p_str,
+ const char* g_str);
+
+ static std::shared_ptr<DL_Group_Data>
+ BER_decode_DL_group(const uint8_t data[], size_t data_len, DL_Group::Format format);
+
+ const DL_Group_Data& data() const;
+ std::shared_ptr<DL_Group_Data> m_data;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_named.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_named.cpp
new file mode 100644
index 0000000000..4d7b71bc1d
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/dl_named.cpp
@@ -0,0 +1,175 @@
+/*
+* List of discrete log groups
+* (C) 2013 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+//static
+std::shared_ptr<DL_Group_Data> DL_Group::DL_group_info(const std::string& name)
+ {
+ /* TLS FFDHE groups */
+
+ if(name == "ffdhe/ietf/2048")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B423861285C97FFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "ffdhe/ietf/3072")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "ffdhe/ietf/4096")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6AFFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "ffdhe/ietf/6144")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "ffdhe/ietf/8192")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C8381E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665CB2C0F1CC01BD70229388839D2AF05E454504AC78B7582822846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA4571EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88CD68C8BB7C5C6424CFFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ /* IETF IPsec groups */
+
+ if(name == "modp/ietf/1024")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "modp/ietf/1536")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "modp/ietf/2048")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "modp/ietf/3072")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "modp/ietf/4096")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "modp/ietf/6144")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ if(name == "modp/ietf/8192")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF",
+ "0x2");
+ }
+
+ /* SRP groups
+
+ SRP groups have a p st (p-1)/2 is prime, but g is not a generator
+ of subgroup of size q, so set q == 0 to bypass generator check
+
+ Missing q doesn't matter for SRP, and nothing but SRP should be
+ using these parameters.
+ */
+
+ if(name == "modp/srp/1024")
+ {
+ return load_DL_group_info("0xEEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3",
+ "0",
+ "0x2");
+ }
+
+ if(name == "modp/srp/1536")
+ {
+ return load_DL_group_info("0x9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB",
+ "0",
+ "0x2");
+ }
+
+ if(name == "modp/srp/2048")
+ {
+ return load_DL_group_info("0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73",
+ "0",
+ "0x2");
+ }
+
+ if(name == "modp/srp/3072")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
+ "0",
+ "0x5");
+ }
+
+ if(name == "modp/srp/4096")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF",
+ "0",
+ "0x5");
+ }
+
+ if(name == "modp/srp/6144")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
+ "0",
+ "0x5");
+ }
+
+ if(name == "modp/srp/8192")
+ {
+ return load_DL_group_info("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF",
+ "0",
+ "0x13");
+ }
+
+ /* DSA groups */
+
+ if(name == "dsa/jce/1024")
+ {
+ return load_DL_group_info("0xFD7F53811D75122952DF4A9C2EECE4E7F611B7523CEF4400C31E3F80B6512669455D402251FB593D8D58FABFC5F5BA30F6CB9B556CD7813B801D346FF26660B76B9950A5A49F9FE8047B1022C24FBBA9D7FEB7C61BF83B57E7C6A8A6150F04FB83F6D3C51EC3023554135A169132F675F3AE2B61D72AEFF22203199DD14801C7",
+ "0x9760508F15230BCCB292B982A2EB840BF0581CF5",
+ "0x469603512E30278CD3947595DB22EEC9826A6322ADC97344F41D740C325724C8F9EFBAA7D4D803FF8C609DCD100EBC5BDFCFAD7C6A425FAEA786EA2050EBE98351EA1FDA1FDF24D6947AA6B9AA23766953802F4D7D4A8ECBA06D19768A2491FFB16D0EF9C43A99B5F71672FF6F0A24B444D0736D04D38A1A1322DAF6CDD88C9D");
+ }
+
+ if(name == "dsa/botan/2048")
+ {
+ return load_DL_group_info("0x91C48A4FDFBCF7C02AE95E7DA126122B5DD2864F559B87E8E74A286D52F59BD1DE68DFD645D0E00C60C080031891980374EEB594A532BFD67B9A09EAC4B8663A07910E68F39465FB7040D25DF13932EBAC4347A530ECBA61C854F9B880D3C0C3660080587C45566DADE26BD5A394BE093B4C0F24B5AFFEF8EC6C5B3E57FB89025A9BC16769932131E16D3C94EFCAB18D0DF061203CC53E6103BC72D5594BFD40CA65380F44A9A851DCB075495FC033A8A58071A1BD78FE052F66555648EB4B719D2AFE8B4880F8DAD6F15818BA178F89274C870BE9B96EB08C46C40040CC2EFE1DFB1B1868DD319DE3C34A32A63AB6EB1224209A419680CC7902D1728D4DF9E1",
+ "0x8CD7D450F86F0AD94EEE4CE469A8756D1EBD1058241943EAFFB0B354585E924D",
+ "0xD9F5E0761B4DBD1833D6AB1A961A0996C5F22303F72D84C140F67C431D94AB5715BEA81A0C98D39CE4BCF78D6B9EBC895D34FE89D94091D5848615EF15F5E86F11D96F6C969E203DDFA58356420A49CB444B595B901A933CFE0767B594F18A07B7F91DECDBA446B88990F78F2FF91F2FE7CD43FD2E46D18EADA1F7BB6602C617F6EF3A4B284F2FD9BA10A36042DE8FA87A2CA36597FEC81157A1485E44041DF02830111CB880BBE6ED494814886F965CDC3135F5CCF1383728BF65B806F9692C0B10D6C4C09C75A6CA3B4013CB16AB2C105F6BE23AEA9000EAB2178985F972C98057E1C86E44E7218688EA4AE0F3636DCCA745C9DCD4E6AFFB67CCBC13D6131");
+ }
+
+ if(name == "dsa/botan/3072")
+ {
+ return load_DL_group_info("0xE4B50880759663585E142460CA2D9DFF132F8AE4C840DDA3A2666889124FE5638B84E8A29B7AF3FA1209BE6BFC4B5072ED3B2B7387BAF3F857F478A80228EF3600B76B3DCFB61D20D34465B2506D2CAF87DF6E7DC0CE91BD2D167A46F6ADCC31C531E4F9C7ABBDB92ADDF35B0A806C66292A5F5E17E964DD099903733AC428AB35D80EA6F685BFBA8BE4068E5418AE5ECAD9E8FF073DE2B63E4E7EAD35C8A9B70B5BD47CFB88D373B66F37931939B0AB71BD5595809086DA0155337D185A0E4FB36A519B1B6202B8591E6002449CF1CD3A66384F6D2073B1CD73BECA93BAF1E1A6117D0238F222AE1ED7FED185A890E7F67FAB8FEB9753CC134A5183DFE87AE2595F7B5C2D9FBB42249FDD59513E1D3396B3EB2FD86684F285A8448FE757A029881C40760B94EF919BDF9740C38389599EC51A6E9BB519A8E068491E9CE0A2FCFE3CB60D66CF0DFAD20A8EC684048684A61444575BD1724D7352B44A760077B3BD6BD385CE5B0A7250CC0BF768DA82923806EB9CFBB138843731B618208C759B",
+ "0xB3EBD364EC69EF8CF3BAF643B75734B16339B2E49E5CDE1B59C1E9FB40EE0C5B",
+ "0x2BED21EEF83964A230AE89BBA71D9F7C39C52FC8229B4E3BC7E5944D329DA10F010EAC9E7BAF6C009FC4EB2960723E2B56DF4663E4C3AC800E9258DE2F7649D206782893F865EFCA498D2EEF30074EA5E8A7AB262712A4D94A2F3B0B9A92EE400FB38A3CC59A5DC7E436D5C004B22E35028381B51C93407EB32D4AE0FD42CB45E12D0ECEE8A26238EDE2082A7B1522113C66CEF8D745C6CF3CB945F84D2F4DE16D44A71DE198270E13F03553C88B8D323AD0B948A1BF2103A949979B6ED16FB5F3C953D95B7C8E88CA67DCF5A636FB9CA39D924215F7A884ED6C7EE3C96D8D9715427974B7C4351282E13D3773F7D28B452F10892A13C7587328DEA4827B6B369B2A8DC172ADC583F51F2A6598C5483E5BC467B02F91D059C402D18E2C2680F776AA06F49280A2C72C17CC42D5B6E740C5C4B1AB3C51C2ED092BE2A2D8B053AE5773D1425ED2B08F06E2DD50592DF1A478C15591CDFD11564FF88FF38B721D42392FDA473212DCFD8D2D88A976A00AFFE6FFFB430A359E64CA2B351CA2412394");
+ }
+
+ return std::shared_ptr<DL_Group_Data>();
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/info.txt
new file mode 100644
index 0000000000..a73edb18c1
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dl_group/info.txt
@@ -0,0 +1,10 @@
+<defines>
+DL_GROUP -> 20131128
+</defines>
+
+<requires>
+asn1
+bigint
+numbertheory
+pem
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dsa/dsa.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/dsa/dsa.cpp
new file mode 100644
index 0000000000..35240292c1
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dsa/dsa.cpp
@@ -0,0 +1,218 @@
+/*
+* DSA
+* (C) 1999-2010,2014,2016 Jack Lloyd
+* (C) 2016 René Korthaus
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/dsa.h>
+#include <botan/keypair.h>
+#include <botan/reducer.h>
+#include <botan/rng.h>
+#include <botan/internal/pk_ops_impl.h>
+
+#if defined(BOTAN_HAS_RFC6979_GENERATOR)
+ #include <botan/emsa.h>
+ #include <botan/rfc6979.h>
+#endif
+
+namespace Botan {
+
+/*
+* DSA_PublicKey Constructor
+*/
+DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ m_group = grp;
+ m_y = y1;
+ }
+
+/*
+* Create a DSA private key
+*/
+DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ m_group = grp;
+
+ if(x_arg == 0)
+ m_x = BigInt::random_integer(rng, 2, group_q());
+ else
+ m_x = x_arg;
+
+ m_y = m_group.power_g_p(m_x, m_group.q_bits());
+ }
+
+DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits) :
+ DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
+ {
+ m_y = m_group.power_g_p(m_x, m_group.q_bits());
+ }
+
+/*
+* 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())
+ return false;
+
+ if(!strong)
+ return true;
+
+ return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
+ }
+
+namespace {
+
+/**
+* Object that can create a DSA signature
+*/
+class DSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
+ {
+ public:
+ DSA_Signature_Operation(const DSA_PrivateKey& dsa,
+ const std::string& emsa,
+ RandomNumberGenerator& rng) :
+ PK_Ops::Signature_with_EMSA(emsa),
+ m_group(dsa.get_group()),
+ m_x(dsa.get_x())
+ {
+#if defined(BOTAN_HAS_RFC6979_GENERATOR)
+ m_rfc6979_hash = hash_for_emsa(emsa);
+#endif
+
+ m_b = BigInt::random_integer(rng, 2, dsa.group_q());
+ m_b_inv = m_group.inverse_mod_q(m_b);
+ }
+
+ size_t max_input_bits() const override { return m_group.get_q().bits(); }
+
+ secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
+ private:
+ const DL_Group m_group;
+ const BigInt& m_x;
+#if defined(BOTAN_HAS_RFC6979_GENERATOR)
+ std::string m_rfc6979_hash;
+#endif
+
+ BigInt m_b, m_b_inv;
+ };
+
+secure_vector<uint8_t>
+DSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ const BigInt& q = m_group.get_q();
+
+ BigInt m(msg, msg_len, m_group.q_bits());
+
+ while(m >= q)
+ m -= q;
+
+#if defined(BOTAN_HAS_RFC6979_GENERATOR)
+ BOTAN_UNUSED(rng);
+ const BigInt k = generate_rfc6979_nonce(m_x, q, m, m_rfc6979_hash);
+#else
+ const BigInt k = BigInt::random_integer(rng, 1, q);
+#endif
+
+ const BigInt k_inv = m_group.inverse_mod_q(k);
+
+ const BigInt r = m_group.mod_q(m_group.power_g_p(k, m_group.q_bits()));
+
+ /*
+ * 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 = m_group.multiply_mod_q(m_b, m);
+ const BigInt xr = m_group.multiply_mod_q(m_b, m_x, r);
+
+ const BigInt s = m_group.multiply_mod_q(m_b_inv, k_inv, m_group.mod_q(xr+m));
+
+ // With overwhelming probability, a bug rather than actual zero r/s
+ if(r.is_zero() || s.is_zero())
+ throw Internal_Error("Computed zero r/s during DSA signature");
+
+ return BigInt::encode_fixed_length_int_pair(r, s, q.bytes());
+ }
+
+/**
+* Object that can verify a DSA signature
+*/
+class DSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
+ {
+ public:
+ DSA_Verification_Operation(const DSA_PublicKey& dsa,
+ const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
+ m_group(dsa.get_group()),
+ m_y(dsa.get_y())
+ {
+ }
+
+ size_t max_input_bits() const override { return m_group.get_q().bits(); }
+
+ bool with_recovery() const override { return false; }
+
+ 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;
+ };
+
+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 size_t q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes || msg_len > q_bytes)
+ return false;
+
+ BigInt r(sig, q_bytes);
+ BigInt s(sig + q_bytes, q_bytes);
+ BigInt i(msg, msg_len, q.bits());
+
+ if(r <= 0 || r >= q || s <= 0 || s >= q)
+ return false;
+
+ 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);
+
+ s = m_group.multi_exponentiate(si, m_y, sr);
+
+ return (m_group.mod_q(s) == r);
+ }
+
+}
+
+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, rng));
+ throw Provider_Not_Found(algo_name(), provider);
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dsa/dsa.h b/src/libs/3rdparty/botan/src/lib/pubkey/dsa/dsa.h
new file mode 100644
index 0000000000..b219a1cf37
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dsa/dsa.h
@@ -0,0 +1,87 @@
+/*
+* DSA
+* (C) 1999-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_DSA_H_
+#define BOTAN_DSA_H_
+
+#include <botan/dl_algo.h>
+
+namespace Botan {
+
+/**
+* DSA Public Key
+*/
+class BOTAN_PUBLIC_API(2,0) DSA_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const override { return "DSA"; }
+
+ DL_Group::Format group_format() const override { return DL_Group::ANSI_X9_57; }
+ size_t message_parts() const override { return 2; }
+ size_t message_part_size() const override { return group_q().bytes(); }
+
+ /**
+ * Load a public key.
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits DER encoded public key bits
+ */
+ DSA_PublicKey(const AlgorithmIdentifier& alg_id,
+ const std::vector<uint8_t>& key_bits) :
+ DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
+ {
+ }
+
+ /**
+ * Create a public key.
+ * @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::unique_ptr<PK_Ops::Verification>
+ create_verification_op(const std::string& params,
+ const std::string& provider) const override;
+ protected:
+ DSA_PublicKey() = default;
+ };
+
+/**
+* DSA Private Key
+*/
+class BOTAN_PUBLIC_API(2,0) DSA_PrivateKey final : public DSA_PublicKey,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ /**
+ * Load a private key.
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits DER encoded key bits in ANSI X9.57 format
+ */
+ DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits);
+
+ /**
+ * Create a private key.
+ * @param rng the RNG to use
+ * @param group the underlying DL group
+ * @param private_key the private key (if zero, a new random key is generated)
+ */
+ DSA_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& group,
+ 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;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/dsa/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/dsa/info.txt
new file mode 100644
index 0000000000..a9f288edea
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/dsa/info.txt
@@ -0,0 +1,12 @@
+<defines>
+DSA -> 20131128
+</defines>
+
+<requires>
+dl_algo
+dl_group
+keypair
+numbertheory
+emsa1
+sha2_32
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/curve_gfp.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/curve_gfp.cpp
new file mode 100644
index 0000000000..bd68a3ed7d
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/curve_gfp.cpp
@@ -0,0 +1,576 @@
+/*
+* Elliptic curves over GF(p) Montgomery Representation
+* (C) 2014,2015,2018 Jack Lloyd
+* 2016 Matthias Gierlings
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/curve_gfp.h>
+#include <botan/curve_nistp.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+#include <botan/internal/mp_core.h>
+#include <botan/internal/mp_asmi.h>
+
+namespace Botan {
+
+namespace {
+
+class CurveGFp_Montgomery final : public CurveGFp_Repr
+ {
+ public:
+ CurveGFp_Montgomery(const BigInt& p, const BigInt& a, const BigInt& b) :
+ m_p(p), m_a(a), m_b(b),
+ m_p_words(m_p.sig_words()),
+ m_p_dash(monty_inverse(m_p.word_at(0)))
+ {
+ Modular_Reducer mod_p(m_p);
+
+ m_r.set_bit(m_p_words * BOTAN_MP_WORD_BITS);
+ m_r = mod_p.reduce(m_r);
+
+ m_r2 = mod_p.square(m_r);
+ m_r3 = mod_p.multiply(m_r, m_r2);
+ m_a_r = mod_p.multiply(m_r, m_a);
+ m_b_r = mod_p.multiply(m_r, m_b);
+
+ m_a_is_zero = m_a.is_zero();
+ m_a_is_minus_3 = (m_a + 3 == m_p);
+ }
+
+ bool a_is_zero() const override { return m_a_is_zero; }
+ bool a_is_minus_3() const override { return m_a_is_minus_3; }
+
+ const BigInt& get_a() const override { return m_a; }
+
+ const BigInt& get_b() const override { return m_b; }
+
+ const BigInt& get_p() const override { return m_p; }
+
+ const BigInt& get_a_rep() const override { return m_a_r; }
+
+ const BigInt& get_b_rep() const override { return m_b_r; }
+
+ const BigInt& get_1_rep() const override { return m_r; }
+
+ bool is_one(const BigInt& x) const override { return x == m_r; }
+
+ size_t get_p_words() const override { return m_p_words; }
+
+ size_t get_ws_size() const override { return 2*m_p_words + 4; }
+
+ void redc_mod_p(BigInt& z, secure_vector<word>& ws) const override;
+
+ BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const override;
+
+ void to_curve_rep(BigInt& x, secure_vector<word>& ws) const override;
+
+ void from_curve_rep(BigInt& x, secure_vector<word>& ws) const override;
+
+ void curve_mul_words(BigInt& z,
+ const word x_words[],
+ const size_t x_size,
+ const BigInt& y,
+ secure_vector<word>& ws) const override;
+
+ void curve_sqr_words(BigInt& z,
+ const word x_words[],
+ size_t x_size,
+ secure_vector<word>& ws) const override;
+
+ private:
+ BigInt m_p;
+ BigInt m_a, m_b;
+ BigInt m_a_r, m_b_r;
+ size_t m_p_words; // cache of m_p.sig_words()
+
+ // Montgomery parameters
+ BigInt m_r, m_r2, m_r3;
+ word m_p_dash;
+
+ bool m_a_is_zero;
+ bool m_a_is_minus_3;
+ };
+
+void CurveGFp_Montgomery::redc_mod_p(BigInt& z, secure_vector<word>& ws) const
+ {
+ z.reduce_below(m_p, ws);
+ }
+
+BigInt CurveGFp_Montgomery::invert_element(const BigInt& x, secure_vector<word>& ws) const
+ {
+ // Should we use Montgomery inverse instead?
+ const BigInt inv = inverse_mod(x, m_p);
+ BigInt res;
+ curve_mul(res, inv, m_r3, ws);
+ return res;
+ }
+
+void CurveGFp_Montgomery::to_curve_rep(BigInt& x, secure_vector<word>& ws) const
+ {
+ const BigInt tx = x;
+ curve_mul(x, tx, m_r2, ws);
+ }
+
+void CurveGFp_Montgomery::from_curve_rep(BigInt& z, secure_vector<word>& ws) const
+ {
+ if(ws.size() < get_ws_size())
+ ws.resize(get_ws_size());
+
+ const size_t output_size = 2*m_p_words + 2;
+ if(z.size() < output_size)
+ z.grow_to(output_size);
+
+ bigint_monty_redc(z.mutable_data(),
+ m_p.data(), m_p_words, m_p_dash,
+ ws.data(), ws.size());
+ }
+
+void CurveGFp_Montgomery::curve_mul_words(BigInt& z,
+ const word x_w[],
+ size_t x_size,
+ const BigInt& y,
+ secure_vector<word>& ws) const
+ {
+ BOTAN_DEBUG_ASSERT(y.sig_words() <= m_p_words);
+
+ if(ws.size() < get_ws_size())
+ ws.resize(get_ws_size());
+
+ const size_t output_size = 2*m_p_words + 2;
+ if(z.size() < output_size)
+ z.grow_to(output_size);
+
+ bigint_mul(z.mutable_data(), z.size(),
+ x_w, x_size, std::min(m_p_words, x_size),
+ y.data(), y.size(), std::min(m_p_words, y.size()),
+ ws.data(), ws.size());
+
+ bigint_monty_redc(z.mutable_data(),
+ m_p.data(), m_p_words, m_p_dash,
+ ws.data(), ws.size());
+ }
+
+void CurveGFp_Montgomery::curve_sqr_words(BigInt& z,
+ const word x[],
+ size_t x_size,
+ secure_vector<word>& ws) const
+ {
+ if(ws.size() < get_ws_size())
+ ws.resize(get_ws_size());
+
+ const size_t output_size = 2*m_p_words + 2;
+ if(z.size() < output_size)
+ z.grow_to(output_size);
+
+ bigint_sqr(z.mutable_data(), z.size(),
+ x, x_size, std::min(m_p_words, x_size),
+ ws.data(), ws.size());
+
+ bigint_monty_redc(z.mutable_data(),
+ m_p.data(), m_p_words, m_p_dash,
+ ws.data(), ws.size());
+ }
+
+class CurveGFp_NIST : public CurveGFp_Repr
+ {
+ public:
+ CurveGFp_NIST(size_t p_bits, const BigInt& a, const BigInt& b) :
+ m_1(1), m_a(a), m_b(b), m_p_words((p_bits + BOTAN_MP_WORD_BITS - 1) / BOTAN_MP_WORD_BITS)
+ {
+ // All Solinas prime curves are assumed a == -3
+ }
+
+ bool a_is_zero() const override { return false; }
+ bool a_is_minus_3() const override { return true; }
+
+ const BigInt& get_a() const override { return m_a; }
+
+ const BigInt& get_b() const override { return m_b; }
+
+ const BigInt& get_1_rep() const override { return m_1; }
+
+ size_t get_p_words() const override { return m_p_words; }
+
+ size_t get_ws_size() const override { return 2*m_p_words + 4; }
+
+ const BigInt& get_a_rep() const override { return m_a; }
+
+ const BigInt& get_b_rep() const override { return m_b; }
+
+ bool is_one(const BigInt& x) const override { return x == 1; }
+
+ void to_curve_rep(BigInt& x, secure_vector<word>& ws) const override
+ { redc_mod_p(x, ws); }
+
+ void from_curve_rep(BigInt& x, secure_vector<word>& ws) const override
+ { redc_mod_p(x, ws); }
+
+ BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const override;
+
+ void curve_mul_words(BigInt& z,
+ const word x_words[],
+ const size_t x_size,
+ const BigInt& y,
+ secure_vector<word>& ws) const override;
+
+ void curve_mul_tmp(BigInt& x, const BigInt& y, BigInt& tmp, secure_vector<word>& ws) const
+ {
+ curve_mul(tmp, x, y, ws);
+ x.swap(tmp);
+ }
+
+ void curve_sqr_tmp(BigInt& x, BigInt& tmp, secure_vector<word>& ws) const
+ {
+ curve_sqr(tmp, x, ws);
+ x.swap(tmp);
+ }
+
+ void curve_sqr_words(BigInt& z,
+ const word x_words[],
+ size_t x_size,
+ secure_vector<word>& ws) const override;
+ private:
+ // Curve parameters
+ BigInt m_1;
+ BigInt m_a, m_b;
+ size_t m_p_words; // cache of m_p.sig_words()
+ };
+
+BigInt CurveGFp_NIST::invert_element(const BigInt& x, secure_vector<word>& ws) const
+ {
+ BOTAN_UNUSED(ws);
+ return inverse_mod(x, get_p());
+ }
+
+void CurveGFp_NIST::curve_mul_words(BigInt& z,
+ const word x_w[],
+ size_t x_size,
+ const BigInt& y,
+ secure_vector<word>& ws) const
+ {
+ BOTAN_DEBUG_ASSERT(y.sig_words() <= m_p_words);
+
+ if(ws.size() < get_ws_size())
+ ws.resize(get_ws_size());
+
+ const size_t output_size = 2*m_p_words + 2;
+ if(z.size() < output_size)
+ z.grow_to(output_size);
+
+ bigint_mul(z.mutable_data(), z.size(),
+ x_w, x_size, std::min(m_p_words, x_size),
+ y.data(), y.size(), std::min(m_p_words, y.size()),
+ ws.data(), ws.size());
+
+ this->redc_mod_p(z, ws);
+ }
+
+void CurveGFp_NIST::curve_sqr_words(BigInt& z, const word x[], size_t x_size,
+ secure_vector<word>& ws) const
+ {
+ if(ws.size() < get_ws_size())
+ ws.resize(get_ws_size());
+
+ const size_t output_size = 2*m_p_words + 2;
+ if(z.size() < output_size)
+ z.grow_to(output_size);
+
+ bigint_sqr(z.mutable_data(), output_size,
+ x, x_size, std::min(m_p_words, x_size),
+ ws.data(), ws.size());
+
+ this->redc_mod_p(z, ws);
+ }
+
+#if defined(BOTAN_HAS_NIST_PRIME_REDUCERS_W32)
+
+/**
+* The NIST P-192 curve
+*/
+class CurveGFp_P192 final : public CurveGFp_NIST
+ {
+ public:
+ CurveGFp_P192(const BigInt& a, const BigInt& b) : CurveGFp_NIST(192, a, b) {}
+ const BigInt& get_p() const override { return prime_p192(); }
+ private:
+ void redc_mod_p(BigInt& x, secure_vector<word>& ws) const override { redc_p192(x, ws); }
+ };
+
+/**
+* The NIST P-224 curve
+*/
+class CurveGFp_P224 final : public CurveGFp_NIST
+ {
+ public:
+ CurveGFp_P224(const BigInt& a, const BigInt& b) : CurveGFp_NIST(224, a, b) {}
+ const BigInt& get_p() const override { return prime_p224(); }
+ private:
+ void redc_mod_p(BigInt& x, secure_vector<word>& ws) const override { redc_p224(x, ws); }
+ };
+
+/**
+* The NIST P-256 curve
+*/
+class CurveGFp_P256 final : public CurveGFp_NIST
+ {
+ public:
+ CurveGFp_P256(const BigInt& a, const BigInt& b) : CurveGFp_NIST(256, a, b) {}
+ const BigInt& get_p() const override { return prime_p256(); }
+ private:
+ void redc_mod_p(BigInt& x, secure_vector<word>& ws) const override { redc_p256(x, ws); }
+ BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const override;
+ };
+
+BigInt CurveGFp_P256::invert_element(const BigInt& x, secure_vector<word>& ws) const
+ {
+ BigInt r, p2, p4, p8, p16, p32, tmp;
+
+ curve_sqr(r, x, ws);
+
+ curve_mul(p2, r, x, ws);
+ curve_sqr(r, p2, ws);
+ curve_sqr_tmp(r, tmp, ws);
+
+ curve_mul(p4, r, p2, ws);
+
+ curve_sqr(r, p4, ws);
+ for(size_t i = 0; i != 3; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul(p8, r, p4, ws);;
+
+ curve_sqr(r, p8, ws);
+ for(size_t i = 0; i != 7; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul(p16, r, p8, ws);
+
+ curve_sqr(r, p16, ws);
+ for(size_t i = 0; i != 15; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul(p32, r, p16, ws);
+
+ curve_sqr(r, p32, ws);
+ for(size_t i = 0; i != 31; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+
+ for(size_t i = 0; i != 32*4; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, p32, tmp, ws);
+
+ for(size_t i = 0; i != 32; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, p32, tmp, ws);
+
+ for(size_t i = 0; i != 16; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, p16, tmp, ws);
+ for(size_t i = 0; i != 8; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, p8, tmp, ws);
+
+ for(size_t i = 0; i != 4; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, p4, tmp, ws);
+
+ for(size_t i = 0; i != 2; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, p2, tmp, ws);
+
+ for(size_t i = 0; i != 2; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+
+ return r;
+ }
+
+/**
+* The NIST P-384 curve
+*/
+class CurveGFp_P384 final : public CurveGFp_NIST
+ {
+ public:
+ CurveGFp_P384(const BigInt& a, const BigInt& b) : CurveGFp_NIST(384, a, b) {}
+ const BigInt& get_p() const override { return prime_p384(); }
+ private:
+ void redc_mod_p(BigInt& x, secure_vector<word>& ws) const override { redc_p384(x, ws); }
+ BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const override;
+ };
+
+BigInt CurveGFp_P384::invert_element(const BigInt& x, secure_vector<word>& ws) const
+ {
+ BigInt r, x2, x3, x15, x30, tmp, rl;
+
+ r = x;
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+ x2 = r;
+
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+
+ x3 = r;
+
+ for(size_t i = 0; i != 3; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x3, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 6; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ for(size_t i = 0; i != 3; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x3, tmp, ws);
+
+ x15 = r;
+ for(size_t i = 0; i != 15; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x15, tmp, ws);
+
+ x30 = r;
+ for(size_t i = 0; i != 30; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x30, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 60; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 120; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ for(size_t i = 0; i != 15; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x15, tmp, ws);
+
+ for(size_t i = 0; i != 31; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x30, tmp, ws);
+
+ for(size_t i = 0; i != 2; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x2, tmp, ws);
+
+ for(size_t i = 0; i != 94; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x30, tmp, ws);
+
+ for(size_t i = 0; i != 2; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+
+ curve_mul_tmp(r, x, tmp, ws);
+
+ return r;
+ }
+
+#endif
+
+/**
+* The NIST P-521 curve
+*/
+class CurveGFp_P521 final : public CurveGFp_NIST
+ {
+ public:
+ CurveGFp_P521(const BigInt& a, const BigInt& b) : CurveGFp_NIST(521, a, b) {}
+ const BigInt& get_p() const override { return prime_p521(); }
+ private:
+ void redc_mod_p(BigInt& x, secure_vector<word>& ws) const override { redc_p521(x, ws); }
+ BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const override;
+ };
+
+BigInt CurveGFp_P521::invert_element(const BigInt& x, secure_vector<word>& ws) const
+ {
+ BigInt r;
+ BigInt rl;
+ BigInt a7;
+ BigInt tmp;
+
+ curve_sqr(r, x, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+
+ rl = r;
+
+ for(size_t i = 0; i != 3; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+ a7 = r; // need this value later
+
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 8; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 16; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 32; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 64; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 128; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ rl = r;
+ for(size_t i = 0; i != 256; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, rl, tmp, ws);
+
+ for(size_t i = 0; i != 7; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, a7, tmp, ws);
+
+ for(size_t i = 0; i != 2; ++i)
+ curve_sqr_tmp(r, tmp, ws);
+ curve_mul_tmp(r, x, tmp, ws);
+
+ return r;
+ }
+
+}
+
+std::shared_ptr<CurveGFp_Repr>
+CurveGFp::choose_repr(const BigInt& p, const BigInt& a, const BigInt& b)
+ {
+#if defined(BOTAN_HAS_NIST_PRIME_REDUCERS_W32)
+ if(p == prime_p192())
+ return std::shared_ptr<CurveGFp_Repr>(new CurveGFp_P192(a, b));
+ if(p == prime_p224())
+ return std::shared_ptr<CurveGFp_Repr>(new CurveGFp_P224(a, b));
+ if(p == prime_p256())
+ return std::shared_ptr<CurveGFp_Repr>(new CurveGFp_P256(a, b));
+ if(p == prime_p384())
+ return std::shared_ptr<CurveGFp_Repr>(new CurveGFp_P384(a, b));
+#endif
+
+ if(p == prime_p521())
+ return std::shared_ptr<CurveGFp_Repr>(new CurveGFp_P521(a, b));
+
+ return std::shared_ptr<CurveGFp_Repr>(new CurveGFp_Montgomery(p, a, b));
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/curve_gfp.h b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/curve_gfp.h
new file mode 100644
index 0000000000..ce3fe4eba8
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/curve_gfp.h
@@ -0,0 +1,269 @@
+/*
+* Elliptic curves over GF(p)
+*
+* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
+* 2010-2011,2012,2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_GFP_CURVE_H_
+#define BOTAN_GFP_CURVE_H_
+
+#include <botan/bigint.h>
+#include <memory>
+
+namespace Botan {
+
+class BOTAN_UNSTABLE_API CurveGFp_Repr
+ {
+ public:
+ virtual ~CurveGFp_Repr() = default;
+
+ virtual const BigInt& get_p() const = 0;
+ virtual const BigInt& get_a() const = 0;
+ virtual const BigInt& get_b() const = 0;
+
+ virtual size_t get_p_words() const = 0;
+
+ virtual size_t get_ws_size() const = 0;
+
+ virtual bool is_one(const BigInt& x) const = 0;
+
+ virtual bool a_is_zero() const = 0;
+
+ virtual bool a_is_minus_3() const = 0;
+
+ /*
+ * Returns to_curve_rep(get_a())
+ */
+ virtual const BigInt& get_a_rep() const = 0;
+
+ /*
+ * Returns to_curve_rep(get_b())
+ */
+ virtual const BigInt& get_b_rep() const = 0;
+
+ /*
+ * Returns to_curve_rep(1)
+ */
+ virtual const BigInt& get_1_rep() const = 0;
+
+ virtual void redc_mod_p(BigInt& z, secure_vector<word>& ws) const = 0;
+
+ virtual BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const = 0;
+
+ virtual void to_curve_rep(BigInt& x, secure_vector<word>& ws) const = 0;
+
+ virtual void from_curve_rep(BigInt& x, secure_vector<word>& ws) const = 0;
+
+ void curve_mul(BigInt& z, const BigInt& x, const BigInt& y,
+ secure_vector<word>& ws) const
+ {
+ BOTAN_DEBUG_ASSERT(x.sig_words() <= m_p_words);
+ curve_mul_words(z, x.data(), x.size(), y, ws);
+ }
+
+ virtual void curve_mul_words(BigInt& z,
+ const word x_words[],
+ const size_t x_size,
+ const BigInt& y,
+ secure_vector<word>& ws) const = 0;
+
+ void curve_sqr(BigInt& z, const BigInt& x,
+ secure_vector<word>& ws) const
+ {
+ BOTAN_DEBUG_ASSERT(x.sig_words() <= m_p_words);
+ curve_sqr_words(z, x.data(), x.size(), ws);
+ }
+
+ virtual void curve_sqr_words(BigInt& z,
+ const word x_words[],
+ size_t x_size,
+ secure_vector<word>& ws) const = 0;
+ };
+
+/**
+* This class represents an elliptic curve over GF(p)
+*
+* There should not be any reason for applications to use this type.
+* If you need EC primitives use the interfaces EC_Group and PointGFp
+*
+* It is likely this class will be removed entirely in a future major
+* release.
+*/
+class BOTAN_UNSTABLE_API CurveGFp final
+ {
+ public:
+
+ /**
+ * Create an uninitialized CurveGFp
+ */
+ CurveGFp() = default;
+
+ /**
+ * Construct the elliptic curve E: y^2 = x^3 + ax + b over GF(p)
+ * @param p prime number of the field
+ * @param a first coefficient
+ * @param b second coefficient
+ */
+ CurveGFp(const BigInt& p, const BigInt& a, const BigInt& b) :
+ m_repr(choose_repr(p, a, b))
+ {
+ }
+
+ CurveGFp(const CurveGFp&) = default;
+
+ CurveGFp& operator=(const CurveGFp&) = default;
+
+ /**
+ * @return curve coefficient a
+ */
+ const BigInt& get_a() const { return m_repr->get_a(); }
+
+ /**
+ * @return curve coefficient b
+ */
+ const BigInt& get_b() const { return m_repr->get_b(); }
+
+ /**
+ * Get prime modulus of the field of the curve
+ * @return prime modulus of the field of the curve
+ */
+ const BigInt& get_p() const { return m_repr->get_p(); }
+
+ size_t get_p_words() const { return m_repr->get_p_words(); }
+
+ size_t get_ws_size() const { return m_repr->get_ws_size(); }
+
+ const BigInt& get_a_rep() const { return m_repr->get_a_rep(); }
+
+ const BigInt& get_b_rep() const { return m_repr->get_b_rep(); }
+
+ const BigInt& get_1_rep() const { return m_repr->get_1_rep(); }
+
+ bool a_is_minus_3() const { return m_repr->a_is_minus_3(); }
+ bool a_is_zero() const { return m_repr->a_is_zero(); }
+
+ bool is_one(const BigInt& x) const { return m_repr->is_one(x); }
+
+ BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const
+ {
+ return m_repr->invert_element(x, ws);
+ }
+
+ void to_rep(BigInt& x, secure_vector<word>& ws) const
+ {
+ m_repr->to_curve_rep(x, ws);
+ }
+
+ void from_rep(BigInt& x, secure_vector<word>& ws) const
+ {
+ m_repr->from_curve_rep(x, ws);
+ }
+
+ BigInt from_rep(const BigInt& x, secure_vector<word>& ws) const
+ {
+ BigInt xt(x);
+ m_repr->from_curve_rep(xt, ws);
+ return xt;
+ }
+
+ // TODO: from_rep taking && ref
+
+ void redc_mod_p(BigInt& z, secure_vector<word>& ws) const
+ {
+ m_repr->redc_mod_p(z, ws);
+ }
+
+ void mul(BigInt& z, const BigInt& x, const BigInt& y, secure_vector<word>& ws) const
+ {
+ m_repr->curve_mul(z, x, y, ws);
+ }
+
+ void mul(BigInt& z, const word x_w[], size_t x_size,
+ const BigInt& y, secure_vector<word>& ws) const
+ {
+ m_repr->curve_mul_words(z, x_w, x_size, y, ws);
+ }
+
+ void sqr(BigInt& z, const BigInt& x, secure_vector<word>& ws) const
+ {
+ m_repr->curve_sqr(z, x, ws);
+ }
+
+ void sqr(BigInt& z, const word x_w[], size_t x_size, secure_vector<word>& ws) const
+ {
+ m_repr->curve_sqr_words(z, x_w, x_size, ws);
+ }
+
+ BigInt mul(const BigInt& x, const BigInt& y, secure_vector<word>& ws) const
+ {
+ return mul_to_tmp(x, y, ws);
+ }
+
+ BigInt sqr(const BigInt& x, secure_vector<word>& ws) const
+ {
+ return sqr_to_tmp(x, ws);
+ }
+
+ BigInt mul_to_tmp(const BigInt& x, const BigInt& y, secure_vector<word>& ws) const
+ {
+ BigInt z;
+ m_repr->curve_mul(z, x, y, ws);
+ return z;
+ }
+
+ BigInt sqr_to_tmp(const BigInt& x, secure_vector<word>& ws) const
+ {
+ BigInt z;
+ m_repr->curve_sqr(z, x, ws);
+ return z;
+ }
+
+ void swap(CurveGFp& other)
+ {
+ std::swap(m_repr, other.m_repr);
+ }
+
+ /**
+ * Equality operator
+ * @param other a curve
+ * @return true iff *this is the same as other
+ */
+ inline bool operator==(const CurveGFp& other) const
+ {
+ if(m_repr.get() == other.m_repr.get())
+ return true;
+
+ return (get_p() == other.get_p()) &&
+ (get_a() == other.get_a()) &&
+ (get_b() == other.get_b());
+ }
+
+ private:
+ static std::shared_ptr<CurveGFp_Repr>
+ choose_repr(const BigInt& p, const BigInt& a, const BigInt& b);
+
+ std::shared_ptr<CurveGFp_Repr> m_repr;
+ };
+
+inline bool operator!=(const CurveGFp& lhs, const CurveGFp& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+}
+
+namespace std {
+
+template<> inline
+void swap<Botan::CurveGFp>(Botan::CurveGFp& curve1,
+ Botan::CurveGFp& curve2) BOTAN_NOEXCEPT
+ {
+ curve1.swap(curve2);
+ }
+
+} // namespace std
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_group.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_group.cpp
new file mode 100644
index 0000000000..586603507e
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_group.cpp
@@ -0,0 +1,765 @@
+/*
+* ECC Domain Parameters
+*
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* (C) 2008,2018 Jack Lloyd
+* (C) 2018 Tobias Niemann
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/ec_group.h>
+#include <botan/internal/point_mul.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/reducer.h>
+#include <botan/mutex.h>
+#include <botan/rng.h>
+#include <vector>
+
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ #include <botan/system_rng.h>
+#elif defined(BOTAN_HAS_HMAC_DRBG) && defined(BOTAN_HAS_SHA2_32)
+ #include <botan/hmac_drbg.h>
+#endif
+
+namespace Botan {
+
+class EC_Group_Data final
+ {
+ public:
+
+ EC_Group_Data(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const BigInt& g_x,
+ const BigInt& g_y,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid) :
+ m_curve(p, a, b),
+ m_base_point(m_curve, g_x, g_y),
+ m_g_x(g_x),
+ m_g_y(g_y),
+ m_order(order),
+ m_cofactor(cofactor),
+ m_mod_order(order),
+ m_base_mult(m_base_point, m_mod_order),
+ m_oid(oid),
+ m_p_bits(p.bits()),
+ m_order_bits(order.bits()),
+ m_a_is_minus_3(a == p - 3),
+ m_a_is_zero(a.is_zero())
+ {
+ }
+
+ bool match(const BigInt& p, const BigInt& a, const BigInt& b,
+ const BigInt& g_x, const BigInt& g_y,
+ const BigInt& order, const BigInt& cofactor) const
+ {
+ return (this->p() == p &&
+ this->a() == a &&
+ this->b() == b &&
+ this->order() == order &&
+ this->cofactor() == cofactor &&
+ this->g_x() == g_x &&
+ this->g_y() == g_y);
+ }
+
+ const OID& oid() const { return m_oid; }
+ const BigInt& p() const { return m_curve.get_p(); }
+ const BigInt& a() const { return m_curve.get_a(); }
+ const BigInt& b() const { return m_curve.get_b(); }
+ const BigInt& order() const { return m_order; }
+ const BigInt& cofactor() const { return m_cofactor; }
+ const BigInt& g_x() const { return m_g_x; }
+ const BigInt& g_y() const { return m_g_y; }
+
+ size_t p_bits() const { return m_p_bits; }
+ size_t p_bytes() const { return (m_p_bits + 7) / 8; }
+
+ size_t order_bits() const { return m_order_bits; }
+ size_t order_bytes() const { return (m_order_bits + 7) / 8; }
+
+ const CurveGFp& curve() const { return m_curve; }
+ const PointGFp& base_point() const { return m_base_point; }
+
+ bool a_is_minus_3() const { return m_a_is_minus_3; }
+ bool a_is_zero() const { return m_a_is_zero; }
+
+ BigInt mod_order(const BigInt& x) const { return m_mod_order.reduce(x); }
+
+ BigInt square_mod_order(const BigInt& x) const
+ {
+ return m_mod_order.square(x);
+ }
+
+ BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const
+ {
+ return m_mod_order.multiply(x, y);
+ }
+
+ BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const
+ {
+ return m_mod_order.multiply(m_mod_order.multiply(x, y), z);
+ }
+
+ BigInt inverse_mod_order(const BigInt& x) const
+ {
+ return inverse_mod(x, m_order);
+ }
+
+ PointGFp blinded_base_point_multiply(const BigInt& k,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws) const
+ {
+ return m_base_mult.mul(k, rng, m_order, ws);
+ }
+
+ private:
+ CurveGFp m_curve;
+ PointGFp m_base_point;
+
+ BigInt m_g_x;
+ BigInt m_g_y;
+ BigInt m_order;
+ BigInt m_cofactor;
+ Modular_Reducer m_mod_order;
+ PointGFp_Base_Point_Precompute m_base_mult;
+ OID m_oid;
+ size_t m_p_bits;
+ size_t m_order_bits;
+ bool m_a_is_minus_3;
+ bool m_a_is_zero;
+ };
+
+class EC_Group_Data_Map final
+ {
+ public:
+ EC_Group_Data_Map() {}
+
+ size_t clear()
+ {
+ lock_guard_type<mutex_type> lock(m_mutex);
+ size_t count = m_registered_curves.size();
+ m_registered_curves.clear();
+ return count;
+ }
+
+ std::shared_ptr<EC_Group_Data> lookup(const OID& oid)
+ {
+ lock_guard_type<mutex_type> lock(m_mutex);
+
+ for(auto i : m_registered_curves)
+ {
+ if(i->oid() == oid)
+ return i;
+ }
+
+ // Not found, check hardcoded data
+ std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid);
+
+ if(data)
+ {
+ m_registered_curves.push_back(data);
+ return data;
+ }
+
+ // Nope, unknown curve
+ return std::shared_ptr<EC_Group_Data>();
+ }
+
+ std::shared_ptr<EC_Group_Data> lookup_or_create(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const BigInt& g_x,
+ const BigInt& g_y,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid)
+ {
+ lock_guard_type<mutex_type> lock(m_mutex);
+
+ for(auto i : m_registered_curves)
+ {
+ if(oid.has_value())
+ {
+ if(i->oid() == oid)
+ return i;
+ else if(i->oid().has_value())
+ continue;
+ }
+
+ if(i->match(p, a, b, g_x, g_y, order, cofactor))
+ return i;
+ }
+
+ // Not found - if OID is set try looking up that way
+
+ if(oid.has_value())
+ {
+ // Not located in existing store - try hardcoded data set
+ std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid);
+
+ if(data)
+ {
+ m_registered_curves.push_back(data);
+ return data;
+ }
+ }
+
+ // Not found or no OID, add data and return
+ return add_curve(p, a, b, g_x, g_y, order, cofactor, oid);
+ }
+
+ private:
+
+ std::shared_ptr<EC_Group_Data> add_curve(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const BigInt& g_x,
+ const BigInt& g_y,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid)
+ {
+ std::shared_ptr<EC_Group_Data> d =
+ std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid);
+
+ // This function is always called with the lock held
+ m_registered_curves.push_back(d);
+ return d;
+ }
+
+ mutex_type m_mutex;
+ std::vector<std::shared_ptr<EC_Group_Data>> m_registered_curves;
+ };
+
+//static
+EC_Group_Data_Map& EC_Group::ec_group_data()
+ {
+ /*
+ * This exists purely to ensure the allocator is constructed before g_ec_data,
+ * which ensures that its destructor runs after ~g_ec_data is complete.
+ */
+
+ static Allocator_Initializer g_init_allocator;
+ static EC_Group_Data_Map g_ec_data;
+ return g_ec_data;
+ }
+
+//static
+size_t EC_Group::clear_registered_curve_data()
+ {
+ return ec_group_data().clear();
+ }
+
+//static
+std::shared_ptr<EC_Group_Data>
+EC_Group::load_EC_group_info(const char* p_str,
+ const char* a_str,
+ const char* b_str,
+ const char* g_x_str,
+ const char* g_y_str,
+ const char* order_str,
+ const OID& oid)
+ {
+ const BigInt p(p_str);
+ const BigInt a(a_str);
+ const BigInt b(b_str);
+ const BigInt g_x(g_x_str);
+ const BigInt g_y(g_y_str);
+ const BigInt order(order_str);
+ const BigInt cofactor(1); // implicit
+
+ return std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid);
+ }
+
+//static
+std::shared_ptr<EC_Group_Data> EC_Group::BER_decode_EC_group(const uint8_t bits[], size_t len)
+ {
+ BER_Decoder ber(bits, len);
+ BER_Object obj = ber.get_next_object();
+
+ if(obj.type() == NULL_TAG)
+ {
+ throw Decoding_Error("Cannot handle ImplicitCA ECC parameters");
+ }
+ else if(obj.type() == OBJECT_ID)
+ {
+ OID dom_par_oid;
+ BER_Decoder(bits, len).decode(dom_par_oid);
+ return ec_group_data().lookup(dom_par_oid);
+ }
+ else if(obj.type() == SEQUENCE)
+ {
+ BigInt p, a, b, order, cofactor;
+ std::vector<uint8_t> base_pt;
+ std::vector<uint8_t> seed;
+
+ BER_Decoder(bits, len)
+ .start_cons(SEQUENCE)
+ .decode_and_check<size_t>(1, "Unknown ECC param version code")
+ .start_cons(SEQUENCE)
+ .decode_and_check(OID("1.2.840.10045.1.1"),
+ "Only prime ECC fields supported")
+ .decode(p)
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .decode_octet_string_bigint(a)
+ .decode_octet_string_bigint(b)
+ .decode_optional_string(seed, BIT_STRING, BIT_STRING)
+ .end_cons()
+ .decode(base_pt, OCTET_STRING)
+ .decode(order)
+ .decode(cofactor)
+ .end_cons()
+ .verify_end();
+
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ System_RNG rng;
+#elif defined(BOTAN_HAS_HMAC_DRBG) && defined(BOTAN_HAS_SHA2_32)
+ /*
+ * This is not ideal because the data is attacker controlled, but
+ * it seems like it would be difficult for someone to come up
+ * with an valid ASN.1 encoding where the prime happened to pass
+ * Miller-Rabin test with exactly the values chosen when
+ * HMAC_DRBG is seeded with the overall data.
+ */
+ HMAC_DRBG rng("SHA-256");
+ rng.add_entropy(bits, len);
+#else
+ Null_RNG rng;
+#endif
+
+ if(p.bits() < 64 || p.is_negative() || (is_prime(p, rng) == false))
+ throw Decoding_Error("Invalid ECC p parameter");
+
+ if(a.is_negative() || a >= p)
+ throw Decoding_Error("Invalid ECC a parameter");
+
+ if(b <= 0 || b >= p)
+ throw Decoding_Error("Invalid ECC b parameter");
+
+ if(order <= 0)
+ throw Decoding_Error("Invalid ECC order parameter");
+
+ if(cofactor <= 0 || cofactor >= 16)
+ throw Decoding_Error("Invalid ECC cofactor parameter");
+
+ std::pair<BigInt, BigInt> base_xy = Botan::OS2ECP(base_pt.data(), base_pt.size(), p, a, b);
+
+ return ec_group_data().lookup_or_create(p, a, b, base_xy.first, base_xy.second, order, cofactor, OID());
+ }
+ else
+ {
+ throw Decoding_Error("Unexpected tag while decoding ECC domain params");
+ }
+ }
+
+EC_Group::EC_Group()
+ {
+ }
+
+EC_Group::~EC_Group()
+ {
+ // shared_ptr possibly freed here
+ }
+
+EC_Group::EC_Group(const OID& domain_oid)
+ {
+ this->m_data = ec_group_data().lookup(domain_oid);
+ if(!this->m_data)
+ throw Invalid_Argument("Unknown EC_Group " + domain_oid.as_string());
+ }
+
+EC_Group::EC_Group(const std::string& str)
+ {
+ if(str == "")
+ return; // no initialization / uninitialized
+
+ try
+ {
+ OID oid = OIDS::lookup(str);
+ if(oid.empty() == false)
+ m_data = ec_group_data().lookup(oid);
+ }
+ catch(Invalid_OID&)
+ {
+ }
+
+ if(m_data == nullptr)
+ {
+ if(str.size() > 30 && str.substr(0, 29) == "-----BEGIN EC PARAMETERS-----")
+ {
+ // OK try it as PEM ...
+ secure_vector<uint8_t> ber = PEM_Code::decode_check_label(str, "EC PARAMETERS");
+ this->m_data = BER_decode_EC_group(ber.data(), ber.size());
+ }
+ }
+
+ if(m_data == nullptr)
+ throw Invalid_Argument("Unknown ECC group '" + str + "'");
+ }
+
+//static
+std::string EC_Group::PEM_for_named_group(const std::string& name)
+ {
+ try
+ {
+ EC_Group group(name);
+ return group.PEM_encode();
+ }
+ catch(...)
+ {
+ return "";
+ }
+ }
+
+EC_Group::EC_Group(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const BigInt& base_x,
+ const BigInt& base_y,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid)
+ {
+ m_data = ec_group_data().lookup_or_create(p, a, b, base_x, base_y, order, cofactor, oid);
+ }
+
+EC_Group::EC_Group(const std::vector<uint8_t>& ber)
+ {
+ m_data = BER_decode_EC_group(ber.data(), ber.size());
+ }
+
+const EC_Group_Data& EC_Group::data() const
+ {
+ if(m_data == nullptr)
+ throw Invalid_State("EC_Group uninitialized");
+ return *m_data;
+ }
+
+const CurveGFp& EC_Group::get_curve() const
+ {
+ return data().curve();
+ }
+
+bool EC_Group::a_is_minus_3() const
+ {
+ return data().a_is_minus_3();
+ }
+
+bool EC_Group::a_is_zero() const
+ {
+ return data().a_is_zero();
+ }
+
+size_t EC_Group::get_p_bits() const
+ {
+ return data().p_bits();
+ }
+
+size_t EC_Group::get_p_bytes() const
+ {
+ return data().p_bytes();
+ }
+
+size_t EC_Group::get_order_bits() const
+ {
+ return data().order_bits();
+ }
+
+size_t EC_Group::get_order_bytes() const
+ {
+ return data().order_bytes();
+ }
+
+const BigInt& EC_Group::get_p() const
+ {
+ return data().p();
+ }
+
+const BigInt& EC_Group::get_a() const
+ {
+ return data().a();
+ }
+
+const BigInt& EC_Group::get_b() const
+ {
+ return data().b();
+ }
+
+const PointGFp& EC_Group::get_base_point() const
+ {
+ return data().base_point();
+ }
+
+const BigInt& EC_Group::get_order() const
+ {
+ return data().order();
+ }
+
+const BigInt& EC_Group::get_g_x() const
+ {
+ return data().g_x();
+ }
+
+const BigInt& EC_Group::get_g_y() const
+ {
+ return data().g_y();
+ }
+
+const BigInt& EC_Group::get_cofactor() const
+ {
+ return data().cofactor();
+ }
+
+BigInt EC_Group::mod_order(const BigInt& k) const
+ {
+ return data().mod_order(k);
+ }
+
+BigInt EC_Group::square_mod_order(const BigInt& x) const
+ {
+ return data().square_mod_order(x);
+ }
+
+BigInt EC_Group::multiply_mod_order(const BigInt& x, const BigInt& y) const
+ {
+ return data().multiply_mod_order(x, y);
+ }
+
+BigInt EC_Group::multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const
+ {
+ return data().multiply_mod_order(x, y, z);
+ }
+
+BigInt EC_Group::inverse_mod_order(const BigInt& x) const
+ {
+ return data().inverse_mod_order(x);
+ }
+
+const OID& EC_Group::get_curve_oid() const
+ {
+ return data().oid();
+ }
+
+PointGFp EC_Group::OS2ECP(const uint8_t bits[], size_t len) const
+ {
+ return Botan::OS2ECP(bits, len, data().curve());
+ }
+
+PointGFp EC_Group::point(const BigInt& x, const BigInt& y) const
+ {
+ // TODO: randomize the representation?
+ return PointGFp(data().curve(), x, y);
+ }
+
+PointGFp EC_Group::point_multiply(const BigInt& x, const PointGFp& pt, const BigInt& y) const
+ {
+ PointGFp_Multi_Point_Precompute xy_mul(get_base_point(), pt);
+ return xy_mul.multi_exp(x, y);
+ }
+
+PointGFp EC_Group::blinded_base_point_multiply(const BigInt& k,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws) const
+ {
+ return data().blinded_base_point_multiply(k, rng, ws);
+ }
+
+BigInt EC_Group::blinded_base_point_multiply_x(const BigInt& k,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws) const
+ {
+ const PointGFp pt = data().blinded_base_point_multiply(k, rng, ws);
+
+ if(pt.is_zero())
+ return 0;
+ return pt.get_affine_x();
+ }
+
+BigInt EC_Group::random_scalar(RandomNumberGenerator& rng) const
+ {
+ return BigInt::random_integer(rng, 1, get_order());
+ }
+
+PointGFp EC_Group::blinded_var_point_multiply(const PointGFp& point,
+ const BigInt& k,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws) const
+ {
+ PointGFp_Var_Point_Precompute mul(point, rng, ws);
+ return mul.mul(k, rng, get_order(), ws);
+ }
+
+PointGFp EC_Group::zero_point() const
+ {
+ return PointGFp(data().curve());
+ }
+
+std::vector<uint8_t>
+EC_Group::DER_encode(EC_Group_Encoding form) const
+ {
+ std::vector<uint8_t> output;
+
+ DER_Encoder der(output);
+
+ if(form == EC_DOMPAR_ENC_EXPLICIT)
+ {
+ const size_t ecpVers1 = 1;
+ const OID curve_type("1.2.840.10045.1.1"); // prime field
+
+ const size_t p_bytes = get_p_bytes();
+
+ der.start_cons(SEQUENCE)
+ .encode(ecpVers1)
+ .start_cons(SEQUENCE)
+ .encode(curve_type)
+ .encode(get_p())
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .encode(BigInt::encode_1363(get_a(), p_bytes),
+ OCTET_STRING)
+ .encode(BigInt::encode_1363(get_b(), p_bytes),
+ OCTET_STRING)
+ .end_cons()
+ .encode(get_base_point().encode(PointGFp::UNCOMPRESSED), OCTET_STRING)
+ .encode(get_order())
+ .encode(get_cofactor())
+ .end_cons();
+ }
+ else if(form == EC_DOMPAR_ENC_OID)
+ {
+ const OID oid = get_curve_oid();
+ if(oid.empty())
+ {
+ throw Encoding_Error("Cannot encode EC_Group as OID because OID not set");
+ }
+ der.encode(oid);
+ }
+ else if(form == EC_DOMPAR_ENC_IMPLICITCA)
+ {
+ der.encode_null();
+ }
+ else
+ {
+ throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
+ }
+
+ return output;
+ }
+
+std::string EC_Group::PEM_encode() const
+ {
+ const std::vector<uint8_t> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
+ return PEM_Code::encode(der, "EC PARAMETERS");
+ }
+
+bool EC_Group::operator==(const EC_Group& other) const
+ {
+ if(m_data == other.m_data)
+ return true; // same shared rep
+
+ /*
+ * No point comparing order/cofactor as they are uniquely determined
+ * by the curve equation (p,a,b) and the base point.
+ */
+ return (get_p() == other.get_p() &&
+ get_a() == other.get_a() &&
+ get_b() == other.get_b() &&
+ get_g_x() == other.get_g_x() &&
+ get_g_y() == other.get_g_y());
+ }
+
+bool EC_Group::verify_public_element(const PointGFp& point) const
+ {
+ //check that public point is not at infinity
+ if(point.is_zero())
+ return false;
+
+ //check that public point is on the curve
+ if(point.on_the_curve() == false)
+ return false;
+
+ //check that public point has order q
+ if((point * get_order()).is_zero() == false)
+ return false;
+
+ if(get_cofactor() > 1)
+ {
+ if((point * get_cofactor()).is_zero())
+ return false;
+ }
+
+ return true;
+ }
+
+bool EC_Group::verify_group(RandomNumberGenerator& rng,
+ bool) const
+ {
+ const BigInt& p = get_p();
+ const BigInt& a = get_a();
+ const BigInt& b = get_b();
+ const BigInt& order = get_order();
+ const PointGFp& base_point = get_base_point();
+
+ if(a < 0 || a >= p)
+ return false;
+ if(b <= 0 || b >= p)
+ return false;
+ if(order <= 0)
+ return false;
+
+ //check if field modulus is prime
+ if(!is_prime(p, rng, 128))
+ {
+ return false;
+ }
+
+ //check if order is prime
+ if(!is_prime(order, rng, 128))
+ {
+ return false;
+ }
+
+ //compute the discriminant: 4*a^3 + 27*b^2 which must be nonzero
+ const Modular_Reducer mod_p(p);
+
+ const BigInt discriminant = mod_p.reduce(
+ mod_p.multiply(4, mod_p.cube(a)) +
+ mod_p.multiply(27, mod_p.square(b)));
+
+ if(discriminant == 0)
+ {
+ return false;
+ }
+
+ //check for valid cofactor
+ if(get_cofactor() < 1)
+ {
+ return false;
+ }
+
+ //check if the base point is on the curve
+ if(!base_point.on_the_curve())
+ {
+ return false;
+ }
+ if((base_point * get_cofactor()).is_zero())
+ {
+ return false;
+ }
+ //check if order of the base point is correct
+ if(!(base_point * order).is_zero())
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_group.h b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_group.h
new file mode 100644
index 0000000000..f8c1c1a123
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_group.h
@@ -0,0 +1,372 @@
+/*
+* ECC Domain Parameters
+*
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* 2008-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ECC_DOMAIN_PARAMETERS_H_
+#define BOTAN_ECC_DOMAIN_PARAMETERS_H_
+
+#include <botan/point_gfp.h>
+#include <botan/asn1_oid.h>
+#include <memory>
+#include <set>
+
+namespace Botan {
+
+/**
+* This class represents elliptic curce domain parameters
+*/
+enum EC_Group_Encoding {
+ EC_DOMPAR_ENC_EXPLICIT = 0,
+ EC_DOMPAR_ENC_IMPLICITCA = 1,
+ EC_DOMPAR_ENC_OID = 2
+};
+
+class CurveGFp;
+
+class EC_Group_Data;
+class EC_Group_Data_Map;
+
+/**
+* Class representing an elliptic curve
+*
+* The internal representation is stored in a shared_ptr, so copying an
+* EC_Group is inexpensive.
+*/
+class BOTAN_PUBLIC_API(2,0) EC_Group final
+ {
+ public:
+
+ /**
+ * Construct Domain paramers from specified parameters
+ * @param curve elliptic curve
+ * @param base_point a base point
+ * @param order the order of the base point
+ * @param cofactor the cofactor
+ */
+ BOTAN_DEPRECATED("Use version taking all BigInts")
+ EC_Group(const CurveGFp& curve,
+ const PointGFp& base_point,
+ const BigInt& order,
+ const BigInt& cofactor) :
+ EC_Group(curve.get_p(),
+ curve.get_a(),
+ curve.get_b(),
+ base_point.get_affine_x(),
+ base_point.get_affine_y(),
+ order,
+ cofactor) {}
+
+ /**
+ * Construct Domain paramers from specified parameters
+ * @param p the elliptic curve p
+ * @param a the elliptic curve a param
+ * @param b the elliptic curve b param
+ * @param base_x the x coordinate of the base point
+ * @param base_y the y coordinate of the base point
+ * @param order the order of the base point
+ * @param cofactor the cofactor
+ * @param oid an optional OID used to identify this curve
+ */
+ EC_Group(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const BigInt& base_x,
+ const BigInt& base_y,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid = OID());
+
+ /**
+ * Decode a BER encoded ECC domain parameter set
+ * @param ber_encoding the bytes of the BER encoding
+ */
+ explicit EC_Group(const std::vector<uint8_t>& ber_encoding);
+
+ /**
+ * Create an EC domain by OID (or throw if unknown)
+ * @param oid the OID of the EC domain to create
+ */
+ explicit EC_Group(const OID& oid);
+
+ /**
+ * Create an EC domain from PEM encoding (as from PEM_encode), or
+ * from an OID name (eg "secp256r1", or "1.2.840.10045.3.1.7")
+ * @param pem_or_oid PEM-encoded data, or an OID
+ */
+ explicit EC_Group(const std::string& pem_or_oid);
+
+ /**
+ * Create an uninitialized EC_Group
+ */
+ EC_Group();
+
+ ~EC_Group();
+
+ /**
+ * Create the DER encoding of this domain
+ * @param form of encoding to use
+ * @returns bytes encododed as DER
+ */
+ std::vector<uint8_t> DER_encode(EC_Group_Encoding form) const;
+
+ /**
+ * Return the PEM encoding (always in explicit form)
+ * @return string containing PEM data
+ */
+ std::string PEM_encode() const;
+
+ /**
+ * Return domain parameter curve
+ * @result domain parameter curve
+ */
+ BOTAN_DEPRECATED("Avoid CurveGFp") const CurveGFp& get_curve() const;
+
+ /**
+ * Return if a == -3 mod p
+ */
+ bool a_is_minus_3() const;
+
+ /**
+ * Return if a == 0 mod p
+ */
+ bool a_is_zero() const;
+
+ /**
+ * Return the size of p in bits (same as get_p().bits())
+ */
+ size_t get_p_bits() const;
+
+ /**
+ * Return the size of p in bits (same as get_p().bytes())
+ */
+ size_t get_p_bytes() const;
+
+ /**
+ * Return the size of group order in bits (same as get_order().bits())
+ */
+ size_t get_order_bits() const;
+
+ /**
+ * Return the size of p in bytes (same as get_order().bytes())
+ */
+ size_t get_order_bytes() const;
+
+ /**
+ * Return the prime modulus of the field
+ */
+ const BigInt& get_p() const;
+
+ /**
+ * Return the a parameter of the elliptic curve equation
+ */
+ const BigInt& get_a() const;
+
+ /**
+ * Return the b parameter of the elliptic curve equation
+ */
+ const BigInt& get_b() const;
+
+ /**
+ * Return group base point
+ * @result base point
+ */
+ const PointGFp& get_base_point() const;
+
+ /**
+ * Return the x coordinate of the base point
+ */
+ const BigInt& get_g_x() const;
+
+ /**
+ * Return the y coordinate of the base point
+ */
+ const BigInt& get_g_y() const;
+
+ /**
+ * Return the order of the base point
+ * @result order of the base point
+ */
+ const BigInt& get_order() const;
+
+ /*
+ * Reduce x modulo the order
+ */
+ BigInt mod_order(const BigInt& x) const;
+
+ /*
+ * Return inverse of x modulo the order
+ */
+ BigInt inverse_mod_order(const BigInt& x) const;
+
+ /*
+ * Reduce (x*x) modulo the order
+ */
+ BigInt square_mod_order(const BigInt& x) const;
+
+ /*
+ * Reduce (x*y) modulo the order
+ */
+ BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const;
+
+ /*
+ * Reduce (x*y*z) modulo the order
+ */
+ BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const;
+
+ /**
+ * Return the cofactor
+ * @result the cofactor
+ */
+ const BigInt& get_cofactor() const;
+
+ /**
+ * Check if y is a plausible point on the curve
+ *
+ * In particular, checks that it is a point on the curve, not infinity,
+ * and that it has order matching the group.
+ */
+ bool verify_public_element(const PointGFp& y) const;
+
+ /**
+ * Return the OID of these domain parameters
+ * @result the OID as a string
+ */
+ std::string BOTAN_DEPRECATED("Use get_curve_oid") get_oid() const { return get_curve_oid().as_string(); }
+
+ /**
+ * Return the OID of these domain parameters
+ * @result the OID
+ */
+ const OID& get_curve_oid() const;
+
+ /**
+ * Return a point on this curve with the affine values x, y
+ */
+ PointGFp point(const BigInt& x, const BigInt& y) const;
+
+ /**
+ * Multi exponentiate. Not constant time.
+ * @return base_point*x + pt*y
+ */
+ PointGFp point_multiply(const BigInt& x, const PointGFp& pt, const BigInt& y) const;
+
+ /**
+ * Blinded point multiplication, attempts resistance to side channels
+ * @param k the scalar
+ * @param rng a random number generator
+ * @param ws a temp workspace
+ * @return base_point*k
+ */
+ PointGFp blinded_base_point_multiply(const BigInt& k,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws) const;
+
+ /**
+ * Blinded point multiplication, attempts resistance to side channels
+ * Returns just the x coordinate of the point
+ *
+ * @param k the scalar
+ * @param rng a random number generator
+ * @param ws a temp workspace
+ * @return x coordinate of base_point*k
+ */
+ BigInt blinded_base_point_multiply_x(const BigInt& k,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws) const;
+
+ /**
+ * Blinded point multiplication, attempts resistance to side channels
+ * @param point input point
+ * @param k the scalar
+ * @param rng a random number generator
+ * @param ws a temp workspace
+ * @return point*k
+ */
+ PointGFp blinded_var_point_multiply(const PointGFp& point,
+ const BigInt& k,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws) const;
+
+ /**
+ * Return a random scalar ie an integer in [1,order)
+ */
+ BigInt random_scalar(RandomNumberGenerator& rng) const;
+
+ /**
+ * Return the zero (or infinite) point on this curve
+ */
+ PointGFp zero_point() const;
+
+ PointGFp OS2ECP(const uint8_t bits[], size_t len) const;
+
+ template<typename Alloc>
+ PointGFp OS2ECP(const std::vector<uint8_t, Alloc>& vec) const
+ {
+ return this->OS2ECP(vec.data(), vec.size());
+ }
+
+ bool initialized() const { return (m_data != nullptr); }
+
+ /**
+ * Verify EC_Group domain
+ * @returns true if group is valid. false otherwise
+ */
+ bool verify_group(RandomNumberGenerator& rng,
+ bool strong = false) const;
+
+ bool operator==(const EC_Group& other) const;
+
+ /**
+ * Return PEM representation of named EC group
+ * Deprecated: Use EC_Group(name).PEM_encode() if this is needed
+ */
+ static std::string BOTAN_DEPRECATED("See header comment") PEM_for_named_group(const std::string& name);
+
+ /**
+ * Return a set of known named EC groups
+ */
+ static const std::set<std::string>& known_named_groups();
+
+ /*
+ * For internal use only
+ */
+ static std::shared_ptr<EC_Group_Data> EC_group_info(const OID& oid);
+
+ static size_t clear_registered_curve_data();
+
+ private:
+ static EC_Group_Data_Map& ec_group_data();
+
+ static std::shared_ptr<EC_Group_Data> BER_decode_EC_group(const uint8_t bits[], size_t len);
+
+ static std::shared_ptr<EC_Group_Data>
+ load_EC_group_info(const char* p,
+ const char* a,
+ const char* b,
+ const char* g_x,
+ const char* g_y,
+ const char* order,
+ const OID& oid);
+
+ // Member data
+ const EC_Group_Data& data() const;
+ std::shared_ptr<EC_Group_Data> m_data;
+ };
+
+inline bool operator!=(const EC_Group& lhs,
+ const EC_Group& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+// For compatibility with 1.8
+typedef EC_Group EC_Domain_Params;
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_named.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_named.cpp
new file mode 100644
index 0000000000..ba91b5eaaf
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/ec_named.cpp
@@ -0,0 +1,289 @@
+/*
+* List of ECC groups
+* (C) 2013,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/ec_group.h>
+
+namespace Botan {
+
+//static
+std::shared_ptr<EC_Group_Data> EC_Group::EC_group_info(const OID& oid)
+ {
+ // P-256
+ if(oid == OID{1,2,840,10045,3,1,7})
+ return load_EC_group_info("0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ "0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+ "0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+ "0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+ "0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+ "0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ oid);
+
+ // P-384
+ if(oid == OID{1,3,132,0,34})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+ "0xB3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ "0xAA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ "0x3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ oid);
+ // P-521
+ if(oid == OID{1,3,132,0,35})
+ return load_EC_group_info("0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+ "0x51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+ "0xC6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+ "0x11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+ "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+ oid);
+
+ // brainpool160r1
+ if(oid == OID{1,3,36,3,3,2,8,1,1,1})
+ return load_EC_group_info("0xE95E4A5F737059DC60DFC7AD95B3D8139515620F",
+ "0x340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
+ "0x1E589A8595423412134FAA2DBDEC95C8D8675E58",
+ "0xBED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
+ "0x1667CB477A1A8EC338F94741669C976316DA6321",
+ "0xE95E4A5F737059DC60DF5991D45029409E60FC09",
+ oid);
+ // brainpool192r1
+ if(oid == OID{1,3,36,3,3,2,8,1,1,3})
+ return load_EC_group_info("0xC302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
+ "0x6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
+ "0x469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
+ "0xC0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
+ "0x14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
+ "0xC302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
+ oid);
+ // brainpool224r1
+ if(oid == OID{1,3,36,3,3,2,8,1,1,5})
+ return load_EC_group_info("0xD7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
+ "0x68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
+ "0x2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
+ "0xD9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
+ "0x58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
+ "0xD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
+ oid);
+ // brainpool256r1
+ if(oid == OID{1,3,36,3,3,2,8,1,1,7})
+ return load_EC_group_info("0xA9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
+ "0x7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
+ "0x26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
+ "0x8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
+ "0x547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
+ "0xA9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
+ oid);
+ // brainpool320r1
+ if(oid == OID{1,3,36,3,3,2,8,1,1,9})
+ return load_EC_group_info("0xD35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
+ "0x3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
+ "0x520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
+ "0x43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
+ "0x14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
+ "0xD35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
+ oid);
+ // brainpool384r1
+ if(oid == OID{1,3,36,3,3,2,8,1,1,11})
+ return load_EC_group_info("0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
+ "0x7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
+ "0x4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
+ "0x1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
+ "0x8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
+ "0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
+ oid);
+ // brainpool512r1
+ if(oid == OID{1,3,36,3,3,2,8,1,1,13})
+ return load_EC_group_info("0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
+ "0x7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
+ "0x3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
+ "0x81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
+ "0x7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
+ "0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
+ oid);
+ // frp256v1
+ if(oid == OID{1,2,250,1,223,101,256,1})
+ return load_EC_group_info("0xF1FD178C0B3AD58F10126DE8CE42435B3961ADBCABC8CA6DE8FCF353D86E9C03",
+ "0xF1FD178C0B3AD58F10126DE8CE42435B3961ADBCABC8CA6DE8FCF353D86E9C00",
+ "0xEE353FCA5428A9300D4ABA754A44C00FDFEC0C9AE4B1A1803075ED967B7BB73F",
+ "0xB6B3D4C356C139EB31183D4749D423958C27D2DCAF98B70164C97A2DD98F5CFF",
+ "0x6142E0F7C8B204911F9271F0F3ECEF8C2701C307E8E4C9E183115A1554062CFB",
+ "0xF1FD178C0B3AD58F10126DE8CE42435B53DC67E140D2BF941FFDD459C6D655E1",
+ oid);
+ // gost_256A
+ if(oid == OID{1,2,643,2,2,35,1})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94",
+ "0xA6",
+ "0x1",
+ "0x8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893",
+ oid);
+ // secp160k1
+ if(oid == OID{1,3,132,0,9})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
+ "0x0",
+ "0x7",
+ "0x3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
+ "0x938CF935318FDCED6BC28286531733C3F03C4FEE",
+ "0x100000000000000000001B8FA16DFAB9ACA16B6B3",
+ oid);
+ // secp160r1
+ if(oid == OID{1,3,132,0,8})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
+ "0x1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
+ "0x4A96B5688EF573284664698968C38BB913CBFC82",
+ "0x23A628553168947D59DCC912042351377AC5FB32",
+ "0x100000000000000000001F4C8F927AED3CA752257",
+ oid);
+ // secp160r2
+ if(oid == OID{1,3,132,0,30})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
+ "0xB4E134D3FB59EB8BAB57274904664D5AF50388BA",
+ "0x52DCB034293A117E1F4FF11B30F7199D3144CE6D",
+ "0xFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
+ "0x100000000000000000000351EE786A818F3A1A16B",
+ oid);
+ // secp192k1
+ if(oid == OID{1,3,132,0,31})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
+ "0x0",
+ "0x3",
+ "0xDB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
+ "0x9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D",
+ oid);
+ // secp192r1
+ if(oid == OID{1,2,840,10045,3,1,1})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
+ "0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
+ "0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
+ "0x7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
+ oid);
+ // secp224k1
+ if(oid == OID{1,3,132,0,32})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
+ "0x0",
+ "0x5",
+ "0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
+ "0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
+ "0x10000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
+ oid);
+ // secp224r1
+ if(oid == OID{1,3,132,0,33})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
+ "0xB4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
+ "0xB70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
+ "0xBD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
+ oid);
+ // secp256k1
+ if(oid == OID{1,3,132,0,10})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
+ "0x0",
+ "0x7",
+ "0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
+ "0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
+ oid);
+
+ // sm2p256v1
+ if(oid == OID{1,2,156,10197,1,301})
+ return load_EC_group_info("0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
+ "0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
+ "0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
+ "0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
+ "0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
+ "0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
+ oid);
+ // x962_p192v2
+ if(oid == OID{1,2,840,10045,3,1,2})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
+ "0xCC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953",
+ "0xEEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
+ "0x6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31",
+ oid);
+ // x962_p192v3
+ if(oid == OID{1,2,840,10045,3,1,3})
+ return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
+ "0x22123DC2395A05CAA7423DAECCC94760A7D462256BD56916",
+ "0x7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
+ "0x38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13",
+ oid);
+ // x962_p239v1
+ if(oid == OID{1,2,840,10045,3,1,4})
+ return load_EC_group_info("0x7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
+ "0x7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
+ "0x6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A",
+ "0xFFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
+ "0x7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
+ "0x7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B",
+ oid);
+ // x962_p239v2
+ if(oid == OID{1,2,840,10045,3,1,5})
+ return load_EC_group_info("0x7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
+ "0x7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
+ "0x617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C",
+ "0x38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
+ "0x5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
+ "0x7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063",
+ oid);
+ // x962_p239v3
+ if(oid == OID{1,2,840,10045,3,1,6})
+ return load_EC_group_info("0x7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
+ "0x7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
+ "0x255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E",
+ "0x6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
+ "0x1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
+ "0x7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551",
+ oid);
+
+ return std::shared_ptr<EC_Group_Data>();
+ }
+
+//static
+const std::set<std::string>& EC_Group::known_named_groups()
+ {
+ static const std::set<std::string> named_groups = {
+ "secp160k1",
+ "secp160r1",
+ "secp160r2",
+ "secp192k1",
+ "secp192r1",
+ "secp224k1",
+ "secp224r1",
+ "secp256k1",
+ "secp256r1",
+ "secp384r1",
+ "secp521r1",
+ "brainpool160r1",
+ "brainpool192r1",
+ "brainpool224r1",
+ "brainpool256r1",
+ "brainpool320r1",
+ "brainpool384r1",
+ "brainpool512r1",
+ "x962_p192v2",
+ "x962_p192v3",
+ "x962_p239v1",
+ "x962_p239v2",
+ "x962_p239v3",
+ "gost_256A",
+ "frp256v1",
+ "sm2p256v1"
+ };
+ return named_groups;
+ }
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/info.txt
new file mode 100644
index 0000000000..e382e25a5e
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/info.txt
@@ -0,0 +1,20 @@
+<defines>
+ECC_GROUP -> 20170225
+EC_CURVE_GFP -> 20131128
+</defines>
+
+<requires>
+asn1
+numbertheory
+pem
+</requires>
+
+<header:internal>
+point_mul.h
+</header:internal>
+
+<header:public>
+curve_gfp.h
+ec_group.h
+point_gfp.h
+</header:public>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_gfp.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_gfp.cpp
new file mode 100644
index 0000000000..77803de78f
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_gfp.cpp
@@ -0,0 +1,727 @@
+/*
+* Point arithmetic on elliptic curves over GF(p)
+*
+* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
+* 2008-2011,2012,2014,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/point_gfp.h>
+#include <botan/numthry.h>
+#include <botan/rng.h>
+#include <botan/internal/rounding.h>
+
+namespace Botan {
+
+PointGFp::PointGFp(const CurveGFp& curve) :
+ m_curve(curve),
+ m_coord_x(0),
+ m_coord_y(curve.get_1_rep()),
+ m_coord_z(0)
+ {
+ // Assumes Montgomery rep of zero is zero
+ }
+
+PointGFp::PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y) :
+ m_curve(curve),
+ m_coord_x(x),
+ m_coord_y(y),
+ m_coord_z(m_curve.get_1_rep())
+ {
+ if(x <= 0 || x >= curve.get_p())
+ throw Invalid_Argument("Invalid PointGFp affine x");
+ if(y <= 0 || y >= curve.get_p())
+ throw Invalid_Argument("Invalid PointGFp affine y");
+
+ secure_vector<word> monty_ws(m_curve.get_ws_size());
+ m_curve.to_rep(m_coord_x, monty_ws);
+ m_curve.to_rep(m_coord_y, monty_ws);
+ }
+
+void PointGFp::randomize_repr(RandomNumberGenerator& rng)
+ {
+ secure_vector<word> ws(m_curve.get_ws_size());
+ randomize_repr(rng, ws);
+ }
+
+void PointGFp::randomize_repr(RandomNumberGenerator& rng, secure_vector<word>& ws)
+ {
+ const BigInt mask = BigInt::random_integer(rng, 2, m_curve.get_p());
+
+ /*
+ * No reason to convert this to Montgomery representation first,
+ * just pretend the random mask was chosen as Redc(mask) and the
+ * random mask we generated above is in the Montgomery
+ * representation.
+ * //m_curve.to_rep(mask, ws);
+ */
+ const BigInt mask2 = m_curve.sqr_to_tmp(mask, ws);
+ const BigInt mask3 = m_curve.mul_to_tmp(mask2, mask, ws);
+
+ m_coord_x = m_curve.mul_to_tmp(m_coord_x, mask2, ws);
+ m_coord_y = m_curve.mul_to_tmp(m_coord_y, mask3, ws);
+ m_coord_z = m_curve.mul_to_tmp(m_coord_z, mask, ws);
+ }
+
+namespace {
+
+inline void resize_ws(std::vector<BigInt>& ws_bn, size_t cap_size)
+ {
+ BOTAN_ASSERT(ws_bn.size() >= PointGFp::WORKSPACE_SIZE,
+ "Expected size for PointGFp workspace");
+
+ for(size_t i = 0; i != ws_bn.size(); ++i)
+ if(ws_bn[i].size() < cap_size)
+ ws_bn[i].get_word_vector().resize(cap_size);
+ }
+
+inline bool all_zeros(const word x[], size_t len)
+ {
+ word z = 0;
+ for(size_t i = 0; i != len; ++i)
+ z |= x[i];
+ return (z == 0);
+ }
+
+}
+
+void PointGFp::add_affine(const word x_words[], size_t x_size,
+ const word y_words[], size_t y_size,
+ std::vector<BigInt>& ws_bn)
+ {
+ if(all_zeros(x_words, x_size) && all_zeros(y_words, y_size))
+ return;
+
+ if(is_zero())
+ {
+ m_coord_x.set_words(x_words, x_size);
+ m_coord_y.set_words(y_words, y_size);
+ m_coord_z = m_curve.get_1_rep();
+ return;
+ }
+
+ resize_ws(ws_bn, m_curve.get_ws_size());
+
+ secure_vector<word>& ws = ws_bn[0].get_word_vector();
+ secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
+
+ BigInt& T0 = ws_bn[2];
+ BigInt& T1 = ws_bn[3];
+ BigInt& T2 = ws_bn[4];
+ BigInt& T3 = ws_bn[5];
+ BigInt& T4 = ws_bn[6];
+
+ /*
+ https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2
+ simplified with Z2 = 1
+ */
+
+ const BigInt& p = m_curve.get_p();
+
+ m_curve.sqr(T3, m_coord_z, ws); // z1^2
+ m_curve.mul(T4, x_words, x_size, T3, ws); // x2*z1^2
+
+ m_curve.mul(T2, m_coord_z, T3, ws); // z1^3
+ m_curve.mul(T0, y_words, y_size, T2, ws); // y2*z1^3
+
+ T4.mod_sub(m_coord_x, p, sub_ws); // x2*z1^2 - x1*z2^2
+
+ T0.mod_sub(m_coord_y, p, sub_ws);
+
+ if(T4.is_zero())
+ {
+ if(T0.is_zero())
+ {
+ mult2(ws_bn);
+ return;
+ }
+
+ // setting to zero:
+ m_coord_x = 0;
+ m_coord_y = m_curve.get_1_rep();
+ m_coord_z = 0;
+ return;
+ }
+
+ m_curve.sqr(T2, T4, ws);
+
+ m_curve.mul(T3, m_coord_x, T2, ws);
+
+ m_curve.mul(T1, T2, T4, ws);
+
+ m_curve.sqr(m_coord_x, T0, ws);
+ m_coord_x.mod_sub(T1, p, sub_ws);
+ m_coord_x.mod_sub(T3, p, sub_ws);
+ m_coord_x.mod_sub(T3, p, sub_ws);
+
+ T3.mod_sub(m_coord_x, p, sub_ws);
+
+ T2 = m_coord_y;
+ m_curve.mul(T2, T0, T3, ws);
+ m_curve.mul(T3, m_coord_y, T1, ws);
+ T2.mod_sub(T3, p, sub_ws);
+ m_coord_y = T2;
+
+ m_curve.mul(T3, m_coord_z, T4, ws);
+ m_coord_z = T3;
+ }
+
+void PointGFp::add(const word x_words[], size_t x_size,
+ const word y_words[], size_t y_size,
+ const word z_words[], size_t z_size,
+ std::vector<BigInt>& ws_bn)
+ {
+ if(all_zeros(x_words, x_size) && all_zeros(z_words, z_size))
+ return;
+
+ if(is_zero())
+ {
+ m_coord_x.set_words(x_words, x_size);
+ m_coord_y.set_words(y_words, y_size);
+ m_coord_z.set_words(z_words, z_size);
+ return;
+ }
+
+ resize_ws(ws_bn, m_curve.get_ws_size());
+
+ secure_vector<word>& ws = ws_bn[0].get_word_vector();
+ secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
+
+ BigInt& T0 = ws_bn[2];
+ BigInt& T1 = ws_bn[3];
+ BigInt& T2 = ws_bn[4];
+ BigInt& T3 = ws_bn[5];
+ BigInt& T4 = ws_bn[6];
+ BigInt& T5 = ws_bn[7];
+
+ /*
+ https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2
+ */
+
+ const BigInt& p = m_curve.get_p();
+
+ m_curve.sqr(T0, z_words, z_size, ws); // z2^2
+ m_curve.mul(T1, m_coord_x, T0, ws); // x1*z2^2
+ m_curve.mul(T3, z_words, z_size, T0, ws); // z2^3
+ m_curve.mul(T2, m_coord_y, T3, ws); // y1*z2^3
+
+ m_curve.sqr(T3, m_coord_z, ws); // z1^2
+ m_curve.mul(T4, x_words, x_size, T3, ws); // x2*z1^2
+
+ m_curve.mul(T5, m_coord_z, T3, ws); // z1^3
+ m_curve.mul(T0, y_words, y_size, T5, ws); // y2*z1^3
+
+ T4.mod_sub(T1, p, sub_ws); // x2*z1^2 - x1*z2^2
+
+ T0.mod_sub(T2, p, sub_ws);
+
+ if(T4.is_zero())
+ {
+ if(T0.is_zero())
+ {
+ mult2(ws_bn);
+ return;
+ }
+
+ // setting to zero:
+ m_coord_x = 0;
+ m_coord_y = m_curve.get_1_rep();
+ m_coord_z = 0;
+ return;
+ }
+
+ m_curve.sqr(T5, T4, ws);
+
+ m_curve.mul(T3, T1, T5, ws);
+
+ m_curve.mul(T1, T5, T4, ws);
+
+ m_curve.sqr(m_coord_x, T0, ws);
+ m_coord_x.mod_sub(T1, p, sub_ws);
+ m_coord_x.mod_sub(T3, p, sub_ws);
+ m_coord_x.mod_sub(T3, p, sub_ws);
+
+ T3.mod_sub(m_coord_x, p, sub_ws);
+
+ m_curve.mul(m_coord_y, T0, T3, ws);
+ m_curve.mul(T3, T2, T1, ws);
+
+ m_coord_y.mod_sub(T3, p, sub_ws);
+
+ m_curve.mul(T3, z_words, z_size, m_coord_z, ws);
+ m_curve.mul(m_coord_z, T3, T4, ws);
+ }
+
+void PointGFp::mult2i(size_t iterations, std::vector<BigInt>& ws_bn)
+ {
+ if(iterations == 0)
+ return;
+
+ if(m_coord_y.is_zero())
+ {
+ *this = PointGFp(m_curve); // setting myself to zero
+ return;
+ }
+
+ /*
+ TODO we can save 2 squarings per iteration by computing
+ a*Z^4 using values cached from previous iteration
+ */
+ for(size_t i = 0; i != iterations; ++i)
+ mult2(ws_bn);
+ }
+
+// *this *= 2
+void PointGFp::mult2(std::vector<BigInt>& ws_bn)
+ {
+ if(is_zero())
+ return;
+
+ if(m_coord_y.is_zero())
+ {
+ *this = PointGFp(m_curve); // setting myself to zero
+ return;
+ }
+
+ resize_ws(ws_bn, m_curve.get_ws_size());
+
+ secure_vector<word>& ws = ws_bn[0].get_word_vector();
+ secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
+
+ BigInt& T0 = ws_bn[2];
+ BigInt& T1 = ws_bn[3];
+ BigInt& T2 = ws_bn[4];
+ BigInt& T3 = ws_bn[5];
+ BigInt& T4 = ws_bn[6];
+
+ /*
+ https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc
+ */
+ const BigInt& p = m_curve.get_p();
+
+ m_curve.sqr(T0, m_coord_y, ws);
+
+ m_curve.mul(T1, m_coord_x, T0, ws);
+ T1 <<= 2; // * 4
+ m_curve.redc_mod_p(T1, sub_ws);
+
+ if(m_curve.a_is_zero())
+ {
+ // if a == 0 then 3*x^2 + a*z^4 is just 3*x^2
+ m_curve.sqr(T4, m_coord_x, ws); // x^2
+ T4 *= 3; // 3*x^2
+ m_curve.redc_mod_p(T4, sub_ws);
+ }
+ else if(m_curve.a_is_minus_3())
+ {
+ /*
+ if a == -3 then
+ 3*x^2 + a*z^4 == 3*x^2 - 3*z^4 == 3*(x^2-z^4) == 3*(x-z^2)*(x+z^2)
+ */
+ m_curve.sqr(T3, m_coord_z, ws); // z^2
+
+ // (x-z^2)
+ T2 = m_coord_x;
+ T2.mod_sub(T3, p, sub_ws);
+
+ // (x+z^2)
+ T3.mod_add(m_coord_x, p, sub_ws);
+
+ m_curve.mul(T4, T2, T3, ws); // (x-z^2)*(x+z^2)
+
+ T4 *= 3; // 3*(x-z^2)*(x+z^2)
+ m_curve.redc_mod_p(T4, sub_ws);
+ }
+ else
+ {
+ m_curve.sqr(T3, m_coord_z, ws); // z^2
+ m_curve.sqr(T4, T3, ws); // z^4
+ m_curve.mul(T3, m_curve.get_a_rep(), T4, ws); // a*z^4
+
+ m_curve.sqr(T4, m_coord_x, ws); // x^2
+ T4 *= 3; // 3*x^2
+ T4.mod_add(T3, p, sub_ws); // 3*x^2 + a*z^4
+ }
+
+ m_curve.sqr(T2, T4, ws);
+ T2.mod_sub(T1, p, sub_ws);
+ T2.mod_sub(T1, p, sub_ws);
+
+ m_curve.sqr(T3, T0, ws);
+ T3 <<= 3;
+ m_curve.redc_mod_p(T3, sub_ws);
+
+ T1.mod_sub(T2, p, sub_ws);
+
+ m_curve.mul(T0, T4, T1, ws);
+ T0.mod_sub(T3, p, sub_ws);
+
+ m_coord_x = T2;
+
+ m_curve.mul(T2, m_coord_y, m_coord_z, ws);
+ T2 <<= 1;
+ m_curve.redc_mod_p(T2, sub_ws);
+
+ m_coord_y = T0;
+ m_coord_z = T2;
+ }
+
+// arithmetic operators
+PointGFp& PointGFp::operator+=(const PointGFp& rhs)
+ {
+ std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE);
+ add(rhs, ws);
+ return *this;
+ }
+
+PointGFp& PointGFp::operator-=(const PointGFp& rhs)
+ {
+ PointGFp minus_rhs = PointGFp(rhs).negate();
+
+ if(is_zero())
+ *this = minus_rhs;
+ else
+ *this += minus_rhs;
+
+ return *this;
+ }
+
+PointGFp& PointGFp::operator*=(const BigInt& scalar)
+ {
+ *this = scalar * *this;
+ return *this;
+ }
+
+PointGFp operator*(const BigInt& scalar, const PointGFp& point)
+ {
+ BOTAN_DEBUG_ASSERT(point.on_the_curve());
+
+ const size_t scalar_bits = scalar.bits();
+
+ std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE);
+
+ PointGFp R[2] = { point.zero(), point };
+
+ for(size_t i = scalar_bits; i > 0; i--)
+ {
+ const size_t b = scalar.get_bit(i - 1);
+ R[b ^ 1].add(R[b], ws);
+ R[b].mult2(ws);
+ }
+
+ if(scalar.is_negative())
+ R[0].negate();
+
+ BOTAN_DEBUG_ASSERT(R[0].on_the_curve());
+
+ return R[0];
+ }
+
+//static
+void PointGFp::force_all_affine(std::vector<PointGFp>& points,
+ secure_vector<word>& ws)
+ {
+ if(points.size() <= 1)
+ {
+ for(size_t i = 0; i != points.size(); ++i)
+ points[i].force_affine();
+ return;
+ }
+
+ /*
+ For >= 2 points use Montgomery's trick
+
+ See Algorithm 2.26 in "Guide to Elliptic Curve Cryptography"
+ (Hankerson, Menezes, Vanstone)
+
+ TODO is it really necessary to save all k points in c?
+ */
+
+ const CurveGFp& curve = points[0].m_curve;
+ const BigInt& rep_1 = curve.get_1_rep();
+
+ if(ws.size() < curve.get_ws_size())
+ ws.resize(curve.get_ws_size());
+
+ std::vector<BigInt> c(points.size());
+ c[0] = points[0].m_coord_z;
+
+ for(size_t i = 1; i != points.size(); ++i)
+ {
+ curve.mul(c[i], c[i-1], points[i].m_coord_z, ws);
+ }
+
+ BigInt s_inv = curve.invert_element(c[c.size()-1], ws);
+
+ BigInt z_inv, z2_inv, z3_inv;
+
+ for(size_t i = points.size() - 1; i != 0; i--)
+ {
+ PointGFp& point = points[i];
+
+ curve.mul(z_inv, s_inv, c[i-1], ws);
+
+ s_inv = curve.mul_to_tmp(s_inv, point.m_coord_z, ws);
+
+ curve.sqr(z2_inv, z_inv, ws);
+ curve.mul(z3_inv, z2_inv, z_inv, ws);
+ point.m_coord_x = curve.mul_to_tmp(point.m_coord_x, z2_inv, ws);
+ point.m_coord_y = curve.mul_to_tmp(point.m_coord_y, z3_inv, ws);
+ point.m_coord_z = rep_1;
+ }
+
+ curve.sqr(z2_inv, s_inv, ws);
+ curve.mul(z3_inv, z2_inv, s_inv, ws);
+ points[0].m_coord_x = curve.mul_to_tmp(points[0].m_coord_x, z2_inv, ws);
+ points[0].m_coord_y = curve.mul_to_tmp(points[0].m_coord_y, z3_inv, ws);
+ points[0].m_coord_z = rep_1;
+ }
+
+void PointGFp::force_affine()
+ {
+ if(is_zero())
+ throw Invalid_State("Cannot convert zero ECC point to affine");
+
+ secure_vector<word> ws;
+
+ const BigInt z_inv = m_curve.invert_element(m_coord_z, ws);
+ const BigInt z2_inv = m_curve.sqr_to_tmp(z_inv, ws);
+ const BigInt z3_inv = m_curve.mul_to_tmp(z_inv, z2_inv, ws);
+ m_coord_x = m_curve.mul_to_tmp(m_coord_x, z2_inv, ws);
+ m_coord_y = m_curve.mul_to_tmp(m_coord_y, z3_inv, ws);
+ m_coord_z = m_curve.get_1_rep();
+ }
+
+bool PointGFp::is_affine() const
+ {
+ return m_curve.is_one(m_coord_z);
+ }
+
+BigInt PointGFp::get_affine_x() const
+ {
+ if(is_zero())
+ throw Illegal_Transformation("Cannot convert zero point to affine");
+
+ secure_vector<word> monty_ws;
+
+ if(is_affine())
+ return m_curve.from_rep(m_coord_x, monty_ws);
+
+ BigInt z2 = m_curve.sqr_to_tmp(m_coord_z, monty_ws);
+ z2 = m_curve.invert_element(z2, monty_ws);
+
+ BigInt r;
+ m_curve.mul(r, m_coord_x, z2, monty_ws);
+ m_curve.from_rep(r, monty_ws);
+ return r;
+ }
+
+BigInt PointGFp::get_affine_y() const
+ {
+ if(is_zero())
+ throw Illegal_Transformation("Cannot convert zero point to affine");
+
+ secure_vector<word> monty_ws;
+
+ if(is_affine())
+ return m_curve.from_rep(m_coord_y, monty_ws);
+
+ const BigInt z2 = m_curve.sqr_to_tmp(m_coord_z, monty_ws);
+ const BigInt z3 = m_curve.mul_to_tmp(m_coord_z, z2, monty_ws);
+ const BigInt z3_inv = m_curve.invert_element(z3, monty_ws);
+
+ BigInt r;
+ m_curve.mul(r, m_coord_y, z3_inv, monty_ws);
+ m_curve.from_rep(r, monty_ws);
+ return r;
+ }
+
+bool PointGFp::on_the_curve() const
+ {
+ /*
+ Is the point still on the curve?? (If everything is correct, the
+ point is always on its curve; then the function will return true.
+ If somehow the state is corrupted, which suggests a fault attack
+ (or internal computational error), then return false.
+ */
+ if(is_zero())
+ return true;
+
+ secure_vector<word> monty_ws;
+
+ const BigInt y2 = m_curve.from_rep(m_curve.sqr_to_tmp(m_coord_y, monty_ws), monty_ws);
+ const BigInt x3 = m_curve.mul_to_tmp(m_coord_x, m_curve.sqr_to_tmp(m_coord_x, monty_ws), monty_ws);
+ const BigInt ax = m_curve.mul_to_tmp(m_coord_x, m_curve.get_a_rep(), monty_ws);
+ const BigInt z2 = m_curve.sqr_to_tmp(m_coord_z, monty_ws);
+
+ if(m_coord_z == z2) // Is z equal to 1 (in Montgomery form)?
+ {
+ if(y2 != m_curve.from_rep(x3 + ax + m_curve.get_b_rep(), monty_ws))
+ return false;
+ }
+
+ const BigInt z3 = m_curve.mul_to_tmp(m_coord_z, z2, monty_ws);
+ const BigInt ax_z4 = m_curve.mul_to_tmp(ax, m_curve.sqr_to_tmp(z2, monty_ws), monty_ws);
+ const BigInt b_z6 = m_curve.mul_to_tmp(m_curve.get_b_rep(), m_curve.sqr_to_tmp(z3, monty_ws), monty_ws);
+
+ if(y2 != m_curve.from_rep(x3 + ax_z4 + b_z6, monty_ws))
+ return false;
+
+ return true;
+ }
+
+// swaps the states of *this and other, does not throw!
+void PointGFp::swap(PointGFp& other)
+ {
+ m_curve.swap(other.m_curve);
+ m_coord_x.swap(other.m_coord_x);
+ m_coord_y.swap(other.m_coord_y);
+ m_coord_z.swap(other.m_coord_z);
+ }
+
+bool PointGFp::operator==(const PointGFp& other) const
+ {
+ if(m_curve != other.m_curve)
+ return false;
+
+ // If this is zero, only equal if other is also zero
+ if(is_zero())
+ return other.is_zero();
+
+ return (get_affine_x() == other.get_affine_x() &&
+ get_affine_y() == other.get_affine_y());
+ }
+
+// encoding and decoding
+std::vector<uint8_t> PointGFp::encode(PointGFp::Compression_Type format) const
+ {
+ if(is_zero())
+ return std::vector<uint8_t>(1); // single 0 byte
+
+ const size_t p_bytes = m_curve.get_p().bytes();
+
+ const BigInt x = get_affine_x();
+ const BigInt y = get_affine_y();
+
+ std::vector<uint8_t> result;
+
+ if(format == PointGFp::UNCOMPRESSED)
+ {
+ result.resize(1 + 2*p_bytes);
+ result[0] = 0x04;
+ BigInt::encode_1363(&result[1], p_bytes, x);
+ BigInt::encode_1363(&result[1+p_bytes], p_bytes, y);
+ }
+ else if(format == PointGFp::COMPRESSED)
+ {
+ result.resize(1 + p_bytes);
+ result[0] = 0x02 | static_cast<uint8_t>(y.get_bit(0));
+ BigInt::encode_1363(&result[1], p_bytes, x);
+ }
+ else if(format == PointGFp::HYBRID)
+ {
+ result.resize(1 + 2*p_bytes);
+ result[0] = 0x06 | static_cast<uint8_t>(y.get_bit(0));
+ BigInt::encode_1363(&result[1], p_bytes, x);
+ BigInt::encode_1363(&result[1+p_bytes], p_bytes, y);
+ }
+ else
+ throw Invalid_Argument("EC2OSP illegal point encoding");
+
+ return result;
+ }
+
+namespace {
+
+BigInt decompress_point(bool yMod2,
+ const BigInt& x,
+ const BigInt& curve_p,
+ const BigInt& curve_a,
+ const BigInt& curve_b)
+ {
+ BigInt xpow3 = x * x * x;
+
+ BigInt g = curve_a * x;
+ g += xpow3;
+ g += curve_b;
+ g = g % curve_p;
+
+ BigInt z = ressol(g, curve_p);
+
+ if(z < 0)
+ throw Illegal_Point("error during EC point decompression");
+
+ if(z.get_bit(0) != yMod2)
+ z = curve_p - z;
+
+ return z;
+ }
+
+}
+
+PointGFp OS2ECP(const uint8_t data[], size_t data_len,
+ const CurveGFp& curve)
+ {
+ // Should we really be doing this?
+ if(data_len <= 1)
+ return PointGFp(curve); // return zero
+
+ std::pair<BigInt, BigInt> xy = OS2ECP(data, data_len, curve.get_p(), curve.get_a(), curve.get_b());
+
+ PointGFp point(curve, xy.first, xy.second);
+
+ if(!point.on_the_curve())
+ throw Illegal_Point("OS2ECP: Decoded point was not on the curve");
+
+ return point;
+ }
+
+std::pair<BigInt, BigInt> OS2ECP(const uint8_t data[], size_t data_len,
+ const BigInt& curve_p,
+ const BigInt& curve_a,
+ const BigInt& curve_b)
+ {
+ if(data_len <= 1)
+ throw Decoding_Error("OS2ECP invalid point");
+
+ const uint8_t pc = data[0];
+
+ BigInt x, y;
+
+ if(pc == 2 || pc == 3)
+ {
+ //compressed form
+ x = BigInt::decode(&data[1], data_len - 1);
+
+ const bool y_mod_2 = ((pc & 0x01) == 1);
+ y = decompress_point(y_mod_2, x, curve_p, curve_a, curve_b);
+ }
+ else if(pc == 4)
+ {
+ const size_t l = (data_len - 1) / 2;
+
+ // uncompressed form
+ x = BigInt::decode(&data[1], l);
+ y = BigInt::decode(&data[l+1], l);
+ }
+ else if(pc == 6 || pc == 7)
+ {
+ const size_t l = (data_len - 1) / 2;
+
+ // hybrid form
+ x = BigInt::decode(&data[1], l);
+ y = BigInt::decode(&data[l+1], l);
+
+ const bool y_mod_2 = ((pc & 0x01) == 1);
+
+ if(decompress_point(y_mod_2, x, curve_p, curve_a, curve_b) != y)
+ throw Illegal_Point("OS2ECP: Decoding error in hybrid format");
+ }
+ else
+ throw Invalid_Argument("OS2ECP: Unknown format type " + std::to_string(pc));
+
+ return std::make_pair(x, y);
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_gfp.h b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_gfp.h
new file mode 100644
index 0000000000..fa447bf87a
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_gfp.h
@@ -0,0 +1,444 @@
+/*
+* Point arithmetic on elliptic curves over GF(p)
+*
+* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
+* 2008-2011,2014,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_POINT_GFP_H_
+#define BOTAN_POINT_GFP_H_
+
+#include <botan/curve_gfp.h>
+#include <botan/exceptn.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Exception thrown if you try to convert a zero point to an affine
+* coordinate
+*/
+class BOTAN_PUBLIC_API(2,0) Illegal_Transformation final : public Exception
+ {
+ public:
+ explicit Illegal_Transformation(const std::string& err =
+ "Requested transformation is not possible") :
+ Exception(err) {}
+ };
+
+/**
+* Exception thrown if some form of illegal point is decoded
+*/
+class BOTAN_PUBLIC_API(2,0) Illegal_Point final : public Exception
+ {
+ public:
+ explicit Illegal_Point(const std::string& err = "Malformed ECP point detected") :
+ Exception(err) {}
+ };
+
+/**
+* This class represents one point on a curve of GF(p)
+*/
+class BOTAN_PUBLIC_API(2,0) PointGFp final
+ {
+ public:
+ enum Compression_Type {
+ UNCOMPRESSED = 0,
+ COMPRESSED = 1,
+ HYBRID = 2
+ };
+
+ enum { WORKSPACE_SIZE = 8 };
+
+ /**
+ * Construct an uninitialized PointGFp
+ */
+ PointGFp() = default;
+
+ /**
+ * Construct the zero point
+ * @param curve The base curve
+ */
+ explicit PointGFp(const CurveGFp& curve);
+
+ /**
+ * Copy constructor
+ */
+ PointGFp(const PointGFp&) = default;
+
+ /**
+ * Move Constructor
+ */
+ PointGFp(PointGFp&& other)
+ {
+ this->swap(other);
+ }
+
+ /**
+ * Standard Assignment
+ */
+ PointGFp& operator=(const PointGFp&) = default;
+
+ /**
+ * Move Assignment
+ */
+ PointGFp& operator=(PointGFp&& other)
+ {
+ if(this != &other)
+ this->swap(other);
+ return (*this);
+ }
+
+ /**
+ * Construct a point from its affine coordinates
+ * @param curve the base curve
+ * @param x affine x coordinate
+ * @param y affine y coordinate
+ */
+ PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y);
+
+ /**
+ * EC2OSP - elliptic curve to octet string primitive
+ * @param format which format to encode using
+ */
+ std::vector<uint8_t> encode(PointGFp::Compression_Type format) const;
+
+ /**
+ * += Operator
+ * @param rhs the PointGFp to add to the local value
+ * @result resulting PointGFp
+ */
+ PointGFp& operator+=(const PointGFp& rhs);
+
+ /**
+ * -= Operator
+ * @param rhs the PointGFp to subtract from the local value
+ * @result resulting PointGFp
+ */
+ PointGFp& operator-=(const PointGFp& rhs);
+
+ /**
+ * *= Operator
+ * @param scalar the PointGFp to multiply with *this
+ * @result resulting PointGFp
+ */
+ PointGFp& operator*=(const BigInt& scalar);
+
+ /**
+ * Negate this point
+ * @return *this
+ */
+ PointGFp& negate()
+ {
+ if(!is_zero())
+ m_coord_y = m_curve.get_p() - m_coord_y;
+ return *this;
+ }
+
+ /**
+ * get affine x coordinate
+ * @result affine x coordinate
+ */
+ BigInt get_affine_x() const;
+
+ /**
+ * get affine y coordinate
+ * @result affine y coordinate
+ */
+ BigInt get_affine_y() const;
+
+ const BigInt& get_x() const { return m_coord_x; }
+ const BigInt& get_y() const { return m_coord_y; }
+ const BigInt& get_z() const { return m_coord_z; }
+
+ void swap_coords(BigInt& new_x, BigInt& new_y, BigInt& new_z)
+ {
+ m_coord_x.swap(new_x);
+ m_coord_y.swap(new_y);
+ m_coord_z.swap(new_z);
+ }
+
+ /**
+ * Force this point to affine coordinates
+ */
+ void force_affine();
+
+ /**
+ * Force all points on the list to affine coordinates
+ */
+ static void force_all_affine(std::vector<PointGFp>& points,
+ secure_vector<word>& ws);
+
+ bool is_affine() const;
+
+ /**
+ * Is this the point at infinity?
+ * @result true, if this point is at infinity, false otherwise.
+ */
+ bool is_zero() const
+ { return (m_coord_x.is_zero() && m_coord_z.is_zero()); }
+
+ /**
+ * Checks whether the point is to be found on the underlying
+ * curve; used to prevent fault attacks.
+ * @return if the point is on the curve
+ */
+ bool on_the_curve() const;
+
+ /**
+ * swaps the states of *this and other, does not throw!
+ * @param other the object to swap values with
+ */
+ void swap(PointGFp& other);
+
+ /**
+ * Randomize the point representation
+ * The actual value (get_affine_x, get_affine_y) does not change
+ */
+ void randomize_repr(RandomNumberGenerator& rng);
+
+ /**
+ * Randomize the point representation
+ * The actual value (get_affine_x, get_affine_y) does not change
+ */
+ void randomize_repr(RandomNumberGenerator& rng, secure_vector<word>& ws);
+
+ /**
+ * Equality operator
+ */
+ bool operator==(const PointGFp& other) const;
+
+ /**
+ * Point addition
+ * @param other the point to add to *this
+ * @param workspace temp space, at least WORKSPACE_SIZE elements
+ */
+ void add(const PointGFp& other, std::vector<BigInt>& workspace)
+ {
+ BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
+
+ const size_t p_words = m_curve.get_p_words();
+
+ add(other.m_coord_x.data(), std::min(p_words, other.m_coord_x.size()),
+ other.m_coord_y.data(), std::min(p_words, other.m_coord_y.size()),
+ other.m_coord_z.data(), std::min(p_words, other.m_coord_z.size()),
+ workspace);
+ }
+
+ /**
+ * Point addition. Array version.
+ *
+ * @param x_words the words of the x coordinate of the other point
+ * @param x_size size of x_words
+ * @param y_words the words of the y coordinate of the other point
+ * @param y_size size of y_words
+ * @param z_words the words of the z coordinate of the other point
+ * @param z_size size of z_words
+ * @param workspace temp space, at least WORKSPACE_SIZE elements
+ */
+ void add(const word x_words[], size_t x_size,
+ const word y_words[], size_t y_size,
+ const word z_words[], size_t z_size,
+ std::vector<BigInt>& workspace);
+
+ /**
+ * Point addition - mixed J+A
+ * @param other affine point to add - assumed to be affine!
+ * @param workspace temp space, at least WORKSPACE_SIZE elements
+ */
+ void add_affine(const PointGFp& other, std::vector<BigInt>& workspace)
+ {
+ BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
+ BOTAN_DEBUG_ASSERT(other.is_affine());
+
+ const size_t p_words = m_curve.get_p_words();
+ add_affine(other.m_coord_x.data(), std::min(p_words, other.m_coord_x.size()),
+ other.m_coord_y.data(), std::min(p_words, other.m_coord_y.size()),
+ workspace);
+ }
+
+ /**
+ * Point addition - mixed J+A. Array version.
+ *
+ * @param x_words the words of the x coordinate of the other point
+ * @param x_size size of x_words
+ * @param y_words the words of the y coordinate of the other point
+ * @param y_size size of y_words
+ * @param workspace temp space, at least WORKSPACE_SIZE elements
+ */
+ void add_affine(const word x_words[], size_t x_size,
+ const word y_words[], size_t y_size,
+ std::vector<BigInt>& workspace);
+
+ /**
+ * Point doubling
+ * @param workspace temp space, at least WORKSPACE_SIZE elements
+ */
+ void mult2(std::vector<BigInt>& workspace);
+
+ /**
+ * Repeated point doubling
+ * @param i number of doublings to perform
+ * @param workspace temp space, at least WORKSPACE_SIZE elements
+ */
+ void mult2i(size_t i, std::vector<BigInt>& workspace);
+
+ /**
+ * Point addition
+ * @param other the point to add to *this
+ * @param workspace temp space, at least WORKSPACE_SIZE elements
+ * @return other plus *this
+ */
+ PointGFp plus(const PointGFp& other, std::vector<BigInt>& workspace) const
+ {
+ PointGFp x = (*this);
+ x.add(other, workspace);
+ return x;
+ }
+
+ /**
+ * Point doubling
+ * @param workspace temp space, at least WORKSPACE_SIZE elements
+ * @return *this doubled
+ */
+ PointGFp double_of(std::vector<BigInt>& workspace) const
+ {
+ PointGFp x = (*this);
+ x.mult2(workspace);
+ return x;
+ }
+
+ /**
+ * Return the zero (aka infinite) point associated with this curve
+ */
+ PointGFp zero() const { return PointGFp(m_curve); }
+
+ /**
+ * Return base curve of this point
+ * @result the curve over GF(p) of this point
+ *
+ * You should not need to use this
+ */
+ const CurveGFp& get_curve() const { return m_curve; }
+
+ private:
+ CurveGFp m_curve;
+ BigInt m_coord_x, m_coord_y, m_coord_z;
+ };
+
+/**
+* Point multiplication operator
+* @param scalar the scalar value
+* @param point the point value
+* @return scalar*point on the curve
+*/
+BOTAN_PUBLIC_API(2,0) PointGFp operator*(const BigInt& scalar, const PointGFp& point);
+
+/**
+* ECC point multiexponentiation - not constant time!
+* @param p1 a point
+* @param z1 a scalar
+* @param p2 a point
+* @param z2 a scalar
+* @result (p1 * z1 + p2 * z2)
+*/
+BOTAN_PUBLIC_API(2,0) PointGFp multi_exponentiate(
+ const PointGFp& p1, const BigInt& z1,
+ const PointGFp& p2, const BigInt& z2);
+
+// relational operators
+inline bool operator!=(const PointGFp& lhs, const PointGFp& rhs)
+ {
+ return !(rhs == lhs);
+ }
+
+// arithmetic operators
+inline PointGFp operator-(const PointGFp& lhs)
+ {
+ return PointGFp(lhs).negate();
+ }
+
+inline PointGFp operator+(const PointGFp& lhs, const PointGFp& rhs)
+ {
+ PointGFp tmp(lhs);
+ return tmp += rhs;
+ }
+
+inline PointGFp operator-(const PointGFp& lhs, const PointGFp& rhs)
+ {
+ PointGFp tmp(lhs);
+ return tmp -= rhs;
+ }
+
+inline PointGFp operator*(const PointGFp& point, const BigInt& scalar)
+ {
+ return scalar * point;
+ }
+
+// encoding and decoding
+inline secure_vector<uint8_t> BOTAN_DEPRECATED("Use PointGFp::encode")
+ EC2OSP(const PointGFp& point, uint8_t format)
+ {
+ std::vector<uint8_t> enc = point.encode(static_cast<PointGFp::Compression_Type>(format));
+ return secure_vector<uint8_t>(enc.begin(), enc.end());
+ }
+
+/**
+* Perform point decoding
+* Use EC_Group::OS2ECP instead
+*/
+PointGFp BOTAN_PUBLIC_API(2,0) OS2ECP(const uint8_t data[], size_t data_len,
+ const CurveGFp& curve);
+
+/**
+* Perform point decoding
+* Use EC_Group::OS2ECP instead
+*
+* @param data the encoded point
+* @param data_len length of data in bytes
+* @param curve_p the curve equation prime
+* @param curve_a the curve equation a parameter
+* @param curve_b the curve equation b parameter
+*/
+std::pair<BigInt, BigInt> BOTAN_UNSTABLE_API OS2ECP(const uint8_t data[], size_t data_len,
+ const BigInt& curve_p,
+ const BigInt& curve_a,
+ const BigInt& curve_b);
+
+template<typename Alloc>
+PointGFp OS2ECP(const std::vector<uint8_t, Alloc>& data, const CurveGFp& curve)
+ { return OS2ECP(data.data(), data.size(), curve); }
+
+class PointGFp_Var_Point_Precompute;
+
+/**
+* Deprecated API for point multiplication
+* Use EC_Group::blinded_base_point_multiply or EC_Group::blinded_var_point_multiply
+*/
+class BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("See comments") Blinded_Point_Multiply final
+ {
+ public:
+ Blinded_Point_Multiply(const PointGFp& base, const BigInt& order, size_t h = 0);
+
+ ~Blinded_Point_Multiply();
+
+ PointGFp blinded_multiply(const BigInt& scalar, RandomNumberGenerator& rng);
+ private:
+ std::vector<BigInt> m_ws;
+ const BigInt& m_order;
+ std::unique_ptr<PointGFp_Var_Point_Precompute> m_point_mul;
+ };
+
+}
+
+namespace std {
+
+template<>
+inline void swap<Botan::PointGFp>(Botan::PointGFp& x, Botan::PointGFp& y)
+ { x.swap(y); }
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_mul.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_mul.cpp
new file mode 100644
index 0000000000..760f060ced
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_mul.cpp
@@ -0,0 +1,375 @@
+/*
+* (C) 2015,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/point_mul.h>
+#include <botan/rng.h>
+#include <botan/reducer.h>
+#include <botan/internal/rounding.h>
+#include <botan/internal/ct_utils.h>
+
+namespace Botan {
+
+PointGFp multi_exponentiate(const PointGFp& x, const BigInt& z1,
+ const PointGFp& y, const BigInt& z2)
+ {
+ PointGFp_Multi_Point_Precompute xy_mul(x, y);
+ return xy_mul.multi_exp(z1, z2);
+ }
+
+Blinded_Point_Multiply::Blinded_Point_Multiply(const PointGFp& base,
+ const BigInt& order,
+ size_t h) :
+ m_ws(PointGFp::WORKSPACE_SIZE),
+ m_order(order)
+ {
+ BOTAN_UNUSED(h);
+ Null_RNG null_rng;
+ m_point_mul.reset(new PointGFp_Var_Point_Precompute(base, null_rng, m_ws));
+ }
+
+Blinded_Point_Multiply::~Blinded_Point_Multiply()
+ {
+ /* for ~unique_ptr */
+ }
+
+PointGFp Blinded_Point_Multiply::blinded_multiply(const BigInt& scalar,
+ RandomNumberGenerator& rng)
+ {
+ return m_point_mul->mul(scalar, rng, m_order, m_ws);
+ }
+
+PointGFp_Base_Point_Precompute::PointGFp_Base_Point_Precompute(const PointGFp& base,
+ const Modular_Reducer& mod_order) :
+ m_base_point(base),
+ m_mod_order(mod_order),
+ m_p_words(base.get_curve().get_p().sig_words()),
+ m_T_size(base.get_curve().get_p().bits() + PointGFp_SCALAR_BLINDING_BITS + 1)
+ {
+ std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE);
+
+ const size_t p_bits = base.get_curve().get_p().bits();
+
+ /*
+ * Some of the curves (eg secp160k1) have an order slightly larger than
+ * the size of the prime modulus. In all cases they are at most 1 bit
+ * longer. The +1 compensates for this.
+ */
+ const size_t T_bits = round_up(p_bits + PointGFp_SCALAR_BLINDING_BITS + 1, 2) / 2;
+
+ std::vector<PointGFp> T(3*T_bits);
+ T.resize(3*T_bits);
+
+ T[0] = base;
+ T[1] = T[0];
+ T[1].mult2(ws);
+ T[2] = T[1];
+ T[2].add(T[0], ws);
+
+ for(size_t i = 1; i != T_bits; ++i)
+ {
+ T[3*i+0] = T[3*i - 2];
+ T[3*i+0].mult2(ws);
+ T[3*i+1] = T[3*i+0];
+ T[3*i+1].mult2(ws);
+ T[3*i+2] = T[3*i+1];
+ T[3*i+2].add(T[3*i+0], ws);
+ }
+
+ PointGFp::force_all_affine(T, ws[0].get_word_vector());
+
+ m_W.resize(T.size() * 2 * m_p_words);
+
+ word* p = &m_W[0];
+ for(size_t i = 0; i != T.size(); ++i)
+ {
+ T[i].get_x().encode_words(p, m_p_words);
+ p += m_p_words;
+ T[i].get_y().encode_words(p, m_p_words);
+ p += m_p_words;
+ }
+ }
+
+PointGFp PointGFp_Base_Point_Precompute::mul(const BigInt& k,
+ RandomNumberGenerator& rng,
+ const BigInt& group_order,
+ std::vector<BigInt>& ws) const
+ {
+ if(k.is_negative())
+ throw Invalid_Argument("PointGFp_Base_Point_Precompute scalar must be positive");
+
+ // Choose a small mask m and use k' = k + m*order (Coron's 1st countermeasure)
+ const BigInt mask(rng, PointGFp_SCALAR_BLINDING_BITS);
+
+ // Instead of reducing k mod group order should we alter the mask size??
+ const BigInt scalar = m_mod_order.reduce(k) + group_order * mask;
+
+ const size_t windows = round_up(scalar.bits(), 2) / 2;
+
+ const size_t elem_size = 2*m_p_words;
+
+ BOTAN_ASSERT(windows <= m_W.size() / (3*elem_size),
+ "Precomputed sufficient values for scalar mult");
+
+ PointGFp R = m_base_point.zero();
+
+ if(ws.size() < PointGFp::WORKSPACE_SIZE)
+ ws.resize(PointGFp::WORKSPACE_SIZE);
+
+ // the precomputed multiples are not secret so use std::vector
+ std::vector<word> Wt(elem_size);
+
+ for(size_t i = 0; i != windows; ++i)
+ {
+ const size_t window = windows - i - 1;
+ const size_t base_addr = (3*window)*elem_size;
+
+ const word w = scalar.get_substring(2*window, 2);
+
+ const word w_is_1 = CT::is_equal<word>(w, 1);
+ const word w_is_2 = CT::is_equal<word>(w, 2);
+ const word w_is_3 = CT::is_equal<word>(w, 3);
+
+ for(size_t j = 0; j != elem_size; ++j)
+ {
+ const word w1 = m_W[base_addr + 0*elem_size + j];
+ const word w2 = m_W[base_addr + 1*elem_size + j];
+ const word w3 = m_W[base_addr + 2*elem_size + j];
+
+ Wt[j] = CT::select3<word>(w_is_1, w1, w_is_2, w2, w_is_3, w3, 0);
+ }
+
+ R.add_affine(&Wt[0], m_p_words, &Wt[m_p_words], m_p_words, ws);
+
+ if(i == 0)
+ {
+ /*
+ * Since we start with the top bit of the exponent we know the
+ * first window must have a non-zero element, and thus R is
+ * now a point other than the point at infinity.
+ */
+ BOTAN_DEBUG_ASSERT(w != 0);
+ R.randomize_repr(rng, ws[0].get_word_vector());
+ }
+ }
+
+ BOTAN_DEBUG_ASSERT(R.on_the_curve());
+
+ return R;
+ }
+
+PointGFp_Var_Point_Precompute::PointGFp_Var_Point_Precompute(const PointGFp& point,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws) :
+ m_curve(point.get_curve()),
+ m_p_words(m_curve.get_p().sig_words()),
+ m_window_bits(4)
+ {
+ if(ws.size() < PointGFp::WORKSPACE_SIZE)
+ ws.resize(PointGFp::WORKSPACE_SIZE);
+
+ std::vector<PointGFp> U(1U << m_window_bits);
+ U[0] = point.zero();
+ U[1] = point;
+
+ for(size_t i = 2; i < U.size(); i += 2)
+ {
+ U[i] = U[i/2].double_of(ws);
+ U[i+1] = U[i].plus(point, ws);
+ }
+
+ // Hack to handle Blinded_Point_Multiply
+ if(rng.is_seeded())
+ {
+ BigInt& mask = ws[0];
+ BigInt& mask2 = ws[1];
+ BigInt& mask3 = ws[2];
+ BigInt& new_x = ws[3];
+ BigInt& new_y = ws[4];
+ BigInt& new_z = ws[5];
+ secure_vector<word>& tmp = ws[6].get_word_vector();
+
+ const CurveGFp& curve = U[0].get_curve();
+
+ const size_t p_bits = curve.get_p().bits();
+
+ // Skipping zero point since it can't be randomized
+ for(size_t i = 1; i != U.size(); ++i)
+ {
+ mask.randomize(rng, p_bits - 1, false);
+ // Easy way of ensuring mask != 0
+ mask.set_bit(0);
+
+ curve.sqr(mask2, mask, tmp);
+ curve.mul(mask3, mask, mask2, tmp);
+
+ curve.mul(new_x, U[i].get_x(), mask2, tmp);
+ curve.mul(new_y, U[i].get_y(), mask3, tmp);
+ curve.mul(new_z, U[i].get_z(), mask, tmp);
+
+ U[i].swap_coords(new_x, new_y, new_z);
+ }
+ }
+
+ m_T.resize(U.size() * 3 * m_p_words);
+
+ word* p = &m_T[0];
+ for(size_t i = 0; i != U.size(); ++i)
+ {
+ U[i].get_x().encode_words(p , m_p_words);
+ U[i].get_y().encode_words(p + m_p_words, m_p_words);
+ U[i].get_z().encode_words(p + 2*m_p_words, m_p_words);
+ p += 3*m_p_words;
+ }
+ }
+
+PointGFp PointGFp_Var_Point_Precompute::mul(const BigInt& k,
+ RandomNumberGenerator& rng,
+ const BigInt& group_order,
+ std::vector<BigInt>& ws) const
+ {
+ if(k.is_negative())
+ throw Invalid_Argument("PointGFp_Var_Point_Precompute scalar must be positive");
+ if(ws.size() < PointGFp::WORKSPACE_SIZE)
+ ws.resize(PointGFp::WORKSPACE_SIZE);
+
+ // Choose a small mask m and use k' = k + m*order (Coron's 1st countermeasure)
+ const BigInt mask(rng, PointGFp_SCALAR_BLINDING_BITS, false);
+ const BigInt scalar = k + group_order * mask;
+
+ const size_t elem_size = 3*m_p_words;
+ const size_t window_elems = (1ULL << m_window_bits);
+
+ size_t windows = round_up(scalar.bits(), m_window_bits) / m_window_bits;
+ PointGFp R(m_curve);
+ secure_vector<word> e(elem_size);
+
+ if(windows > 0)
+ {
+ windows--;
+
+ const uint32_t w = scalar.get_substring(windows*m_window_bits, m_window_bits);
+
+ clear_mem(e.data(), e.size());
+ for(size_t i = 1; i != window_elems; ++i)
+ {
+ const word wmask = CT::is_equal<word>(w, i);
+
+ for(size_t j = 0; j != elem_size; ++j)
+ {
+ e[j] |= wmask & m_T[i * elem_size + j];
+ }
+ }
+
+ R.add(&e[0], m_p_words, &e[m_p_words], m_p_words, &e[2*m_p_words], m_p_words, ws);
+
+ /*
+ Randomize after adding the first nibble as before the addition R
+ is zero, and we cannot effectively randomize the point
+ representation of the zero point.
+ */
+ R.randomize_repr(rng, ws[0].get_word_vector());
+ }
+
+ while(windows)
+ {
+ R.mult2i(m_window_bits, ws);
+
+ const uint32_t w = scalar.get_substring((windows-1)*m_window_bits, m_window_bits);
+
+ clear_mem(e.data(), e.size());
+ for(size_t i = 1; i != window_elems; ++i)
+ {
+ const word wmask = CT::is_equal<word>(w, i);
+
+ for(size_t j = 0; j != elem_size; ++j)
+ e[j] |= wmask & m_T[i * elem_size + j];
+ }
+
+ R.add(&e[0], m_p_words, &e[m_p_words], m_p_words, &e[2*m_p_words], m_p_words, ws);
+
+ windows--;
+ }
+
+ BOTAN_DEBUG_ASSERT(R.on_the_curve());
+
+ return R;
+ }
+
+
+PointGFp_Multi_Point_Precompute::PointGFp_Multi_Point_Precompute(const PointGFp& x,
+ const PointGFp& y)
+ {
+ std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE);
+
+ PointGFp x2 = x;
+ x2.mult2(ws);
+
+ const PointGFp x3(x2.plus(x, ws));
+
+ PointGFp y2 = y;
+ y2.mult2(ws);
+
+ const PointGFp y3(y2.plus(y, ws));
+
+ m_M.reserve(15);
+
+ m_M.push_back(x);
+ m_M.push_back(x2);
+ m_M.push_back(x3);
+
+ m_M.push_back(y);
+ m_M.push_back(y.plus(x, ws));
+ m_M.push_back(y.plus(x2, ws));
+ m_M.push_back(y.plus(x3, ws));
+
+ m_M.push_back(y2);
+ m_M.push_back(y2.plus(x, ws));
+ m_M.push_back(y2.plus(x2, ws));
+ m_M.push_back(y2.plus(x3, ws));
+
+ m_M.push_back(y3);
+ m_M.push_back(y3.plus(x, ws));
+ m_M.push_back(y3.plus(x2, ws));
+ m_M.push_back(y3.plus(x3, ws));
+
+ PointGFp::force_all_affine(m_M, ws[0].get_word_vector());
+ }
+
+PointGFp PointGFp_Multi_Point_Precompute::multi_exp(const BigInt& z1,
+ const BigInt& z2) const
+ {
+ std::vector<BigInt> ws(PointGFp::WORKSPACE_SIZE);
+
+ const size_t z_bits = round_up(std::max(z1.bits(), z2.bits()), 2);
+
+ PointGFp H = m_M[0].zero();
+
+ for(size_t i = 0; i != z_bits; i += 2)
+ {
+ if(i > 0)
+ {
+ H.mult2i(2, ws);
+ }
+
+ const uint8_t z1_b = z1.get_substring(z_bits - i - 2, 2);
+ const uint8_t z2_b = z2.get_substring(z_bits - i - 2, 2);
+
+ const uint8_t z12 = (4*z2_b) + z1_b;
+
+ // This function is not intended to be const time
+ if(z12)
+ {
+ H.add_affine(m_M[z12-1], ws);
+ }
+ }
+
+ if(z1.is_negative() != z2.is_negative())
+ H.negate();
+
+ return H;
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_mul.h b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_mul.h
new file mode 100644
index 0000000000..dbaae29950
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ec_group/point_mul.h
@@ -0,0 +1,84 @@
+/*
+* (C) 2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_POINT_MUL_H_
+#define BOTAN_POINT_MUL_H_
+
+#include <botan/point_gfp.h>
+
+namespace Botan {
+
+class Modular_Reducer;
+
+static const size_t PointGFp_SCALAR_BLINDING_BITS = 80;
+
+class PointGFp_Base_Point_Precompute final
+ {
+ public:
+ PointGFp_Base_Point_Precompute(const PointGFp& base_point,
+ const Modular_Reducer& mod_order);
+
+ PointGFp mul(const BigInt& k,
+ RandomNumberGenerator& rng,
+ const BigInt& group_order,
+ std::vector<BigInt>& ws) const;
+ private:
+ const PointGFp& m_base_point;
+ const Modular_Reducer& m_mod_order;
+
+ const size_t m_p_words;
+ const size_t m_T_size;
+
+ /*
+ * This is a table of T_size * 3*p_word words
+ */
+ std::vector<word> m_W;
+ };
+
+class PointGFp_Var_Point_Precompute final
+ {
+ public:
+ PointGFp_Var_Point_Precompute(const PointGFp& point,
+ RandomNumberGenerator& rng,
+ std::vector<BigInt>& ws);
+
+ PointGFp mul(const BigInt& k,
+ RandomNumberGenerator& rng,
+ const BigInt& group_order,
+ std::vector<BigInt>& ws) const;
+ private:
+ const CurveGFp m_curve;
+ const size_t m_p_words;
+ const size_t m_window_bits;
+
+ /*
+ * Table of 2^window_bits * 3*2*p_word words
+ * Kept in locked vector since the base point might be sensitive
+ * (normally isn't in most protocols but hard to say anything
+ * categorically.)
+ */
+ secure_vector<word> m_T;
+ };
+
+class PointGFp_Multi_Point_Precompute final
+ {
+ public:
+ PointGFp_Multi_Point_Precompute(const PointGFp& g1,
+ const PointGFp& g2);
+
+ /*
+ * Return (g1*k1 + g2*k2)
+ * Not constant time, intended to use with public inputs
+ */
+ PointGFp multi_exp(const BigInt& k1,
+ const BigInt& k2) const;
+ private:
+ std::vector<PointGFp> m_M;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/ecc_key.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/ecc_key.cpp
new file mode 100644
index 0000000000..2c23c1b47e
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/ecc_key.cpp
@@ -0,0 +1,201 @@
+/*
+* ECC Key implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* Falko Strenzke, FlexSecure GmbH
+* 2008-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/ecc_key.h>
+#include <botan/numthry.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/secmem.h>
+#include <botan/point_gfp.h>
+#include <botan/workfactor.h>
+
+namespace Botan {
+
+size_t EC_PublicKey::key_length() const
+ {
+ return domain().get_p_bits();
+ }
+
+size_t EC_PublicKey::estimated_strength() const
+ {
+ return ecp_work_factor(key_length());
+ }
+
+EC_PublicKey::EC_PublicKey(const EC_Group& dom_par,
+ const PointGFp& pub_point) :
+ m_domain_params(dom_par), m_public_key(pub_point)
+ {
+ if (!dom_par.get_curve_oid().empty())
+ m_domain_encoding = EC_DOMPAR_ENC_OID;
+ else
+ m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+
+#if 0
+ if(domain().get_curve() != public_point().get_curve())
+ throw Invalid_Argument("EC_PublicKey: curve mismatch in constructor");
+#endif
+ }
+
+EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id,
+ const std::vector<uint8_t>& key_bits) :
+ m_domain_params{EC_Group(alg_id.get_parameters())},
+ m_public_key{domain().OS2ECP(key_bits)}
+ {
+ if (!domain().get_curve_oid().empty())
+ m_domain_encoding = EC_DOMPAR_ENC_OID;
+ else
+ m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+ }
+
+bool EC_PublicKey::check_key(RandomNumberGenerator& rng,
+ bool) const
+ {
+ return m_domain_params.verify_group(rng) &&
+ m_domain_params.verify_public_element(public_point());
+ }
+
+
+AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const
+ {
+ return AlgorithmIdentifier(get_oid(), DER_domain());
+ }
+
+std::vector<uint8_t> EC_PublicKey::public_key_bits() const
+ {
+ return public_point().encode(point_encoding());
+ }
+
+void EC_PublicKey::set_point_encoding(PointGFp::Compression_Type enc)
+ {
+ if(enc != PointGFp::COMPRESSED &&
+ enc != PointGFp::UNCOMPRESSED &&
+ enc != PointGFp::HYBRID)
+ throw Invalid_Argument("Invalid point encoding for EC_PublicKey");
+
+ m_point_encoding = enc;
+ }
+
+void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form)
+ {
+ if(form != EC_DOMPAR_ENC_EXPLICIT &&
+ form != EC_DOMPAR_ENC_IMPLICITCA &&
+ form != EC_DOMPAR_ENC_OID)
+ throw Invalid_Argument("Invalid encoding form for EC-key object specified");
+
+ if((form == EC_DOMPAR_ENC_OID) && (m_domain_params.get_curve_oid().empty()))
+ throw Invalid_Argument("Invalid encoding form OID specified for "
+ "EC-key object whose corresponding domain "
+ "parameters are without oid");
+
+ m_domain_encoding = form;
+ }
+
+const BigInt& EC_PrivateKey::private_value() const
+ {
+ if(m_private_key == 0)
+ throw Invalid_State("EC_PrivateKey::private_value - uninitialized");
+
+ return m_private_key;
+ }
+
+/**
+* EC_PrivateKey constructor
+*/
+EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Group& ec_group,
+ const BigInt& x,
+ bool with_modular_inverse)
+ {
+ m_domain_params = ec_group;
+ if (!ec_group.get_curve_oid().empty())
+ m_domain_encoding = EC_DOMPAR_ENC_OID;
+ else
+ m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+
+ if(x == 0)
+ {
+ m_private_key = ec_group.random_scalar(rng);
+ }
+ else
+ {
+ m_private_key = x;
+ }
+
+ // Can't use rng here because ffi load functions use Null_RNG
+ if(with_modular_inverse)
+ {
+ // ECKCDSA
+ m_public_key = domain().get_base_point() * m_domain_params.inverse_mod_order(m_private_key);
+ }
+ else
+ {
+ m_public_key = domain().get_base_point() * m_private_key;
+ }
+
+ BOTAN_ASSERT(m_public_key.on_the_curve(),
+ "Generated public key point was on the curve");
+ }
+
+secure_vector<uint8_t> EC_PrivateKey::private_key_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(static_cast<size_t>(1))
+ .encode(BigInt::encode_1363(m_private_key, m_private_key.bytes()),
+ OCTET_STRING)
+ .end_cons()
+ .get_contents();
+ }
+
+EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits,
+ bool with_modular_inverse)
+ {
+ m_domain_params = EC_Group(alg_id.get_parameters());
+ m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+
+ if (!domain().get_curve_oid().empty())
+ m_domain_encoding = EC_DOMPAR_ENC_OID;
+ else
+ m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+
+ OID key_parameters;
+ secure_vector<uint8_t> public_key_bits;
+
+ BER_Decoder(key_bits)
+ .start_cons(SEQUENCE)
+ .decode_and_check<size_t>(1, "Unknown version code for ECC key")
+ .decode_octet_string_bigint(m_private_key)
+ .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE)
+ .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE)
+ .end_cons();
+
+ if(public_key_bits.empty())
+ {
+ if(with_modular_inverse)
+ {
+ // ECKCDSA
+ m_public_key = domain().get_base_point() * m_domain_params.inverse_mod_order(m_private_key);
+ }
+ else
+ {
+ m_public_key = domain().get_base_point() * m_private_key;
+ }
+
+ BOTAN_ASSERT(m_public_key.on_the_curve(),
+ "Public point derived from loaded key was on the curve");
+ }
+ else
+ {
+ m_public_key = domain().OS2ECP(public_key_bits);
+ // OS2ECP verifies that the point is on the curve
+ }
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/ecc_key.h b/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/ecc_key.h
new file mode 100644
index 0000000000..ec2b5f9be3
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/ecc_key.h
@@ -0,0 +1,172 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ECC_PUBLIC_KEY_BASE_H_
+#define BOTAN_ECC_PUBLIC_KEY_BASE_H_
+
+#include <botan/ec_group.h>
+#include <botan/pk_keys.h>
+
+namespace Botan {
+
+/**
+* This class represents abstract ECC public keys. When encoding a key
+* via an encoder that can be accessed via the corresponding member
+* functions, the key will decide upon its internally stored encoding
+* information whether to encode itself with or without domain
+* parameters, or using the domain parameter oid. Furthermore, a public
+* key without domain parameters can be decoded. In that case, it
+* cannot be used for verification until its domain parameters are set
+* by calling the corresponding member function.
+*/
+class BOTAN_PUBLIC_API(2,0) EC_PublicKey : public virtual Public_Key
+ {
+ public:
+ /**
+ * Create a public key.
+ * @param dom_par EC domain parameters
+ * @param pub_point public point on the curve
+ */
+ EC_PublicKey(const EC_Group& dom_par,
+ const PointGFp& pub_point);
+
+ /**
+ * Load a public key.
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits DER encoded public key bits
+ */
+ EC_PublicKey(const AlgorithmIdentifier& alg_id,
+ const std::vector<uint8_t>& key_bits);
+
+ EC_PublicKey(const EC_PublicKey& other) = default;
+ EC_PublicKey& operator=(const EC_PublicKey& other) = default;
+ virtual ~EC_PublicKey() = default;
+
+ /**
+ * Get the public point of this key.
+ * @throw Invalid_State is thrown if the
+ * domain parameters of this point are not set
+ * @result the public point of this key
+ */
+ const PointGFp& public_point() const { return m_public_key; }
+
+ AlgorithmIdentifier algorithm_identifier() const override;
+
+ std::vector<uint8_t> public_key_bits() const override;
+
+ bool check_key(RandomNumberGenerator& rng,
+ bool strong) const override;
+
+ /**
+ * Get the domain parameters of this key.
+ * @throw Invalid_State is thrown if the
+ * domain parameters of this point are not set
+ * @result the domain parameters of this key
+ */
+ const EC_Group& domain() const { return m_domain_params; }
+
+ /**
+ * Set the domain parameter encoding to be used when encoding this key.
+ * @param enc the encoding to use
+ */
+ void set_parameter_encoding(EC_Group_Encoding enc);
+
+ /**
+ * Set the point encoding method to be used when encoding this key.
+ * @param enc the encoding to use
+ */
+ void set_point_encoding(PointGFp::Compression_Type enc);
+
+ /**
+ * Return the DER encoding of this keys domain in whatever format
+ * is preset for this particular key
+ */
+ std::vector<uint8_t> DER_domain() const
+ { return domain().DER_encode(domain_format()); }
+
+ /**
+ * Get the domain parameter encoding to be used when encoding this key.
+ * @result the encoding to use
+ */
+ EC_Group_Encoding domain_format() const
+ { return m_domain_encoding; }
+
+ /**
+ * Get the point encoding method to be used when encoding this key.
+ * @result the encoding to use
+ */
+ PointGFp::Compression_Type point_encoding() const
+ { return m_point_encoding; }
+
+ size_t key_length() const override;
+ size_t estimated_strength() const override;
+
+ protected:
+ EC_PublicKey() : m_domain_params{}, m_public_key{}, m_domain_encoding(EC_DOMPAR_ENC_EXPLICIT)
+ {}
+
+ EC_Group m_domain_params;
+ PointGFp m_public_key;
+ EC_Group_Encoding m_domain_encoding;
+ PointGFp::Compression_Type m_point_encoding = PointGFp::UNCOMPRESSED;
+ };
+
+/**
+* This abstract class represents ECC private keys
+*/
+class BOTAN_PUBLIC_API(2,0) EC_PrivateKey : public virtual EC_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ /*
+ * If x=0, creates a new private key in the domain
+ * using the given rng. If with_modular_inverse is set,
+ * the public key will be calculated by multiplying
+ * the base point with the modular inverse of
+ * x (as in ECGDSA and ECKCDSA), otherwise by
+ * multiplying directly with x (as in ECDSA).
+ */
+ EC_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Group& domain,
+ const BigInt& x,
+ bool with_modular_inverse=false);
+
+ /*
+ * Creates a new private key object from the
+ * ECPrivateKey structure given in key_bits.
+ * If with_modular_inverse is set,
+ * the public key will be calculated by multiplying
+ * the base point with the modular inverse of
+ * x (as in ECGDSA and ECKCDSA), otherwise by
+ * multiplying directly with x (as in ECDSA).
+ */
+ EC_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits,
+ bool with_modular_inverse=false);
+
+ secure_vector<uint8_t> private_key_bits() const override;
+
+ /**
+ * Get the private key value of this key object.
+ * @result the private key value of this key object
+ */
+ const BigInt& private_value() const;
+
+ EC_PrivateKey(const EC_PrivateKey& other) = default;
+ EC_PrivateKey& operator=(const EC_PrivateKey& other) = default;
+ ~EC_PrivateKey() = default;
+ protected:
+ EC_PrivateKey() = default;
+
+ BigInt m_private_key;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/info.txt
new file mode 100644
index 0000000000..f46c9bb544
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecc_key/info.txt
@@ -0,0 +1,10 @@
+<defines>
+ECC_PUBLIC_KEY_CRYPTO -> 20131128
+</defines>
+
+<requires>
+asn1
+bigint
+ec_group
+numbertheory
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/ecdh.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/ecdh.cpp
new file mode 100644
index 0000000000..59f245a00c
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/ecdh.cpp
@@ -0,0 +1,85 @@
+/*
+* ECDH implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* 2007 Falko Strenzke, FlexSecure GmbH
+* 2008-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/ecdh.h>
+#include <botan/numthry.h>
+#include <botan/internal/pk_ops_impl.h>
+
+#if defined(BOTAN_HAS_OPENSSL)
+ #include <botan/internal/openssl.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+/**
+* ECDH operation
+*/
+class ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF
+ {
+ public:
+
+ ECDH_KA_Operation(const ECDH_PrivateKey& key, const std::string& kdf, RandomNumberGenerator& rng) :
+ PK_Ops::Key_Agreement_with_KDF(kdf),
+ m_group(key.domain()),
+ m_rng(rng)
+ {
+ m_l_times_priv = m_group.inverse_mod_order(m_group.get_cofactor()) * key.private_value();
+ }
+
+ secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override
+ {
+ PointGFp input_point = m_group.get_cofactor() * m_group.OS2ECP(w, w_len);
+ input_point.randomize_repr(m_rng);
+
+ const PointGFp S = m_group.blinded_var_point_multiply(
+ input_point, m_l_times_priv, m_rng, m_ws);
+
+ if(S.on_the_curve() == false)
+ throw Internal_Error("ECDH agreed value was not on the curve");
+ return BigInt::encode_1363(S.get_affine_x(), m_group.get_p_bytes());
+ }
+ private:
+ const EC_Group m_group;
+ BigInt m_l_times_priv;
+ RandomNumberGenerator& m_rng;
+ std::vector<BigInt> m_ws;
+ };
+
+}
+
+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, rng));
+
+ throw Provider_Not_Found(algo_name(), provider);
+ }
+
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/ecdh.h b/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/ecdh.h
new file mode 100644
index 0000000000..f88955ac40
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/ecdh.h
@@ -0,0 +1,106 @@
+/*
+* ECDH
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ECDH_KEY_H_
+#define BOTAN_ECDH_KEY_H_
+
+#include <botan/ecc_key.h>
+
+namespace Botan {
+
+/**
+* This class represents ECDH Public Keys.
+*/
+class BOTAN_PUBLIC_API(2,0) ECDH_PublicKey : public virtual EC_PublicKey
+ {
+ public:
+ /**
+ * Create an ECDH public key.
+ * @param alg_id algorithm identifier
+ * @param key_bits DER encoded public key bits
+ */
+ ECDH_PublicKey(const AlgorithmIdentifier& alg_id,
+ const std::vector<uint8_t>& key_bits) :
+ EC_PublicKey(alg_id, key_bits) {}
+
+ /**
+ * Construct a public key from a given public point.
+ * @param dom_par the domain parameters associated with this key
+ * @param public_point the public point defining this key
+ */
+ ECDH_PublicKey(const EC_Group& dom_par,
+ const PointGFp& public_point) :
+ EC_PublicKey(dom_par, public_point) {}
+
+ /**
+ * Get this keys algorithm name.
+ * @return this keys algorithm name
+ */
+ std::string algo_name() const override { return "ECDH"; }
+
+ /**
+ * @return public point value
+ */
+ std::vector<uint8_t> public_value() const
+ { return public_point().encode(PointGFp::UNCOMPRESSED); }
+
+ /**
+ * @return public point value
+ */
+ std::vector<uint8_t> public_value(PointGFp::Compression_Type format) const
+ { return public_point().encode(format); }
+
+ protected:
+ ECDH_PublicKey() = default;
+ };
+
+/**
+* This class represents ECDH Private Keys.
+*/
+class BOTAN_PUBLIC_API(2,0) ECDH_PrivateKey final : public ECDH_PublicKey,
+ public EC_PrivateKey,
+ public PK_Key_Agreement_Key
+ {
+ public:
+
+ /**
+ * Load a private key.
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits ECPrivateKey bits
+ */
+ ECDH_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits) :
+ EC_PrivateKey(alg_id, key_bits) {}
+
+ /**
+ * Generate a new private key
+ * @param rng a random number generator
+ * @param domain parameters to used for this key
+ * @param x the private key; if zero, a new random key is generated
+ */
+ ECDH_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Group& domain,
+ const BigInt& x = 0) :
+ EC_PrivateKey(rng, domain, x) {}
+
+ std::vector<uint8_t> public_value() const override
+ { return ECDH_PublicKey::public_value(PointGFp::UNCOMPRESSED); }
+
+ std::vector<uint8_t> 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;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/info.txt
new file mode 100644
index 0000000000..11ca921dab
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecdh/info.txt
@@ -0,0 +1,10 @@
+<defines>
+ECDH -> 20131128
+</defines>
+
+<requires>
+asn1
+ec_group
+ecc_key
+numbertheory
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/ecdsa.cpp
new file mode 100644
index 0000000000..2409d8f0d2
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/ecdsa.cpp
@@ -0,0 +1,256 @@
+/*
+* ECDSA implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* 2007 Falko Strenzke, FlexSecure GmbH
+* 2008-2010,2015,2016,2018 Jack Lloyd
+* 2016 René Korthaus
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/ecdsa.h>
+#include <botan/internal/pk_ops_impl.h>
+#include <botan/internal/point_mul.h>
+#include <botan/keypair.h>
+#include <botan/reducer.h>
+#include <botan/emsa.h>
+
+#if defined(BOTAN_HAS_RFC6979_GENERATOR)
+ #include <botan/rfc6979.h>
+#endif
+
+#if defined(BOTAN_HAS_BEARSSL)
+ #include <botan/internal/bearssl.h>
+#endif
+
+#if defined(BOTAN_HAS_OPENSSL)
+ #include <botan/internal/openssl.h>
+#endif
+
+namespace Botan {
+
+bool ECDSA_PrivateKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ if(!public_point().on_the_curve())
+ return false;
+
+ if(!strong)
+ return true;
+
+ return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
+ }
+
+namespace {
+
+/**
+* ECDSA signature operation
+*/
+class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
+ {
+ public:
+
+ ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa,
+ const std::string& emsa,
+ RandomNumberGenerator& rng) :
+ PK_Ops::Signature_with_EMSA(emsa),
+ m_group(ecdsa.domain()),
+ m_x(ecdsa.private_value())
+ {
+#if defined(BOTAN_HAS_RFC6979_GENERATOR)
+ m_rfc6979_hash = hash_for_emsa(emsa);
+#endif
+
+ m_b = m_group.random_scalar(rng);
+ m_b_inv = m_group.inverse_mod_order(m_b);
+ }
+
+ size_t max_input_bits() const override { return m_group.get_order_bits(); }
+
+ secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
+
+ private:
+ const EC_Group m_group;
+ const BigInt& m_x;
+
+#if defined(BOTAN_HAS_RFC6979_GENERATOR)
+ std::string m_rfc6979_hash;
+#endif
+
+ std::vector<BigInt> m_ws;
+
+ BigInt m_b, m_b_inv;
+ };
+
+secure_vector<uint8_t>
+ECDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ BigInt m(msg, msg_len, m_group.get_order_bits());
+
+#if defined(BOTAN_HAS_RFC6979_GENERATOR)
+ const BigInt k = generate_rfc6979_nonce(m_x, m_group.get_order(), m, m_rfc6979_hash);
+#else
+ const BigInt k = m_group.random_scalar(rng);
+#endif
+
+ const BigInt r = m_group.mod_order(
+ m_group.blinded_base_point_multiply_x(k, rng, m_ws));
+
+ const BigInt k_inv = m_group.inverse_mod_order(k);
+
+ /*
+ * Blind the input message and compute x*r+m as (x*r*b + m*b)/b
+ */
+ m_b = m_group.square_mod_order(m_b);
+ m_b_inv = m_group.square_mod_order(m_b_inv);
+
+ m = m_group.multiply_mod_order(m_b, m);
+ const BigInt xr = m_group.multiply_mod_order(m_x, m_b, r);
+
+ const BigInt s = m_group.multiply_mod_order(k_inv, xr + m, m_b_inv);
+
+ // With overwhelming probability, a bug rather than actual zero r/s
+ if(r.is_zero() || s.is_zero())
+ throw Internal_Error("During ECDSA signature generated zero r/s");
+
+ return BigInt::encode_fixed_length_int_pair(r, s, m_group.get_order_bytes());
+ }
+
+/**
+* ECDSA verification operation
+*/
+class ECDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
+ {
+ public:
+ ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa,
+ const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
+ m_group(ecdsa.domain()),
+ m_gy_mul(m_group.get_base_point(), ecdsa.public_point())
+ {
+ }
+
+ size_t max_input_bits() const override { return m_group.get_order_bits(); }
+
+ bool with_recovery() const override { return false; }
+
+ bool verify(const uint8_t msg[], size_t msg_len,
+ const uint8_t sig[], size_t sig_len) override;
+ private:
+ const EC_Group m_group;
+ const PointGFp_Multi_Point_Precompute m_gy_mul;
+ };
+
+bool ECDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
+ const uint8_t sig[], size_t sig_len)
+ {
+ if(sig_len != m_group.get_order_bytes() * 2)
+ return false;
+
+ const BigInt e(msg, msg_len, m_group.get_order_bits());
+
+ const BigInt r(sig, sig_len / 2);
+ const BigInt s(sig + sig_len / 2, sig_len / 2);
+
+ if(r <= 0 || r >= m_group.get_order() || s <= 0 || s >= m_group.get_order())
+ return false;
+
+ const BigInt w = m_group.inverse_mod_order(s);
+
+ const BigInt u1 = m_group.multiply_mod_order(m_group.mod_order(e), w);
+ const BigInt u2 = m_group.multiply_mod_order(r, w);
+ const PointGFp R = m_gy_mul.multi_exp(u1, u2);
+
+ if(R.is_zero())
+ return false;
+
+ const BigInt v = m_group.mod_order(R.get_affine_x());
+ return (v == r);
+ }
+
+}
+
+std::unique_ptr<PK_Ops::Verification>
+ECDSA_PublicKey::create_verification_op(const std::string& params,
+ const std::string& provider) const
+ {
+#if defined(BOTAN_HAS_BEARSSL)
+ if(provider == "bearssl" || provider.empty())
+ {
+ try
+ {
+ return make_bearssl_ecdsa_ver_op(*this, params);
+ }
+ catch(Lookup_Error& e)
+ {
+ if(provider == "bearssl")
+ throw;
+ }
+ }
+#endif
+
+#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_BEARSSL)
+ if(provider == "bearssl" || provider.empty())
+ {
+ try
+ {
+ return make_bearssl_ecdsa_sig_op(*this, params);
+ }
+ catch(Lookup_Error& e)
+ {
+ if(provider == "bearssl")
+ throw;
+ }
+ }
+#endif
+
+#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, rng));
+
+ throw Provider_Not_Found(algo_name(), provider);
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/ecdsa.h b/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/ecdsa.h
new file mode 100644
index 0000000000..2929059c56
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/ecdsa.h
@@ -0,0 +1,98 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ECDSA_KEY_H_
+#define BOTAN_ECDSA_KEY_H_
+
+#include <botan/ecc_key.h>
+
+namespace Botan {
+
+/**
+* This class represents ECDSA Public Keys.
+*/
+class BOTAN_PUBLIC_API(2,0) ECDSA_PublicKey : public virtual EC_PublicKey
+ {
+ public:
+
+ /**
+ * Create a public key from a given public point.
+ * @param dom_par the domain parameters associated with this key
+ * @param public_point the public point defining this key
+ */
+ ECDSA_PublicKey(const EC_Group& dom_par,
+ const PointGFp& public_point) :
+ EC_PublicKey(dom_par, public_point) {}
+
+ /**
+ * Load a public key.
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits DER encoded public key bits
+ */
+ ECDSA_PublicKey(const AlgorithmIdentifier& alg_id,
+ const std::vector<uint8_t>& key_bits) :
+ EC_PublicKey(alg_id, key_bits) {}
+
+ /**
+ * Get this keys algorithm name.
+ * @result this keys algorithm name ("ECDSA")
+ */
+ std::string algo_name() const override { return "ECDSA"; }
+
+ size_t message_parts() const override { return 2; }
+
+ 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() = default;
+ };
+
+/**
+* This class represents ECDSA Private Keys
+*/
+class BOTAN_PUBLIC_API(2,0) ECDSA_PrivateKey final : public ECDSA_PublicKey,
+ public EC_PrivateKey
+ {
+ public:
+
+ /**
+ * Load a private key
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits ECPrivateKey bits
+ */
+ ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits) :
+ EC_PrivateKey(alg_id, key_bits) {}
+
+ /**
+ * Create a private key.
+ * @param rng a random number generator
+ * @param domain parameters to used for this key
+ * @param x the private key (if zero, generate a new random key)
+ */
+ ECDSA_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Group& domain,
+ const BigInt& x = 0) :
+ 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;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/info.txt
new file mode 100644
index 0000000000..6bd32ca175
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/ecdsa/info.txt
@@ -0,0 +1,14 @@
+<defines>
+ECDSA -> 20131128
+</defines>
+
+<requires>
+asn1
+ec_group
+ecc_key
+keypair
+numbertheory
+rng
+emsa1
+sha2_32
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/info.txt
new file mode 100644
index 0000000000..c6e8036e59
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/info.txt
@@ -0,0 +1,31 @@
+<defines>
+PUBLIC_KEY_CRYPTO -> 20131128
+</defines>
+
+<header:public>
+blinding.h
+pk_algs.h
+pk_keys.h
+pk_ops.h
+pk_ops_fwd.h
+pkcs8.h
+pubkey.h
+workfactor.h
+x509_key.h
+</header:public>
+
+<header:internal>
+pk_ops_impl.h
+</header:internal>
+
+<requires>
+asn1
+bigint
+kdf
+pem
+pk_pad
+numbertheory
+rng
+hash
+hex
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/keypair/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/keypair/info.txt
new file mode 100644
index 0000000000..ed85abf691
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/keypair/info.txt
@@ -0,0 +1,6 @@
+<defines>
+KEYPAIR_TESTING -> 20131128
+</defines>
+
+<requires>
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/keypair/keypair.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/keypair/keypair.cpp
new file mode 100644
index 0000000000..e8d88e99f3
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/keypair/keypair.cpp
@@ -0,0 +1,85 @@
+/*
+* Keypair Checks
+* (C) 1999-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/keypair.h>
+#include <botan/pubkey.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+namespace KeyPair {
+
+/*
+* Check an encryption key pair for consistency
+*/
+bool encryption_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& private_key,
+ const Public_Key& public_key,
+ const std::string& padding)
+ {
+ PK_Encryptor_EME encryptor(public_key, rng, padding);
+ PK_Decryptor_EME decryptor(private_key, rng, padding);
+
+ /*
+ Weird corner case, if the key is too small to encrypt anything at
+ all. This can happen with very small RSA keys with PSS
+ */
+ if(encryptor.maximum_input_size() == 0)
+ return true;
+
+ std::vector<uint8_t> plaintext =
+ unlock(rng.random_vec(encryptor.maximum_input_size() - 1));
+
+ std::vector<uint8_t> ciphertext = encryptor.encrypt(plaintext, rng);
+ if(ciphertext == plaintext)
+ return false;
+
+ std::vector<uint8_t> decrypted = unlock(decryptor.decrypt(ciphertext));
+
+ return (plaintext == decrypted);
+ }
+
+/*
+* Check a signature key pair for consistency
+*/
+bool signature_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& private_key,
+ const Public_Key& public_key,
+ const std::string& padding)
+ {
+ PK_Signer signer(private_key, rng, padding);
+ PK_Verifier verifier(public_key, padding);
+
+ std::vector<uint8_t> message(32);
+ rng.randomize(message.data(), message.size());
+
+ std::vector<uint8_t> signature;
+
+ try
+ {
+ signature = signer.sign_message(message, rng);
+ }
+ catch(Encoding_Error&)
+ {
+ return false;
+ }
+
+ if(!verifier.verify_message(message, signature))
+ return false;
+
+ // Now try to check a corrupt signature, ensure it does not succeed
+ ++signature[0];
+
+ if(verifier.verify_message(message, signature))
+ return false;
+
+ return true;
+ }
+
+}
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/keypair/keypair.h b/src/libs/3rdparty/botan/src/lib/pubkey/keypair/keypair.h
new file mode 100644
index 0000000000..4f28f325fd
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/keypair/keypair.h
@@ -0,0 +1,83 @@
+/*
+* Keypair Checks
+* (C) 1999-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_KEYPAIR_CHECKS_H_
+#define BOTAN_KEYPAIR_CHECKS_H_
+
+#include <botan/pk_keys.h>
+
+namespace Botan {
+
+namespace KeyPair {
+
+/**
+* Tests whether the key is consistent for encryption; whether
+* encrypting and then decrypting gives to the original plaintext.
+* @param rng the rng to use
+* @param private_key the key to test
+* @param public_key the key to test
+* @param padding the encryption padding method to use
+* @return true if consistent otherwise false
+*/
+BOTAN_PUBLIC_API(2,0) bool
+encryption_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& private_key,
+ const Public_Key& public_key,
+ const std::string& padding);
+
+/**
+* Tests whether the key is consistent for signatures; whether a
+* signature can be created and then verified
+* @param rng the rng to use
+* @param private_key the key to test
+* @param public_key the key to test
+* @param padding the signature padding method to use
+* @return true if consistent otherwise false
+*/
+BOTAN_PUBLIC_API(2,0) bool
+signature_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& private_key,
+ const Public_Key& public_key,
+ const std::string& padding);
+
+/**
+* Tests whether the key is consistent for encryption; whether
+* encrypting and then decrypting gives to the original plaintext.
+* @param rng the rng to use
+* @param key the key to test
+* @param padding the encryption padding method to use
+* @return true if consistent otherwise false
+*/
+inline bool
+encryption_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& key,
+ const std::string& padding)
+ {
+ return encryption_consistency_check(rng, key, key, padding);
+ }
+
+/**
+* Tests whether the key is consistent for signatures; whether a
+* signature can be created and then verified
+* @param rng the rng to use
+* @param key the key to test
+* @param padding the signature padding method to use
+* @return true if consistent otherwise false
+*/
+inline bool
+signature_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& key,
+ const std::string& padding)
+ {
+ return signature_consistency_check(rng, key, key, padding);
+ }
+
+}
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/info.txt
new file mode 100644
index 0000000000..f8c6d37196
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/info.txt
@@ -0,0 +1,10 @@
+<defines>
+PKCS5_PBES2 -> 20141119
+</defines>
+
+<requires>
+asn1
+cbc
+hmac
+pbkdf2
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/pbes2.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/pbes2.cpp
new file mode 100644
index 0000000000..cfac722d7c
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/pbes2.cpp
@@ -0,0 +1,312 @@
+/*
+* PKCS #5 PBES2
+* (C) 1999-2008,2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/pbes2.h>
+#include <botan/cipher_mode.h>
+#include <botan/pbkdf.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/parsing.h>
+#include <botan/alg_id.h>
+#include <botan/oids.h>
+#include <botan/rng.h>
+
+#if defined(BOTAN_HAS_SCRYPT)
+ #include <botan/scrypt.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+SymmetricKey derive_key(const std::string& passphrase,
+ const AlgorithmIdentifier& kdf_algo,
+ size_t default_key_size)
+ {
+ if(kdf_algo.get_oid() == OIDS::lookup("PKCS5.PBKDF2"))
+ {
+ secure_vector<uint8_t> salt;
+ size_t iterations = 0, key_length = 0;
+
+ AlgorithmIdentifier prf_algo;
+ BER_Decoder(kdf_algo.get_parameters())
+ .start_cons(SEQUENCE)
+ .decode(salt, OCTET_STRING)
+ .decode(iterations)
+ .decode_optional(key_length, INTEGER, UNIVERSAL)
+ .decode_optional(prf_algo, SEQUENCE, CONSTRUCTED,
+ AlgorithmIdentifier("HMAC(SHA-160)",
+ AlgorithmIdentifier::USE_NULL_PARAM))
+ .end_cons();
+
+ if(salt.size() < 8)
+ throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small");
+
+ const std::string prf = OIDS::lookup(prf_algo.get_oid());
+
+ std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(" + prf + ")"));
+
+ if(key_length == 0)
+ key_length = default_key_size;
+
+ return pbkdf->pbkdf_iterations(key_length, passphrase, salt.data(), salt.size(), iterations);
+ }
+#if defined(BOTAN_HAS_SCRYPT)
+ else if(kdf_algo.get_oid() == OIDS::lookup("Scrypt"))
+ {
+ secure_vector<uint8_t> salt;
+ size_t N = 0, r = 0, p = 0;
+ size_t key_length = 0;
+
+ AlgorithmIdentifier prf_algo;
+ BER_Decoder(kdf_algo.get_parameters())
+ .start_cons(SEQUENCE)
+ .decode(salt, OCTET_STRING)
+ .decode(N)
+ .decode(r)
+ .decode(p)
+ .decode_optional(key_length, INTEGER, UNIVERSAL)
+ .end_cons();
+
+ if(key_length == 0)
+ key_length = default_key_size;
+
+ secure_vector<uint8_t> output(key_length);
+ scrypt(output.data(), output.size(), passphrase,
+ salt.data(), salt.size(), N, r, p);
+
+ return SymmetricKey(output);
+ }
+#endif
+ else
+ throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " +
+ kdf_algo.get_oid().as_string());
+ }
+
+secure_vector<uint8_t> derive_key(const std::string& passphrase,
+ const std::string& digest,
+ RandomNumberGenerator& rng,
+ size_t* msec_in_iterations_out,
+ size_t iterations_if_msec_null,
+ size_t key_length,
+ AlgorithmIdentifier& kdf_algo)
+ {
+ const secure_vector<uint8_t> salt = rng.random_vec(12);
+
+ if(digest == "Scrypt")
+ {
+#if defined(BOTAN_HAS_SCRYPT)
+
+ Scrypt_Params params(32768, 8, 4);
+
+ if(msec_in_iterations_out)
+ params = Scrypt_Params(std::chrono::milliseconds(*msec_in_iterations_out));
+ else
+ params = Scrypt_Params(iterations_if_msec_null);
+
+ secure_vector<uint8_t> key(key_length);
+ scrypt(key.data(), key.size(), passphrase,
+ salt.data(), salt.size(), params);
+
+ std::vector<uint8_t> scrypt_params;
+ DER_Encoder(scrypt_params)
+ .start_cons(SEQUENCE)
+ .encode(salt, OCTET_STRING)
+ .encode(params.N())
+ .encode(params.r())
+ .encode(params.p())
+ .encode(key_length)
+ .end_cons();
+
+ kdf_algo = AlgorithmIdentifier(OIDS::lookup("Scrypt"), scrypt_params);
+ return key;
+#else
+ throw Not_Implemented("Scrypt is not available in this build");
+#endif
+ }
+ else
+ {
+ const std::string prf = "HMAC(" + digest + ")";
+
+ std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(" + prf + ")"));
+
+ size_t iterations = iterations_if_msec_null;
+
+ secure_vector<uint8_t> key;
+
+ if(msec_in_iterations_out)
+ {
+ std::chrono::milliseconds msec(*msec_in_iterations_out);
+ key = pbkdf->derive_key(key_length, passphrase, salt.data(), salt.size(), msec, iterations).bits_of();
+ *msec_in_iterations_out = iterations;
+ }
+ else
+ {
+ key = pbkdf->pbkdf_iterations(key_length, passphrase, salt.data(), salt.size(), iterations);
+ }
+
+ std::vector<uint8_t> pbkdf2_params;
+
+ DER_Encoder(pbkdf2_params)
+ .start_cons(SEQUENCE)
+ .encode(salt, OCTET_STRING)
+ .encode(iterations)
+ .encode(key_length)
+ .encode_if(prf != "HMAC(SHA-160)",
+ AlgorithmIdentifier(prf, AlgorithmIdentifier::USE_NULL_PARAM))
+ .end_cons();
+
+ kdf_algo = AlgorithmIdentifier("PKCS5.PBKDF2", pbkdf2_params);
+ return key;
+ }
+ }
+
+/*
+* PKCS#5 v2.0 PBE Encryption
+*/
+std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
+pbes2_encrypt_shared(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ size_t* msec_in_iterations_out,
+ size_t iterations_if_msec_null,
+ const std::string& cipher,
+ const std::string& prf,
+ RandomNumberGenerator& rng)
+ {
+ const std::vector<std::string> cipher_spec = split_on(cipher, '/');
+ if(cipher_spec.size() != 2)
+ throw Encoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
+
+ if(cipher_spec[1] != "CBC" && cipher_spec[1] != "GCM")
+ throw Encoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher);
+
+ const OID cipher_oid = OIDS::lookup(cipher);
+ if(cipher_oid.empty())
+ throw Encoding_Error("PBE-PKCS5 v2.0: No OID assigned for " + cipher);
+
+ std::unique_ptr<Cipher_Mode> enc = Cipher_Mode::create(cipher, ENCRYPTION);
+
+ if(!enc)
+ throw Decoding_Error("PBE-PKCS5 cannot encrypt no cipher " + cipher);
+
+ const size_t key_length = enc->key_spec().maximum_keylength();
+
+ const secure_vector<uint8_t> iv = rng.random_vec(enc->default_nonce_length());
+
+ AlgorithmIdentifier kdf_algo;
+
+ const secure_vector<uint8_t> derived_key =
+ derive_key(passphrase, prf, rng,
+ msec_in_iterations_out, iterations_if_msec_null,
+ key_length, kdf_algo);
+
+ enc->set_key(derived_key);
+ enc->start(iv);
+ secure_vector<uint8_t> ctext = key_bits;
+ enc->finish(ctext);
+
+ std::vector<uint8_t> pbes2_params;
+
+ DER_Encoder(pbes2_params)
+ .start_cons(SEQUENCE)
+ .encode(kdf_algo)
+ .encode(
+ AlgorithmIdentifier(cipher,
+ DER_Encoder().encode(iv, OCTET_STRING).get_contents_unlocked()
+ )
+ )
+ .end_cons();
+
+ AlgorithmIdentifier id(OIDS::lookup("PBE-PKCS5v20"), pbes2_params);
+
+ return std::make_pair(id, unlock(ctext));
+ }
+
+
+}
+
+std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
+pbes2_encrypt(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ std::chrono::milliseconds msec,
+ const std::string& cipher,
+ const std::string& digest,
+ RandomNumberGenerator& rng)
+ {
+ size_t msec_in_iterations_out = static_cast<size_t>(msec.count());
+ return pbes2_encrypt_shared(key_bits, passphrase, &msec_in_iterations_out, 0, cipher, digest, rng);
+ // return value msec_in_iterations_out discarded
+ }
+
+std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
+pbes2_encrypt_msec(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ std::chrono::milliseconds msec,
+ size_t* out_iterations_if_nonnull,
+ const std::string& cipher,
+ const std::string& digest,
+ RandomNumberGenerator& rng)
+ {
+ size_t msec_in_iterations_out = static_cast<size_t>(msec.count());
+
+ auto ret = pbes2_encrypt_shared(key_bits, passphrase, &msec_in_iterations_out, 0, cipher, digest, rng);
+
+ if(out_iterations_if_nonnull)
+ *out_iterations_if_nonnull = msec_in_iterations_out;
+
+ return ret;
+ }
+
+std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
+pbes2_encrypt_iter(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ size_t pbkdf_iter,
+ const std::string& cipher,
+ const std::string& digest,
+ RandomNumberGenerator& rng)
+ {
+ return pbes2_encrypt_shared(key_bits, passphrase, nullptr, pbkdf_iter, cipher, digest, rng);
+ }
+
+secure_vector<uint8_t>
+pbes2_decrypt(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ const std::vector<uint8_t>& params)
+ {
+ AlgorithmIdentifier kdf_algo, enc_algo;
+
+ BER_Decoder(params)
+ .start_cons(SEQUENCE)
+ .decode(kdf_algo)
+ .decode(enc_algo)
+ .end_cons();
+
+ const std::string cipher = OIDS::lookup(enc_algo.get_oid());
+ const std::vector<std::string> cipher_spec = split_on(cipher, '/');
+ if(cipher_spec.size() != 2)
+ throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
+ if(cipher_spec[1] != "CBC" && cipher_spec[1] != "GCM")
+ throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher);
+
+ secure_vector<uint8_t> iv;
+ BER_Decoder(enc_algo.get_parameters()).decode(iv, OCTET_STRING).verify_end();
+
+ std::unique_ptr<Cipher_Mode> dec = Cipher_Mode::create(cipher, DECRYPTION);
+ if(!dec)
+ throw Decoding_Error("PBE-PKCS5 cannot decrypt no cipher " + cipher);
+
+ dec->set_key(derive_key(passphrase, kdf_algo, dec->key_spec().maximum_keylength()));
+
+ dec->start(iv);
+
+ secure_vector<uint8_t> buf = key_bits;
+ dec->finish(buf);
+
+ return buf;
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/pbes2.h b/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/pbes2.h
new file mode 100644
index 0000000000..bc56abd97f
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pbes2/pbes2.h
@@ -0,0 +1,85 @@
+/*
+* PKCS #5 v2.0 PBE
+* (C) 1999-2007,2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PBE_PKCS_v20_H_
+#define BOTAN_PBE_PKCS_v20_H_
+
+#include <botan/alg_id.h>
+#include <chrono>
+
+namespace Botan {
+
+class RandomNumberGenerator;
+
+/**
+* Encrypt with PBES2 from PKCS #5 v2.0
+* @param key_bits the input
+* @param passphrase the passphrase to use for encryption
+* @param msec how many milliseconds to run PBKDF2
+* @param cipher specifies the block cipher to use to encrypt
+* @param digest specifies the PRF to use with PBKDF2 (eg "HMAC(SHA-1)")
+* @param rng a random number generator
+*/
+std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
+BOTAN_PUBLIC_API(2,0) pbes2_encrypt(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ std::chrono::milliseconds msec,
+ const std::string& cipher,
+ const std::string& digest,
+ RandomNumberGenerator& rng);
+
+/**
+* Encrypt with PBES2 from PKCS #5 v2.0
+* @param key_bits the input
+* @param passphrase the passphrase to use for encryption
+* @param msec how many milliseconds to run PBKDF2
+* @param out_iterations_if_nonnull if not null, set to the number
+* of PBKDF iterations used
+* @param cipher specifies the block cipher to use to encrypt
+* @param digest specifies the PRF to use with PBKDF2 (eg "HMAC(SHA-1)")
+* @param rng a random number generator
+*/
+std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
+BOTAN_PUBLIC_API(2,1) pbes2_encrypt_msec(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ std::chrono::milliseconds msec,
+ size_t* out_iterations_if_nonnull,
+ const std::string& cipher,
+ const std::string& digest,
+ RandomNumberGenerator& rng);
+
+/**
+* Encrypt with PBES2 from PKCS #5 v2.0
+* @param key_bits the input
+* @param passphrase the passphrase to use for encryption
+* @param iterations how many iterations to run PBKDF2
+* @param cipher specifies the block cipher to use to encrypt
+* @param digest specifies the PRF to use with PBKDF2 (eg "HMAC(SHA-1)")
+* @param rng a random number generator
+*/
+std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
+BOTAN_PUBLIC_API(2,1) pbes2_encrypt_iter(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ size_t iterations,
+ const std::string& cipher,
+ const std::string& digest,
+ RandomNumberGenerator& rng);
+
+/**
+* Decrypt a PKCS #5 v2.0 encrypted stream
+* @param key_bits the input
+* @param passphrase the passphrase to use for decryption
+* @param params the PBES2 parameters
+*/
+secure_vector<uint8_t>
+BOTAN_PUBLIC_API(2,0) pbes2_decrypt(const secure_vector<uint8_t>& key_bits,
+ const std::string& passphrase,
+ const std::vector<uint8_t>& params);
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pem/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/pem/info.txt
new file mode 100644
index 0000000000..471d9abd63
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pem/info.txt
@@ -0,0 +1,7 @@
+<defines>
+PEM_CODEC -> 20131128
+</defines>
+
+<requires>
+base64
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pem/pem.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/pem/pem.cpp
new file mode 100644
index 0000000000..d2433860dd
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pem/pem.cpp
@@ -0,0 +1,169 @@
+/*
+* PEM Encoding/Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/pem.h>
+#include <botan/data_src.h>
+#include <botan/base64.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace PEM_Code {
+
+namespace {
+
+std::string linewrap(size_t width, const std::string& in)
+ {
+ std::string out;
+ for(size_t i = 0; i != in.size(); ++i)
+ {
+ if(i > 0 && i % width == 0)
+ {
+ out.push_back('\n');
+ }
+ out.push_back(in[i]);
+ }
+ if(out.size() > 0 && out[out.size()-1] != '\n')
+ {
+ out.push_back('\n');
+ }
+
+ return out;
+ }
+
+}
+
+/*
+* PEM encode BER/DER-encoded objects
+*/
+std::string encode(const uint8_t der[], size_t length, const std::string& label, size_t width)
+ {
+ const std::string PEM_HEADER = "-----BEGIN " + label + "-----\n";
+ const std::string PEM_TRAILER = "-----END " + label + "-----\n";
+
+ return (PEM_HEADER + linewrap(width, base64_encode(der, length)) + PEM_TRAILER);
+ }
+
+/*
+* Decode PEM down to raw BER/DER
+*/
+secure_vector<uint8_t> decode_check_label(DataSource& source,
+ const std::string& label_want)
+ {
+ std::string label_got;
+ secure_vector<uint8_t> ber = decode(source, label_got);
+ if(label_got != label_want)
+ throw Decoding_Error("PEM: Label mismatch, wanted " + label_want +
+ ", got " + label_got);
+ return ber;
+ }
+
+/*
+* Decode PEM down to raw BER/DER
+*/
+secure_vector<uint8_t> decode(DataSource& source, std::string& label)
+ {
+ const size_t RANDOM_CHAR_LIMIT = 8;
+
+ label.clear();
+
+ const std::string PEM_HEADER1 = "-----BEGIN ";
+ const std::string PEM_HEADER2 = "-----";
+ size_t position = 0;
+
+ while(position != PEM_HEADER1.length())
+ {
+ uint8_t b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM header found");
+ if(b == PEM_HEADER1[position])
+ ++position;
+ else if(position >= RANDOM_CHAR_LIMIT)
+ throw Decoding_Error("PEM: Malformed PEM header");
+ else
+ position = 0;
+ }
+ position = 0;
+ while(position != PEM_HEADER2.length())
+ {
+ uint8_t b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM header found");
+ if(b == PEM_HEADER2[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PEM: Malformed PEM header");
+
+ if(position == 0)
+ label += static_cast<char>(b);
+ }
+
+ std::vector<char> b64;
+
+ const std::string PEM_TRAILER = "-----END " + label + "-----";
+ position = 0;
+ while(position != PEM_TRAILER.length())
+ {
+ uint8_t b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM trailer found");
+ if(b == PEM_TRAILER[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PEM: Malformed PEM trailer");
+
+ if(position == 0)
+ b64.push_back(b);
+ }
+
+ return base64_decode(b64.data(), b64.size());
+ }
+
+secure_vector<uint8_t> decode_check_label(const std::string& pem,
+ const std::string& label_want)
+ {
+ DataSource_Memory src(pem);
+ return decode_check_label(src, label_want);
+ }
+
+secure_vector<uint8_t> decode(const std::string& pem, std::string& label)
+ {
+ DataSource_Memory src(pem);
+ return decode(src, label);
+ }
+
+/*
+* Search for a PEM signature
+*/
+bool matches(DataSource& source, const std::string& extra,
+ size_t search_range)
+ {
+ const std::string PEM_HEADER = "-----BEGIN " + extra;
+
+ secure_vector<uint8_t> search_buf(search_range);
+ size_t got = source.peek(search_buf.data(), search_buf.size(), 0);
+
+ if(got < PEM_HEADER.length())
+ return false;
+
+ size_t index = 0;
+
+ for(size_t j = 0; j != got; ++j)
+ {
+ if(search_buf[j] == PEM_HEADER[index])
+ ++index;
+ else
+ index = 0;
+ if(index == PEM_HEADER.size())
+ return true;
+ }
+ return false;
+ }
+
+}
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pem/pem.h b/src/libs/3rdparty/botan/src/lib/pubkey/pem/pem.h
new file mode 100644
index 0000000000..c02294dce5
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pem/pem.h
@@ -0,0 +1,91 @@
+/*
+* PEM Encoding/Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PEM_H_
+#define BOTAN_PEM_H_
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+class DataSource;
+
+namespace PEM_Code {
+
+/**
+* Encode some binary data in PEM format
+* @param data binary data to encode
+* @param data_len length of binary data in bytes
+* @param label PEM label put after BEGIN and END
+* @param line_width after this many characters, a new line is inserted
+*/
+BOTAN_PUBLIC_API(2,0) std::string encode(const uint8_t data[],
+ size_t data_len,
+ const std::string& label,
+ size_t line_width = 64);
+
+/**
+* Encode some binary data in PEM format
+* @param data binary data to encode
+* @param label PEM label
+* @param line_width after this many characters, a new line is inserted
+*/
+template<typename Alloc>
+std::string encode(const std::vector<uint8_t, Alloc>& data,
+ const std::string& label,
+ size_t line_width = 64)
+ {
+ return encode(data.data(), data.size(), label, line_width);
+ }
+
+/**
+* Decode PEM data
+* @param pem a datasource containing PEM encoded data
+* @param label is set to the PEM label found for later inspection
+*/
+BOTAN_PUBLIC_API(2,0) secure_vector<uint8_t> decode(DataSource& pem,
+ std::string& label);
+
+/**
+* Decode PEM data
+* @param pem a string containing PEM encoded data
+* @param label is set to the PEM label found for later inspection
+*/
+BOTAN_PUBLIC_API(2,0) secure_vector<uint8_t> decode(const std::string& pem,
+ std::string& label);
+
+/**
+* Decode PEM data
+* @param pem a datasource containing PEM encoded data
+* @param label is what we expect the label to be
+*/
+BOTAN_PUBLIC_API(2,0)
+secure_vector<uint8_t> decode_check_label(DataSource& pem,
+ const std::string& label);
+
+/**
+* Decode PEM data
+* @param pem a string containing PEM encoded data
+* @param label is what we expect the label to be
+*/
+BOTAN_PUBLIC_API(2,0)
+secure_vector<uint8_t> decode_check_label(const std::string& pem,
+ const std::string& label);
+
+/**
+* Heuristic test for PEM data.
+*/
+BOTAN_PUBLIC_API(2,0) bool matches(DataSource& source,
+ const std::string& extra = "",
+ size_t search_range = 4096);
+
+}
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pk_algs.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/pk_algs.cpp
new file mode 100644
index 0000000000..89ef7c708e
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pk_algs.cpp
@@ -0,0 +1,434 @@
+/*
+* PK Key
+* (C) 1999-2010,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/pk_algs.h>
+#include <botan/oids.h>
+#include <botan/parsing.h>
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DL_GROUP)
+ #include <botan/dl_group.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
+ #include <botan/ecc_key.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECGDSA)
+ #include <botan/ecgdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKCDSA)
+ #include <botan/eckcdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ED25519)
+ #include <botan/ed25519.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ #include <botan/gost_3410.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elgamal.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ #include <botan/ecdh.h>
+#endif
+
+#if defined(BOTAN_HAS_CURVE_25519)
+ #include <botan/curve25519.h>
+#endif
+
+#if defined(BOTAN_HAS_MCELIECE)
+ #include <botan/mceliece.h>
+#endif
+
+#if defined(BOTAN_HAS_XMSS)
+ #include <botan/xmss.h>
+#endif
+
+#if defined(BOTAN_HAS_SM2)
+ #include <botan/sm2.h>
+ #include <botan/sm2_enc.h>
+#endif
+
+#if defined(BOTAN_HAS_OPENSSL)
+ #include <botan/internal/openssl.h>
+#endif
+
+namespace Botan {
+
+std::unique_ptr<Public_Key>
+load_public_key(const AlgorithmIdentifier& alg_id,
+ const std::vector<uint8_t>& key_bits)
+ {
+ const std::vector<std::string> alg_info = split_on(OIDS::lookup(alg_id.get_oid()), '/');
+
+ if(alg_info.empty())
+ throw Decoding_Error("Unknown algorithm OID: " + alg_id.get_oid().as_string());
+
+ const std::string alg_name = alg_info[0];
+
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA")
+ return std::unique_ptr<Public_Key>(new RSA_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_CURVE_25519)
+ if(alg_name == "Curve25519")
+ return std::unique_ptr<Public_Key>(new Curve25519_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_MCELIECE)
+ if(alg_name == "McEliece")
+ return std::unique_ptr<Public_Key>(new McEliece_PublicKey(key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA")
+ return std::unique_ptr<Public_Key>(new ECDSA_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ if(alg_name == "ECDH")
+ return std::unique_ptr<Public_Key>(new ECDH_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(alg_name == "DH")
+ return std::unique_ptr<Public_Key>(new DH_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA")
+ return std::unique_ptr<Public_Key>(new DSA_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(alg_name == "ElGamal")
+ return std::unique_ptr<Public_Key>(new ElGamal_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ECGDSA)
+ if(alg_name == "ECGDSA")
+ return std::unique_ptr<Public_Key>(new ECGDSA_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ECKCDSA)
+ if(alg_name == "ECKCDSA")
+ return std::unique_ptr<Public_Key>(new ECKCDSA_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ED25519)
+ if(alg_name == "Ed25519")
+ return std::unique_ptr<Public_Key>(new Ed25519_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ if(alg_name == "GOST-34.10")
+ return std::unique_ptr<Public_Key>(new GOST_3410_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_SM2)
+ if(alg_name == "SM2_Sig")
+ return std::unique_ptr<Public_Key>(new SM2_Signature_PublicKey(alg_id, key_bits));
+ if(alg_name == "SM2_Enc")
+ return std::unique_ptr<Public_Key>(new SM2_Encryption_PublicKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_XMSS)
+ if(alg_name == "XMSS")
+ return std::unique_ptr<Public_Key>(new XMSS_PublicKey(key_bits));
+#endif
+
+ throw Decoding_Error("Unhandled PK algorithm " + alg_name);
+ }
+
+std::unique_ptr<Private_Key>
+load_private_key(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits)
+ {
+ const std::string alg_name = OIDS::lookup(alg_id.get_oid());
+ if(alg_name == "")
+ throw Decoding_Error("Unknown algorithm OID: " + alg_id.get_oid().as_string());
+
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA")
+ return std::unique_ptr<Private_Key>(new RSA_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_CURVE_25519)
+ if(alg_name == "Curve25519")
+ return std::unique_ptr<Private_Key>(new Curve25519_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA")
+ return std::unique_ptr<Private_Key>(new ECDSA_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ if(alg_name == "ECDH")
+ return std::unique_ptr<Private_Key>(new ECDH_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(alg_name == "DH")
+ return std::unique_ptr<Private_Key>(new DH_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA")
+ return std::unique_ptr<Private_Key>(new DSA_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_MCELIECE)
+ if(alg_name == "McEliece")
+ return std::unique_ptr<Private_Key>(new McEliece_PrivateKey(key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ECGDSA)
+ if(alg_name == "ECGDSA")
+ return std::unique_ptr<Private_Key>(new ECGDSA_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ECKCDSA)
+ if(alg_name == "ECKCDSA")
+ return std::unique_ptr<Private_Key>(new ECKCDSA_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ED25519)
+ if(alg_name == "Ed25519")
+ return std::unique_ptr<Private_Key>(new Ed25519_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ if(alg_name == "GOST-34.10")
+ return std::unique_ptr<Private_Key>(new GOST_3410_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_SM2)
+ if(alg_name == "SM2_Sig")
+ return std::unique_ptr<Private_Key>(new SM2_Signature_PrivateKey(alg_id, key_bits));
+ if(alg_name == "SM2_Enc")
+ return std::unique_ptr<Private_Key>(new SM2_Encryption_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(alg_name == "ElGamal")
+ return std::unique_ptr<Private_Key>(new ElGamal_PrivateKey(alg_id, key_bits));
+#endif
+
+#if defined(BOTAN_HAS_XMSS)
+ if(alg_name == "XMSS")
+ return std::unique_ptr<Private_Key>(new XMSS_PrivateKey(key_bits));
+#endif
+
+ throw Decoding_Error("Unhandled PK algorithm " + alg_name);
+ }
+
+#if defined(BOTAN_HAS_ECC_GROUP)
+
+namespace {
+
+std::string default_ec_group_for(const std::string& alg_name)
+ {
+ if(alg_name == "SM2_Enc" || alg_name == "SM2_Sig")
+ return "sm2p256v1";
+ if(alg_name == "GOST-34.10")
+ return "gost_256A";
+ if(alg_name == "ECGDSA")
+ return "brainpool256r1";
+ return "secp256r1";
+
+ }
+
+}
+
+#endif
+
+std::unique_ptr<Private_Key>
+create_private_key(const std::string& alg_name,
+ RandomNumberGenerator& rng,
+ const std::string& params,
+ const std::string& provider)
+ {
+ /*
+ * Default paramaters are chosen for work factor > 2**128 where possible
+ */
+
+#if defined(BOTAN_HAS_CURVE_25519)
+ if(alg_name == "Curve25519")
+ return std::unique_ptr<Private_Key>(new Curve25519_PrivateKey(rng));
+#endif
+
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA")
+ {
+ const size_t rsa_bits = (params.empty() ? 3072 : to_u32bit(params));
+#if defined(BOTAN_HAS_OPENSSL)
+ if(provider.empty() || provider == "openssl")
+ {
+ std::unique_ptr<Botan::Private_Key> pk;
+ if((pk = make_openssl_rsa_private_key(rng, rsa_bits)))
+ return pk;
+
+ if(!provider.empty())
+ return nullptr;
+ }
+#endif
+ return std::unique_ptr<Private_Key>(new RSA_PrivateKey(rng, rsa_bits));
+ }
+#endif
+
+#if defined(BOTAN_HAS_MCELIECE)
+ if(alg_name == "McEliece")
+ {
+ std::vector<std::string> mce_param =
+ Botan::split_on(params.empty() ? "2960,57" : params, ',');
+
+ if(mce_param.size() != 2)
+ throw Invalid_Argument("create_private_key bad McEliece parameters " + params);
+
+ size_t mce_n = Botan::to_u32bit(mce_param[0]);
+ size_t mce_t = Botan::to_u32bit(mce_param[1]);
+
+ return std::unique_ptr<Botan::Private_Key>(new Botan::McEliece_PrivateKey(rng, mce_n, mce_t));
+ }
+#endif
+
+#if defined(BOTAN_HAS_XMSS)
+ if(alg_name == "XMSS")
+ {
+ return std::unique_ptr<Private_Key>(
+ new XMSS_PrivateKey(XMSS_Parameters(params.empty() ? "XMSS_SHA2-512_W16_H10" : params).oid(), rng));
+ }
+#endif
+
+#if defined(BOTAN_HAS_ED25519)
+ if(alg_name == "Ed25519")
+ {
+ return std::unique_ptr<Private_Key>(new Ed25519_PrivateKey(rng));
+ }
+#endif
+
+ // ECC crypto
+#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
+
+ if(alg_name == "ECDSA" ||
+ alg_name == "ECDH" ||
+ alg_name == "ECKCDSA" ||
+ alg_name == "ECGDSA" ||
+ alg_name == "SM2_Sig" ||
+ alg_name == "SM2_Enc" ||
+ alg_name == "GOST-34.10")
+ {
+ const EC_Group ec_group(params.empty() ? default_ec_group_for(alg_name) : params);
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA")
+ return std::unique_ptr<Private_Key>(new ECDSA_PrivateKey(rng, ec_group));
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ if(alg_name == "ECDH")
+ return std::unique_ptr<Private_Key>(new ECDH_PrivateKey(rng, ec_group));
+#endif
+
+#if defined(BOTAN_HAS_ECKCDSA)
+ if(alg_name == "ECKCDSA")
+ return std::unique_ptr<Private_Key>(new ECKCDSA_PrivateKey(rng, ec_group));
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ if(alg_name == "GOST-34.10")
+ return std::unique_ptr<Private_Key>(new GOST_3410_PrivateKey(rng, ec_group));
+#endif
+
+#if defined(BOTAN_HAS_SM2)
+ if(alg_name == "SM2_Sig")
+ return std::unique_ptr<Private_Key>(new SM2_Signature_PrivateKey(rng, ec_group));
+ if(alg_name == "SM2_Enc")
+ return std::unique_ptr<Private_Key>(new SM2_Encryption_PrivateKey(rng, ec_group));
+#endif
+
+#if defined(BOTAN_HAS_ECGDSA)
+ if(alg_name == "ECGDSA")
+ return std::unique_ptr<Private_Key>(new ECGDSA_PrivateKey(rng, ec_group));
+#endif
+ }
+#endif
+
+ // DL crypto
+#if defined(BOTAN_HAS_DL_GROUP)
+ if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal")
+ {
+ std::string default_group = (alg_name == "DSA") ? "dsa/botan/2048" : "modp/ietf/2048";
+ DL_Group modp_group(params.empty() ? default_group : params);
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(alg_name == "DH")
+ return std::unique_ptr<Private_Key>(new DH_PrivateKey(rng, modp_group));
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA")
+ return std::unique_ptr<Private_Key>(new DSA_PrivateKey(rng, modp_group));
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(alg_name == "ElGamal")
+ return std::unique_ptr<Private_Key>(new ElGamal_PrivateKey(rng, modp_group));
+#endif
+ }
+#endif
+
+ BOTAN_UNUSED(alg_name, rng, params, provider);
+
+ return std::unique_ptr<Private_Key>();
+ }
+
+std::vector<std::string>
+probe_provider_private_key(const std::string& alg_name,
+ const std::vector<std::string> possible)
+ {
+ std::vector<std::string> providers;
+ for(auto&& prov : possible)
+ {
+ if(prov == "base" ||
+#if defined(BOTAN_HAS_OPENSSL)
+ (prov == "openssl" && alg_name == "RSA") ||
+#endif
+ 0)
+ {
+ providers.push_back(prov); // available
+ }
+ }
+
+ BOTAN_UNUSED(alg_name);
+
+ return providers;
+ }
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pk_algs.h b/src/libs/3rdparty/botan/src/lib/pubkey/pk_algs.h
new file mode 100644
index 0000000000..e3c7174288
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pk_algs.h
@@ -0,0 +1,46 @@
+/*
+* PK Key Factory
+* (C) 1999-2010,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PK_KEY_FACTORY_H_
+#define BOTAN_PK_KEY_FACTORY_H_
+
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+#include <memory>
+
+namespace Botan {
+
+BOTAN_PUBLIC_API(2,0) std::unique_ptr<Public_Key>
+load_public_key(const AlgorithmIdentifier& alg_id,
+ const std::vector<uint8_t>& key_bits);
+
+BOTAN_PUBLIC_API(2,0) std::unique_ptr<Private_Key>
+load_private_key(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits);
+
+/**
+* Create a new key
+* For ECC keys, algo_params specifies EC group (eg, "secp256r1")
+* For DH/DSA/ElGamal keys, algo_params is DL group (eg, "modp/ietf/2048")
+* For RSA, algo_params is integer keylength
+* For McEliece, algo_params is n,t
+* If algo_params is left empty, suitable default parameters are chosen.
+*/
+BOTAN_PUBLIC_API(2,0) std::unique_ptr<Private_Key>
+create_private_key(const std::string& algo_name,
+ RandomNumberGenerator& rng,
+ const std::string& algo_params = "",
+ const std::string& provider = "");
+
+BOTAN_PUBLIC_API(2,2)
+std::vector<std::string>
+probe_provider_private_key(const std::string& algo_name,
+ const std::vector<std::string> possible);
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pk_keys.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/pk_keys.cpp
new file mode 100644
index 0000000000..fbbc6f7dd4
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pk_keys.cpp
@@ -0,0 +1,148 @@
+/*
+* PK Key Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/pk_keys.h>
+#include <botan/pk_ops.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+#include <botan/hash.h>
+#include <botan/hex.h>
+
+namespace Botan {
+
+std::string create_hex_fingerprint(const uint8_t bits[],
+ size_t bits_len,
+ const std::string& hash_name)
+ {
+ std::unique_ptr<HashFunction> hash_fn(HashFunction::create_or_throw(hash_name));
+ const std::string hex_hash = hex_encode(hash_fn->process(bits, bits_len));
+
+ std::string fprint;
+
+ for(size_t i = 0; i != hex_hash.size(); i += 2)
+ {
+ if(i != 0)
+ fprint.push_back(':');
+
+ fprint.push_back(hex_hash[i]);
+ fprint.push_back(hex_hash[i+1]);
+ }
+
+ return fprint;
+ }
+
+std::vector<uint8_t> Public_Key::subject_public_key() const
+ {
+ std::vector<uint8_t> output;
+
+ DER_Encoder(output).start_cons(SEQUENCE)
+ .encode(algorithm_identifier())
+ .encode(public_key_bits(), BIT_STRING)
+ .end_cons();
+
+ return output;
+ }
+
+/*
+* Default OID access
+*/
+OID Public_Key::get_oid() const
+ {
+ try {
+ return OIDS::lookup(algo_name());
+ }
+ catch(Lookup_Error&)
+ {
+ throw Lookup_Error("PK algo " + algo_name() + " has no defined OIDs");
+ }
+ }
+
+secure_vector<uint8_t> Private_Key::private_key_info() const
+ {
+ const size_t PKCS8_VERSION = 0;
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(pkcs8_algorithm_identifier())
+ .encode(private_key_bits(), OCTET_STRING)
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* Hash of the X.509 subjectPublicKey encoding
+*/
+std::string Public_Key::fingerprint_public(const std::string& hash_algo) const
+ {
+ return create_hex_fingerprint(subject_public_key(), hash_algo);
+ }
+
+/*
+* Hash of the PKCS #8 encoding for this key object
+*/
+std::string Private_Key::fingerprint_private(const std::string& hash_algo) const
+ {
+ return create_hex_fingerprint(private_key_bits(), hash_algo);
+ }
+
+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/libs/3rdparty/botan/src/lib/pubkey/pk_keys.h b/src/libs/3rdparty/botan/src/lib/pubkey/pk_keys.h
new file mode 100644
index 0000000000..79254ea290
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pk_keys.h
@@ -0,0 +1,317 @@
+/*
+* PK Key Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PK_KEYS_H_
+#define BOTAN_PK_KEYS_H_
+
+#include <botan/secmem.h>
+#include <botan/asn1_oid.h>
+#include <botan/alg_id.h>
+#include <botan/pk_ops_fwd.h>
+
+namespace Botan {
+
+class RandomNumberGenerator;
+
+/**
+* Public Key Base Class.
+*/
+class BOTAN_PUBLIC_API(2,0) Public_Key
+ {
+ public:
+ Public_Key() =default;
+ Public_Key(const Public_Key& other) = default;
+ Public_Key& operator=(const Public_Key& other) = default;
+ virtual ~Public_Key() = default;
+
+ /**
+ * Get the name of the underlying public key scheme.
+ * @return name of the public key scheme
+ */
+ virtual std::string algo_name() const = 0;
+
+ /**
+ * Return the estimated strength of the underlying key against
+ * the best currently known attack. Note that this ignores anything
+ * but pure attacks against the key itself and do not take into
+ * account padding schemes, usage mistakes, etc which might reduce
+ * the strength. However it does suffice to provide an upper bound.
+ *
+ * @return estimated strength in bits
+ */
+ virtual size_t estimated_strength() const = 0;
+
+ /**
+ * Return an integer value best approximating the length of the
+ * primary security parameter. For example for RSA this will be
+ * the size of the modulus, for ECDSA the size of the ECC group,
+ * and for McEliece the size of the code will be returned.
+ */
+ virtual size_t key_length() const = 0;
+
+ /**
+ * Get the OID of the underlying public key scheme.
+ * @return OID of the public key scheme
+ */
+ virtual OID get_oid() const;
+
+ /**
+ * Test the key values for consistency.
+ * @param rng rng to use
+ * @param strong whether to perform strong and lengthy version
+ * of the test
+ * @return true if the test is passed
+ */
+ virtual bool check_key(RandomNumberGenerator& rng,
+ bool strong) const = 0;
+
+
+ /**
+ * @return X.509 AlgorithmIdentifier for this key
+ */
+ virtual AlgorithmIdentifier algorithm_identifier() const = 0;
+
+ /**
+ * @return BER encoded public key bits
+ */
+ virtual std::vector<uint8_t> public_key_bits() const = 0;
+
+ /**
+ * @return X.509 subject key encoding for this key object
+ */
+ std::vector<uint8_t> subject_public_key() const;
+
+ /**
+ * @return Hash of the subject public key
+ */
+ std::string fingerprint_public(const std::string& alg = "SHA-256") const;
+
+ // Internal or non-public declarations follow
+
+ /**
+ * Returns more than 1 if the output of this algorithm
+ * (ciphertext, signature) should be treated as more than one
+ * value. This is used for algorithms like DSA and ECDSA, where
+ * the (r,s) output pair can be encoded as either a plain binary
+ * list or a TLV tagged DER encoding depending on the protocol.
+ *
+ * This function is public but applications should have few
+ * reasons to ever call this.
+ *
+ * @return number of message parts
+ */
+ virtual size_t message_parts() const { return 1; }
+
+ /**
+ * Returns how large each of the message parts refered to
+ * by message_parts() is
+ *
+ * This function is public but applications should have few
+ * reasons to ever call this.
+ *
+ * @return size of the message parts in bits
+ */
+ virtual size_t message_part_size() const { return 0; }
+
+ /**
+ * 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.
+ * @param params additional parameters
+ * @param provider the provider to use
+ */
+ 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.
+ * @param params additional parameters
+ * @param provider the provider to use
+ */
+ 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
+ * @param params additional parameters
+ * @param provider the provider to use
+ */
+ virtual std::unique_ptr<PK_Ops::Verification>
+ create_verification_op(const std::string& params,
+ const std::string& provider) const;
+ };
+
+/**
+* Private Key Base Class
+*/
+class BOTAN_PUBLIC_API(2,0) Private_Key : public virtual Public_Key
+ {
+ public:
+ Private_Key() = default;
+ Private_Key(const Private_Key& other) = default;
+ Private_Key& operator=(const Private_Key& other) = default;
+ virtual ~Private_Key() = default;
+
+ /**
+ * @return BER encoded private key bits
+ */
+ virtual secure_vector<uint8_t> private_key_bits() const = 0;
+
+ /**
+ * @return PKCS #8 private key encoding for this key object
+ */
+ secure_vector<uint8_t> private_key_info() const;
+
+ /**
+ * @return PKCS #8 AlgorithmIdentifier for this key
+ * Might be different from the X.509 identifier, but normally is not
+ */
+ 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_private(const std::string& alg) const;
+
+ BOTAN_DEPRECATED("Use fingerprint_private or fingerprint_public")
+ inline std::string fingerprint(const std::string& alg) const
+ {
+ return fingerprint_private(alg); // match behavior in previous versions
+ }
+
+ /**
+ * 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.
+ * @param params additional parameters
+ * @param provider the provider to use
+ *
+ */
+ 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.
+ * @param params additional parameters
+ * @param provider the provider to use
+ */
+ 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.
+ * @param params additional parameters
+ * @param provider the provider to use
+ */
+ 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.
+ * @param params additional parameters
+ * @param provider the provider to use
+ */
+ virtual std::unique_ptr<PK_Ops::Key_Agreement>
+ create_key_agreement_op(RandomNumberGenerator& rng,
+ const std::string& params,
+ const std::string& provider) const;
+ };
+
+/**
+* PK Secret Value Derivation Key
+*/
+class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement_Key : public virtual Private_Key
+ {
+ public:
+ /*
+ * @return public component of this key
+ */
+ virtual std::vector<uint8_t> public_value() const = 0;
+
+ PK_Key_Agreement_Key() = default;
+ PK_Key_Agreement_Key(const PK_Key_Agreement_Key&) = default;
+ PK_Key_Agreement_Key& operator=(const PK_Key_Agreement_Key&) = default;
+ virtual ~PK_Key_Agreement_Key() = default;
+ };
+
+/*
+* Old compat typedefs
+* TODO: remove these?
+*/
+typedef PK_Key_Agreement_Key PK_KA_Key;
+typedef Public_Key X509_PublicKey;
+typedef Private_Key PKCS8_PrivateKey;
+
+std::string BOTAN_PUBLIC_API(2,4)
+ create_hex_fingerprint(const uint8_t bits[], size_t len,
+ const std::string& hash_name);
+
+template<typename Alloc>
+std::string create_hex_fingerprint(const std::vector<uint8_t, Alloc>& vec,
+ const std::string& hash_name)
+ {
+ return create_hex_fingerprint(vec.data(), vec.size(), hash_name);
+ }
+
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops.cpp
new file mode 100644
index 0000000000..025836878b
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops.cpp
@@ -0,0 +1,173 @@
+/*
+* PK Operation Types
+* (C) 2010,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/pk_ops_impl.h>
+#include <botan/internal/bit_ops.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+PK_Ops::Encryption_with_EME::Encryption_with_EME(const std::string& eme)
+ {
+ m_eme.reset(get_eme(eme));
+ if(!m_eme.get())
+ throw Algorithm_Not_Found(eme);
+ }
+
+size_t PK_Ops::Encryption_with_EME::max_input_bits() const
+ {
+ return 8 * m_eme->maximum_input_size(max_raw_input_bits());
+ }
+
+secure_vector<uint8_t> PK_Ops::Encryption_with_EME::encrypt(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ const size_t max_raw = max_raw_input_bits();
+ const std::vector<uint8_t> encoded = unlock(m_eme->encode(msg, msg_len, max_raw, rng));
+ return raw_encrypt(encoded.data(), encoded.size(), rng);
+ }
+
+PK_Ops::Decryption_with_EME::Decryption_with_EME(const std::string& eme)
+ {
+ m_eme.reset(get_eme(eme));
+ if(!m_eme.get())
+ throw Algorithm_Not_Found(eme);
+ }
+
+secure_vector<uint8_t>
+PK_Ops::Decryption_with_EME::decrypt(uint8_t& valid_mask,
+ const uint8_t ciphertext[],
+ size_t ciphertext_len)
+ {
+ const secure_vector<uint8_t> raw = raw_decrypt(ciphertext, ciphertext_len);
+ return m_eme->unpad(valid_mask, raw.data(), raw.size());
+ }
+
+PK_Ops::Key_Agreement_with_KDF::Key_Agreement_with_KDF(const std::string& kdf)
+ {
+ if(kdf != "Raw")
+ m_kdf.reset(get_kdf(kdf));
+ }
+
+secure_vector<uint8_t> PK_Ops::Key_Agreement_with_KDF::agree(size_t key_len,
+ const uint8_t w[], size_t w_len,
+ const uint8_t salt[], size_t salt_len)
+ {
+ secure_vector<uint8_t> z = raw_agree(w, w_len);
+ if(m_kdf)
+ return m_kdf->derive_key(key_len, z, salt, salt_len);
+ return z;
+ }
+
+PK_Ops::Signature_with_EMSA::Signature_with_EMSA(const std::string& emsa) :
+ Signature(),
+ m_emsa(get_emsa(emsa)),
+ m_hash(hash_for_emsa(emsa)),
+ m_prefix_used(false)
+ {
+ if(!m_emsa)
+ throw Algorithm_Not_Found(emsa);
+ }
+
+void PK_Ops::Signature_with_EMSA::update(const uint8_t msg[], size_t msg_len)
+ {
+ if(has_prefix() && !m_prefix_used)
+ {
+ m_prefix_used = true;
+ secure_vector<uint8_t> prefix = message_prefix();
+ m_emsa->update(prefix.data(), prefix.size());
+ }
+ m_emsa->update(msg, msg_len);
+ }
+
+secure_vector<uint8_t> PK_Ops::Signature_with_EMSA::sign(RandomNumberGenerator& rng)
+ {
+ m_prefix_used = false;
+ const secure_vector<uint8_t> msg = m_emsa->raw_data();
+ const auto padded = m_emsa->encoding_of(msg, this->max_input_bits(), rng);
+ return raw_sign(padded.data(), padded.size(), rng);
+ }
+
+PK_Ops::Verification_with_EMSA::Verification_with_EMSA(const std::string& emsa) :
+ Verification(),
+ m_emsa(get_emsa(emsa)),
+ m_hash(hash_for_emsa(emsa)),
+ m_prefix_used(false)
+ {
+ if(!m_emsa)
+ throw Algorithm_Not_Found(emsa);
+ }
+
+void PK_Ops::Verification_with_EMSA::update(const uint8_t msg[], size_t msg_len)
+ {
+ if(has_prefix() && !m_prefix_used)
+ {
+ m_prefix_used = true;
+ secure_vector<uint8_t> prefix = message_prefix();
+ m_emsa->update(prefix.data(), prefix.size());
+ }
+ m_emsa->update(msg, msg_len);
+ }
+
+bool PK_Ops::Verification_with_EMSA::is_valid_signature(const uint8_t sig[], size_t sig_len)
+ {
+ m_prefix_used = false;
+ const secure_vector<uint8_t> msg = m_emsa->raw_data();
+
+ if(with_recovery())
+ {
+ secure_vector<uint8_t> output_of_key = verify_mr(sig, sig_len);
+ return m_emsa->verify(output_of_key, msg, max_input_bits());
+ }
+ else
+ {
+ Null_RNG rng;
+ secure_vector<uint8_t> encoded = m_emsa->encoding_of(msg, max_input_bits(), rng);
+ return verify(encoded.data(), encoded.size(), sig, sig_len);
+ }
+ }
+
+void PK_Ops::KEM_Encryption_with_KDF::kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& out_shared_key,
+ size_t desired_shared_key_len,
+ Botan::RandomNumberGenerator& rng,
+ const uint8_t salt[],
+ size_t salt_len)
+ {
+ secure_vector<uint8_t> raw_shared;
+ this->raw_kem_encrypt(out_encapsulated_key, raw_shared, rng);
+
+ out_shared_key = m_kdf->derive_key(desired_shared_key_len,
+ raw_shared.data(), raw_shared.size(),
+ salt, salt_len);
+ }
+
+PK_Ops::KEM_Encryption_with_KDF::KEM_Encryption_with_KDF(const std::string& kdf)
+ {
+ m_kdf.reset(get_kdf(kdf));
+ }
+
+secure_vector<uint8_t>
+PK_Ops::KEM_Decryption_with_KDF::kem_decrypt(const uint8_t encap_key[],
+ size_t len,
+ size_t desired_shared_key_len,
+ const uint8_t salt[],
+ size_t salt_len)
+ {
+ secure_vector<uint8_t> raw_shared = this->raw_kem_decrypt(encap_key, len);
+
+ return m_kdf->derive_key(desired_shared_key_len,
+ raw_shared.data(), raw_shared.size(),
+ salt, salt_len);
+ }
+
+PK_Ops::KEM_Decryption_with_KDF::KEM_Decryption_with_KDF(const std::string& kdf)
+ {
+ m_kdf.reset(get_kdf(kdf));
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops.h b/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops.h
new file mode 100644
index 0000000000..0aaf0b0dfe
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops.h
@@ -0,0 +1,150 @@
+/*
+* (C) 2010,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PK_OPERATIONS_H_
+#define BOTAN_PK_OPERATIONS_H_
+
+/**
+* Ordinary applications should never need to include or use this
+* header. It is exposed only for specialized applications which want
+* to implement new versions of public key crypto without merging them
+* as changes to the library. One actual example of such usage is an
+* application which creates RSA signatures using a custom TPM library.
+* Unless you're doing something like that, you don't need anything
+* here. Instead use pubkey.h which wraps these types safely and
+* provides a stable application-oriented API.
+*/
+
+#include <botan/pk_keys.h>
+#include <botan/secmem.h>
+
+namespace Botan {
+
+class RandomNumberGenerator;
+class EME;
+class KDF;
+class EMSA;
+
+namespace PK_Ops {
+
+/**
+* Public key encryption interface
+*/
+class BOTAN_PUBLIC_API(2,0) Encryption
+ {
+ public:
+ virtual secure_vector<uint8_t> encrypt(const uint8_t msg[],
+ size_t msg_len,
+ RandomNumberGenerator& rng) = 0;
+
+ virtual size_t max_input_bits() const = 0;
+
+ virtual ~Encryption() = default;
+ };
+
+/**
+* Public key decryption interface
+*/
+class BOTAN_PUBLIC_API(2,0) Decryption
+ {
+ public:
+ virtual secure_vector<uint8_t> decrypt(uint8_t& valid_mask,
+ const uint8_t ciphertext[],
+ size_t ciphertext_len) = 0;
+
+ virtual ~Decryption() = default;
+ };
+
+/**
+* Public key signature verification interface
+*/
+class BOTAN_PUBLIC_API(2,0) Verification
+ {
+ public:
+ /*
+ * Add more data to the message currently being signed
+ * @param msg the message
+ * @param msg_len the length of msg in bytes
+ */
+ virtual void update(const uint8_t msg[], size_t msg_len) = 0;
+
+ /*
+ * Perform a verification operation
+ * @param rng a random number generator
+ */
+ virtual bool is_valid_signature(const uint8_t sig[], size_t sig_len) = 0;
+
+ virtual ~Verification() = default;
+ };
+
+/**
+* Public key signature creation interface
+*/
+class BOTAN_PUBLIC_API(2,0) Signature
+ {
+ public:
+ /*
+ * Add more data to the message currently being signed
+ * @param msg the message
+ * @param msg_len the length of msg in bytes
+ */
+ virtual void update(const uint8_t msg[], size_t msg_len) = 0;
+
+ /*
+ * Perform a signature operation
+ * @param rng a random number generator
+ */
+ virtual secure_vector<uint8_t> sign(RandomNumberGenerator& rng) = 0;
+
+ virtual ~Signature() = default;
+ };
+
+/**
+* A generic key agreement operation (eg DH or ECDH)
+*/
+class BOTAN_PUBLIC_API(2,0) Key_Agreement
+ {
+ public:
+ virtual secure_vector<uint8_t> agree(size_t key_len,
+ const uint8_t other_key[], size_t other_key_len,
+ const uint8_t salt[], size_t salt_len) = 0;
+
+ virtual ~Key_Agreement() = default;
+ };
+
+/**
+* KEM (key encapsulation)
+*/
+class BOTAN_PUBLIC_API(2,0) KEM_Encryption
+ {
+ public:
+ virtual void kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& out_shared_key,
+ size_t desired_shared_key_len,
+ Botan::RandomNumberGenerator& rng,
+ const uint8_t salt[],
+ size_t salt_len) = 0;
+
+ virtual ~KEM_Encryption() = default;
+ };
+
+class BOTAN_PUBLIC_API(2,0) KEM_Decryption
+ {
+ public:
+ virtual secure_vector<uint8_t> kem_decrypt(const uint8_t encap_key[],
+ size_t len,
+ size_t desired_shared_key_len,
+ const uint8_t salt[],
+ size_t salt_len) = 0;
+
+ virtual ~KEM_Decryption() = default;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops_fwd.h b/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops_fwd.h
new file mode 100644
index 0000000000..92a3c2a969
--- /dev/null
+++ b/src/libs/3rdparty/botan/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/libs/3rdparty/botan/src/lib/pubkey/pk_ops_impl.h b/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops_impl.h
new file mode 100644
index 0000000000..1878a74177
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pk_ops_impl.h
@@ -0,0 +1,231 @@
+
+/*
+* (C) 2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PK_OPERATION_IMPL_H_
+#define BOTAN_PK_OPERATION_IMPL_H_
+
+#include <botan/pk_ops.h>
+#include <botan/eme.h>
+#include <botan/kdf.h>
+#include <botan/emsa.h>
+
+namespace Botan {
+
+namespace PK_Ops {
+
+class Encryption_with_EME : public Encryption
+ {
+ public:
+ size_t max_input_bits() const override;
+
+ secure_vector<uint8_t> encrypt(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
+
+ ~Encryption_with_EME() = default;
+ protected:
+ explicit Encryption_with_EME(const std::string& eme);
+ private:
+ virtual size_t max_raw_input_bits() const = 0;
+
+ virtual secure_vector<uint8_t> raw_encrypt(const uint8_t msg[], size_t len,
+ RandomNumberGenerator& rng) = 0;
+ std::unique_ptr<EME> m_eme;
+ };
+
+class Decryption_with_EME : public Decryption
+ {
+ public:
+ secure_vector<uint8_t> decrypt(uint8_t& valid_mask,
+ const uint8_t msg[], size_t msg_len) override;
+
+ ~Decryption_with_EME() = default;
+ protected:
+ explicit Decryption_with_EME(const std::string& eme);
+ private:
+ virtual secure_vector<uint8_t> raw_decrypt(const uint8_t msg[], size_t len) = 0;
+ std::unique_ptr<EME> m_eme;
+ };
+
+class Verification_with_EMSA : public Verification
+ {
+ public:
+ ~Verification_with_EMSA() = default;
+
+ void update(const uint8_t msg[], size_t msg_len) override;
+ bool is_valid_signature(const uint8_t sig[], size_t sig_len) override;
+
+ bool do_check(const secure_vector<uint8_t>& msg,
+ const uint8_t sig[], size_t sig_len);
+
+ std::string hash_for_signature() { return m_hash; }
+
+ protected:
+ explicit Verification_with_EMSA(const std::string& emsa);
+
+ /**
+ * Get the maximum message size in bits supported by this public key.
+ * @return maximum message in bits
+ */
+ virtual size_t max_input_bits() const = 0;
+
+ /**
+ * @return boolean specifying if this signature scheme uses
+ * a message prefix returned by message_prefix()
+ */
+ virtual bool has_prefix() { return false; }
+
+ /**
+ * @return the message prefix if this signature scheme uses
+ * a message prefix, signaled via has_prefix()
+ */
+ virtual secure_vector<uint8_t> message_prefix() const { throw Exception( "No prefix" ); }
+
+ /**
+ * @return boolean specifying if this key type supports message
+ * recovery and thus if you need to call verify() or verify_mr()
+ */
+ virtual bool with_recovery() const = 0;
+
+ /*
+ * Perform a signature check operation
+ * @param msg the message
+ * @param msg_len the length of msg in bytes
+ * @param sig the signature
+ * @param sig_len the length of sig in bytes
+ * @returns if signature is a valid one for message
+ */
+ virtual bool verify(const uint8_t[], size_t,
+ const uint8_t[], size_t)
+ {
+ throw Invalid_State("Message recovery required");
+ }
+
+ /*
+ * Perform a signature operation (with message recovery)
+ * Only call this if with_recovery() returns true
+ * @param msg the message
+ * @param msg_len the length of msg in bytes
+ * @returns recovered message
+ */
+ virtual secure_vector<uint8_t> verify_mr(const uint8_t[], size_t)
+ {
+ throw Invalid_State("Message recovery not supported");
+ }
+
+ std::unique_ptr<EMSA> clone_emsa() const { return std::unique_ptr<EMSA>(m_emsa->clone()); }
+
+ private:
+ std::unique_ptr<EMSA> m_emsa;
+ const std::string m_hash;
+ bool m_prefix_used;
+ };
+
+class Signature_with_EMSA : public Signature
+ {
+ public:
+ void update(const uint8_t msg[], size_t msg_len) override;
+
+ secure_vector<uint8_t> sign(RandomNumberGenerator& rng) override;
+ protected:
+ explicit Signature_with_EMSA(const std::string& emsa);
+ ~Signature_with_EMSA() = default;
+
+ std::string hash_for_signature() { return m_hash; }
+
+ /**
+ * @return boolean specifying if this signature scheme uses
+ * a message prefix returned by message_prefix()
+ */
+ virtual bool has_prefix() { return false; }
+
+ /**
+ * @return the message prefix if this signature scheme uses
+ * a message prefix, signaled via has_prefix()
+ */
+ virtual secure_vector<uint8_t> message_prefix() const { throw Exception( "No prefix" ); }
+
+ std::unique_ptr<EMSA> clone_emsa() const { return std::unique_ptr<EMSA>(m_emsa->clone()); }
+
+ private:
+
+ /**
+ * Get the maximum message size in bits supported by this public key.
+ * @return maximum message in bits
+ */
+ virtual size_t max_input_bits() const = 0;
+
+ bool self_test_signature(const std::vector<uint8_t>& msg,
+ const std::vector<uint8_t>& sig) const;
+
+ virtual secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator& rng) = 0;
+
+ std::unique_ptr<EMSA> m_emsa;
+ const std::string m_hash;
+ bool m_prefix_used;
+ };
+
+class Key_Agreement_with_KDF : public Key_Agreement
+ {
+ public:
+ secure_vector<uint8_t> agree(size_t key_len,
+ const uint8_t other_key[], size_t other_key_len,
+ const uint8_t salt[], size_t salt_len) override;
+
+ protected:
+ explicit Key_Agreement_with_KDF(const std::string& kdf);
+ ~Key_Agreement_with_KDF() = default;
+ private:
+ virtual secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) = 0;
+ std::unique_ptr<KDF> m_kdf;
+ };
+
+class KEM_Encryption_with_KDF : public KEM_Encryption
+ {
+ public:
+ void kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& out_shared_key,
+ size_t desired_shared_key_len,
+ Botan::RandomNumberGenerator& rng,
+ const uint8_t salt[],
+ size_t salt_len) override;
+
+ protected:
+ virtual void raw_kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& raw_shared_key,
+ Botan::RandomNumberGenerator& rng) = 0;
+
+ explicit KEM_Encryption_with_KDF(const std::string& kdf);
+ ~KEM_Encryption_with_KDF() = default;
+ private:
+ std::unique_ptr<KDF> m_kdf;
+ };
+
+class KEM_Decryption_with_KDF : public KEM_Decryption
+ {
+ public:
+ secure_vector<uint8_t> kem_decrypt(const uint8_t encap_key[],
+ size_t len,
+ size_t desired_shared_key_len,
+ const uint8_t salt[],
+ size_t salt_len) override;
+
+ protected:
+ virtual secure_vector<uint8_t>
+ raw_kem_decrypt(const uint8_t encap_key[], size_t len) = 0;
+
+ explicit KEM_Decryption_with_KDF(const std::string& kdf);
+ ~KEM_Decryption_with_KDF() = default;
+ private:
+ std::unique_ptr<KDF> m_kdf;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pkcs8.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/pkcs8.cpp
new file mode 100644
index 0000000000..8d3eba6dc7
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pkcs8.cpp
@@ -0,0 +1,468 @@
+/*
+* PKCS #8
+* (C) 1999-2010,2014,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/pkcs8.h>
+#include <botan/rng.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/alg_id.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/scan_name.h>
+#include <botan/pk_algs.h>
+
+#if defined(BOTAN_HAS_PKCS5_PBES2)
+ #include <botan/pbes2.h>
+#endif
+
+namespace Botan {
+
+namespace PKCS8 {
+
+namespace {
+
+/*
+* Get info from an EncryptedPrivateKeyInfo
+*/
+secure_vector<uint8_t> PKCS8_extract(DataSource& source,
+ AlgorithmIdentifier& pbe_alg_id)
+ {
+ secure_vector<uint8_t> key_data;
+
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .decode(pbe_alg_id)
+ .decode(key_data, OCTET_STRING)
+ .verify_end();
+
+ return key_data;
+ }
+
+/*
+* PEM decode and/or decrypt a private key
+*/
+secure_vector<uint8_t> PKCS8_decode(
+ DataSource& source,
+ std::function<std::string ()> get_passphrase,
+ AlgorithmIdentifier& pk_alg_id,
+ bool is_encrypted)
+ {
+ AlgorithmIdentifier pbe_alg_id;
+ secure_vector<uint8_t> key_data, key;
+
+ try {
+ if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+ {
+ if(is_encrypted)
+ {
+ key_data = PKCS8_extract(source, pbe_alg_id);
+ }
+ else
+ {
+ // todo read more efficiently
+ while(!source.end_of_data())
+ {
+ uint8_t b;
+ size_t read = source.read_byte(b);
+ if(read)
+ {
+ key_data.push_back(b);
+ }
+ }
+ }
+ }
+ else
+ {
+ std::string label;
+ key_data = PEM_Code::decode(source, label);
+
+ // todo remove autodetect for pem as well?
+ if(label == "PRIVATE KEY")
+ is_encrypted = false;
+ else if(label == "ENCRYPTED PRIVATE KEY")
+ {
+ DataSource_Memory key_source(key_data);
+ key_data = PKCS8_extract(key_source, pbe_alg_id);
+ }
+ else
+ throw PKCS8_Exception("Unknown PEM label " + label);
+ }
+
+ if(key_data.empty())
+ throw PKCS8_Exception("No key data found");
+ }
+ catch(Decoding_Error& e)
+ {
+ throw Decoding_Error("PKCS #8 private key decoding failed: " + std::string(e.what()));
+ }
+
+ try
+ {
+ if(is_encrypted)
+ {
+ if(OIDS::lookup(pbe_alg_id.get_oid()) != "PBE-PKCS5v20")
+ throw Exception("Unknown PBE type " + pbe_alg_id.get_oid().as_string());
+#if defined(BOTAN_HAS_PKCS5_PBES2)
+ key = pbes2_decrypt(key_data, get_passphrase(), pbe_alg_id.get_parameters());
+#else
+ BOTAN_UNUSED(get_passphrase);
+ throw Decoding_Error("Private key is encrypted but PBES2 was disabled in build");
+#endif
+ }
+ else
+ key = key_data;
+
+ BER_Decoder(key)
+ .start_cons(SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
+ .decode(pk_alg_id)
+ .decode(key, OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+ }
+ catch(std::exception& e)
+ {
+ throw Decoding_Error("PKCS #8 private key decoding failed: " + std::string(e.what()));
+ }
+ return key;
+ }
+
+}
+
+/*
+* BER encode a PKCS #8 private key, unencrypted
+*/
+secure_vector<uint8_t> BER_encode(const Private_Key& key)
+ {
+ // keeping around for compat
+ return key.private_key_info();
+ }
+
+/*
+* PEM encode a PKCS #8 private key, unencrypted
+*/
+std::string PEM_encode(const Private_Key& key)
+ {
+ return PEM_Code::encode(PKCS8::BER_encode(key), "PRIVATE KEY");
+ }
+
+#if defined(BOTAN_HAS_PKCS5_PBES2)
+
+namespace {
+
+std::pair<std::string, std::string>
+choose_pbe_params(const std::string& pbe_algo, const std::string& key_algo)
+ {
+ if(pbe_algo.empty())
+ {
+ // Defaults:
+ if(key_algo == "Curve25519" || key_algo == "McEliece")
+ return std::make_pair("AES-256/GCM", "SHA-512");
+ else // for everything else (RSA, DSA, ECDSA, GOST, ...)
+ return std::make_pair("AES-256/CBC", "SHA-256");
+ }
+
+ SCAN_Name request(pbe_algo);
+ if(request.algo_name() != "PBE-PKCS5v20" || request.arg_count() != 2)
+ throw Exception("Unsupported PBE " + pbe_algo);
+ return std::make_pair(request.arg(0), request.arg(1));
+ }
+
+}
+
+#endif
+
+/*
+* BER encode a PKCS #8 private key, encrypted
+*/
+std::vector<uint8_t> BER_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds msec,
+ const std::string& pbe_algo)
+ {
+#if defined(BOTAN_HAS_PKCS5_PBES2)
+ const auto pbe_params = choose_pbe_params(pbe_algo, key.algo_name());
+
+ const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info =
+ pbes2_encrypt_msec(PKCS8::BER_encode(key), pass, msec, nullptr,
+ pbe_params.first, pbe_params.second, rng);
+
+ std::vector<uint8_t> output;
+ DER_Encoder der(output);
+ der.start_cons(SEQUENCE)
+ .encode(pbe_info.first)
+ .encode(pbe_info.second, OCTET_STRING)
+ .end_cons();
+
+ return output;
+#else
+ BOTAN_UNUSED(key, rng, pass, msec, pbe_algo);
+ throw Encoding_Error("PKCS8::BER_encode cannot encrypt because PBES2 was disabled in build");
+#endif
+ }
+
+/*
+* PEM encode a PKCS #8 private key, encrypted
+*/
+std::string PEM_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds msec,
+ const std::string& pbe_algo)
+ {
+ if(pass.empty())
+ return PEM_encode(key);
+
+ return PEM_Code::encode(PKCS8::BER_encode(key, rng, pass, msec, pbe_algo),
+ "ENCRYPTED PRIVATE KEY");
+ }
+
+/*
+* BER encode a PKCS #8 private key, encrypted
+*/
+std::vector<uint8_t> BER_encode_encrypted_pbkdf_iter(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ size_t pbkdf_iterations,
+ const std::string& cipher,
+ const std::string& pbkdf_hash)
+ {
+#if defined(BOTAN_HAS_PKCS5_PBES2)
+ const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info =
+ pbes2_encrypt_iter(key.private_key_info(),
+ pass, pbkdf_iterations,
+ cipher.empty() ? "AES-256/CBC" : cipher,
+ pbkdf_hash.empty() ? "SHA-256" : pbkdf_hash,
+ rng);
+
+ std::vector<uint8_t> output;
+ DER_Encoder der(output);
+ der.start_cons(SEQUENCE)
+ .encode(pbe_info.first)
+ .encode(pbe_info.second, OCTET_STRING)
+ .end_cons();
+
+ return output;
+
+#else
+ BOTAN_UNUSED(key, rng, pass, pbkdf_iterations, cipher, pbkdf_hash);
+ throw Encoding_Error("PKCS8::BER_encode_encrypted_pbkdf_iter cannot encrypt because PBES2 disabled in build");
+#endif
+ }
+
+/*
+* PEM encode a PKCS #8 private key, encrypted
+*/
+std::string PEM_encode_encrypted_pbkdf_iter(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ size_t pbkdf_iterations,
+ const std::string& cipher,
+ const std::string& pbkdf_hash)
+ {
+ return PEM_Code::encode(
+ PKCS8::BER_encode_encrypted_pbkdf_iter(key, rng, pass, pbkdf_iterations, cipher, pbkdf_hash),
+ "ENCRYPTED PRIVATE KEY");
+ }
+
+/*
+* BER encode a PKCS #8 private key, encrypted
+*/
+std::vector<uint8_t> BER_encode_encrypted_pbkdf_msec(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds pbkdf_msec,
+ size_t* pbkdf_iterations,
+ const std::string& cipher,
+ const std::string& pbkdf_hash)
+ {
+#if defined(BOTAN_HAS_PKCS5_PBES2)
+ const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info =
+ pbes2_encrypt_msec(key.private_key_info(), pass,
+ pbkdf_msec, pbkdf_iterations,
+ cipher.empty() ? "AES-256/CBC" : cipher,
+ pbkdf_hash.empty() ? "SHA-256" : pbkdf_hash,
+ rng);
+
+ std::vector<uint8_t> output;
+ DER_Encoder(output)
+ .start_cons(SEQUENCE)
+ .encode(pbe_info.first)
+ .encode(pbe_info.second, OCTET_STRING)
+ .end_cons();
+
+ return output;
+#else
+ BOTAN_UNUSED(key, rng, pass, pbkdf_msec, pbkdf_iterations, cipher, pbkdf_hash);
+ throw Encoding_Error("BER_encode_encrypted_pbkdf_msec cannot encrypt because PBES2 disabled in build");
+#endif
+ }
+
+/*
+* PEM encode a PKCS #8 private key, encrypted
+*/
+std::string PEM_encode_encrypted_pbkdf_msec(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds pbkdf_msec,
+ size_t* pbkdf_iterations,
+ const std::string& cipher,
+ const std::string& pbkdf_hash)
+ {
+ return PEM_Code::encode(
+ PKCS8::BER_encode_encrypted_pbkdf_msec(key, rng, pass, pbkdf_msec, pbkdf_iterations, cipher, pbkdf_hash),
+ "ENCRYPTED PRIVATE KEY");
+ }
+
+namespace {
+
+/*
+* Extract a private key (encrypted/unencrypted) and return it
+*/
+std::unique_ptr<Private_Key>
+load_key(DataSource& source,
+ std::function<std::string ()> get_pass,
+ bool is_encrypted)
+ {
+ AlgorithmIdentifier alg_id;
+ secure_vector<uint8_t> pkcs8_key = PKCS8_decode(source, get_pass, alg_id, is_encrypted);
+
+ const std::string alg_name = OIDS::lookup(alg_id.get_oid());
+ if(alg_name.empty() || alg_name == alg_id.get_oid().as_string())
+ throw PKCS8_Exception("Unknown algorithm OID: " +
+ alg_id.get_oid().as_string());
+
+ return load_private_key(alg_id, pkcs8_key);
+ }
+
+}
+
+/*
+* Extract an encrypted private key and return it
+*/
+std::unique_ptr<Private_Key> load_key(DataSource& source,
+ std::function<std::string ()> get_pass)
+ {
+ return load_key(source, get_pass, true);
+ }
+
+/*
+* Extract an encrypted private key and return it
+*/
+std::unique_ptr<Private_Key> load_key(DataSource& source,
+ const std::string& pass)
+ {
+ return load_key(source, [pass]() { return pass; }, true);
+ }
+
+/*
+* Extract an unencrypted private key and return it
+*/
+std::unique_ptr<Private_Key> load_key(DataSource& source)
+ {
+ auto fail_fn = []() -> std::string {
+ throw PKCS8_Exception("Internal error: Attempt to read password for unencrypted key");
+ };
+
+ return load_key(source, fail_fn, false);
+ }
+
+/*
+* Make a copy of this private key
+*/
+std::unique_ptr<Private_Key> copy_key(const Private_Key& key)
+ {
+ DataSource_Memory source(PEM_encode(key));
+ return PKCS8::load_key(source);
+ }
+
+/*
+* Extract an encrypted private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ std::function<std::string ()> get_pass)
+ {
+ BOTAN_UNUSED(rng);
+ return PKCS8::load_key(source, get_pass).release();
+ }
+
+/*
+* Extract an encrypted private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const std::string& pass)
+ {
+ BOTAN_UNUSED(rng);
+ return PKCS8::load_key(source, pass).release();
+ }
+
+/*
+* Extract an unencrypted private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng)
+ {
+ BOTAN_UNUSED(rng);
+ return PKCS8::load_key(source).release();
+ }
+
+#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
+
+/*
+* Extract an encrypted private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ std::function<std::string ()> get_pass)
+ {
+ BOTAN_UNUSED(rng);
+ DataSource_Stream in(fsname);
+ return PKCS8::load_key(in, get_pass).release();
+ }
+
+/*
+* Extract an encrypted private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ const std::string& pass)
+ {
+ BOTAN_UNUSED(rng);
+ DataSource_Stream in(fsname);
+ return PKCS8::load_key(in, [pass]() { return pass; }).release();
+ }
+
+/*
+* Extract an unencrypted private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng)
+ {
+ BOTAN_UNUSED(rng);
+ DataSource_Stream in(fsname);
+ return PKCS8::load_key(in).release();
+ }
+#endif
+
+/*
+* Make a copy of this private key
+*/
+Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ BOTAN_UNUSED(rng);
+ return PKCS8::copy_key(key).release();
+ }
+
+
+
+}
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pkcs8.h b/src/libs/3rdparty/botan/src/lib/pubkey/pkcs8.h
new file mode 100644
index 0000000000..0bc9a18f14
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pkcs8.h
@@ -0,0 +1,288 @@
+/*
+* PKCS #8
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PKCS8_H_
+#define BOTAN_PKCS8_H_
+
+#include <botan/pk_keys.h>
+#include <botan/exceptn.h>
+#include <botan/secmem.h>
+#include <functional>
+#include <chrono>
+#include <memory>
+
+namespace Botan {
+
+class DataSource;
+class RandomNumberGenerator;
+
+/**
+* PKCS #8 General Exception
+*/
+class BOTAN_PUBLIC_API(2,0) PKCS8_Exception final : public Decoding_Error
+ {
+ public:
+ explicit PKCS8_Exception(const std::string& error) :
+ Decoding_Error("PKCS #8: " + error) {}
+ };
+
+/**
+* This namespace contains functions for handling PKCS #8 private keys
+*/
+namespace PKCS8 {
+
+/**
+* BER encode a private key
+* @param key the private key to encode
+* @return BER encoded key
+*/
+BOTAN_PUBLIC_API(2,0) secure_vector<uint8_t> BER_encode(const Private_Key& key);
+
+/**
+* Get a string containing a PEM encoded private key.
+* @param key the key to encode
+* @return encoded key
+*/
+BOTAN_PUBLIC_API(2,0) std::string PEM_encode(const Private_Key& key);
+
+/**
+* Encrypt a key using PKCS #8 encryption
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param msec number of milliseconds to run the password derivation
+* @param pbe_algo the name of the desired password-based encryption
+* algorithm; if empty ("") a reasonable (portable/secure)
+* default will be chosen.
+* @return encrypted key in binary BER form
+*/
+BOTAN_PUBLIC_API(2,0) std::vector<uint8_t>
+BER_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds msec = std::chrono::milliseconds(300),
+ const std::string& pbe_algo = "");
+
+/**
+* Get a string containing a PEM encoded private key, encrypting it with a
+* password.
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param msec number of milliseconds to run the password derivation
+* @param pbe_algo the name of the desired password-based encryption
+* algorithm; if empty ("") a reasonable (portable/secure)
+* default will be chosen.
+* @return encrypted key in PEM form
+*/
+BOTAN_PUBLIC_API(2,0) std::string
+PEM_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds msec = std::chrono::milliseconds(300),
+ const std::string& pbe_algo = "");
+
+/**
+* Encrypt a key using PKCS #8 encryption and a fixed iteration count
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param pbkdf_iter number of interations to run PBKDF2
+* @param cipher if non-empty specifies the cipher to use. CBC and GCM modes
+* are supported, for example "AES-128/CBC", "AES-256/GCM", "Serpent/CBC".
+* If empty a suitable default is chosen.
+* @param pbkdf_hash if non-empty specifies the PBKDF hash function to use.
+* For example "SHA-256" or "SHA-384". If empty a suitable default is chosen.
+* @return encrypted key in binary BER form
+*/
+BOTAN_PUBLIC_API(2,1) std::vector<uint8_t>
+BER_encode_encrypted_pbkdf_iter(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ size_t pbkdf_iter,
+ const std::string& cipher = "",
+ const std::string& pbkdf_hash = "");
+
+/**
+* Get a string containing a PEM encoded private key, encrypting it with a
+* password.
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param pbkdf_iter number of iterations to run PBKDF
+* @param cipher if non-empty specifies the cipher to use. CBC and GCM modes
+* are supported, for example "AES-128/CBC", "AES-256/GCM", "Serpent/CBC".
+* If empty a suitable default is chosen.
+* @param pbkdf_hash if non-empty specifies the PBKDF hash function to use.
+* For example "SHA-256" or "SHA-384". If empty a suitable default is chosen.
+* @return encrypted key in PEM form
+*/
+BOTAN_PUBLIC_API(2,1) std::string
+PEM_encode_encrypted_pbkdf_iter(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ size_t pbkdf_iter,
+ const std::string& cipher = "",
+ const std::string& pbkdf_hash = "");
+
+/**
+* Encrypt a key using PKCS #8 encryption and a variable iteration count
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param pbkdf_msec how long to run PBKDF2
+* @param pbkdf_iterations if non-null, set to the number of iterations used
+* @param cipher if non-empty specifies the cipher to use. CBC and GCM modes
+* are supported, for example "AES-128/CBC", "AES-256/GCM", "Serpent/CBC".
+* If empty a suitable default is chosen.
+* @param pbkdf_hash if non-empty specifies the PBKDF hash function to use.
+* For example "SHA-256" or "SHA-384". If empty a suitable default is chosen.
+* @return encrypted key in binary BER form
+*/
+BOTAN_PUBLIC_API(2,1) std::vector<uint8_t>
+BER_encode_encrypted_pbkdf_msec(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds pbkdf_msec,
+ size_t* pbkdf_iterations,
+ const std::string& cipher = "",
+ const std::string& pbkdf_hash = "");
+
+/**
+* Get a string containing a PEM encoded private key, encrypting it with a
+* password.
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param pbkdf_msec how long in milliseconds to run PBKDF2
+* @param pbkdf_iterations (output argument) number of iterations of PBKDF
+* that ended up being used
+* @param cipher if non-empty specifies the cipher to use. CBC and GCM modes
+* are supported, for example "AES-128/CBC", "AES-256/GCM", "Serpent/CBC".
+* If empty a suitable default is chosen.
+* @param pbkdf_hash if non-empty specifies the PBKDF hash function to use.
+* For example "SHA-256" or "SHA-384". If empty a suitable default is chosen.
+* @return encrypted key in PEM form
+*/
+BOTAN_PUBLIC_API(2,1) std::string
+PEM_encode_encrypted_pbkdf_msec(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds pbkdf_msec,
+ size_t* pbkdf_iterations,
+ const std::string& cipher = "",
+ const std::string& pbkdf_hash = "");
+
+/**
+* Load an encrypted key from a data source.
+* @param source the data source providing the encoded key
+* @param rng ignored for compatability
+* @param get_passphrase a function that returns passphrases
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,0) Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ std::function<std::string ()> get_passphrase);
+
+/** Load an encrypted key from a data source.
+* @param source the data source providing the encoded key
+* @param rng ignored for compatability
+* @param pass the passphrase to decrypt the key
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,0) Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const std::string& pass);
+
+/** Load an unencrypted key from a data source.
+* @param source the data source providing the encoded key
+* @param rng ignored for compatability
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,0) Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng);
+
+#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
+/**
+* Load an encrypted key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng ignored for compatability
+* @param get_passphrase a function that returns passphrases
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,0) Private_Key* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ std::function<std::string ()> get_passphrase);
+
+/** Load an encrypted key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng ignored for compatability
+* @param pass the passphrase to decrypt the key
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,0) Private_Key* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const std::string& pass);
+
+/** Load an unencrypted key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng ignored for compatability
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,0) Private_Key* load_key(const std::string& filename,
+ RandomNumberGenerator& rng);
+#endif
+
+/**
+* Copy an existing encoded key object.
+* @param key the key to copy
+* @param rng ignored for compatability
+* @return new copy of the key
+*/
+BOTAN_PUBLIC_API(2,0) Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng);
+
+
+/**
+* Load an encrypted key from a data source.
+* @param source the data source providing the encoded key
+* @param get_passphrase a function that returns passphrases
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,3)
+std::unique_ptr<Private_Key> load_key(DataSource& source,
+ std::function<std::string ()> get_passphrase);
+
+/** Load an encrypted key from a data source.
+* @param source the data source providing the encoded key
+* @param pass the passphrase to decrypt the key
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,3)
+std::unique_ptr<Private_Key> load_key(DataSource& source,
+ const std::string& pass);
+
+/** Load an unencrypted key from a data source.
+* @param source the data source providing the encoded key
+* @return loaded private key object
+*/
+BOTAN_PUBLIC_API(2,3)
+std::unique_ptr<Private_Key> load_key(DataSource& source);
+
+/**
+* Copy an existing encoded key object.
+* @param key the key to copy
+* @return new copy of the key
+*/
+BOTAN_PUBLIC_API(2,3)
+std::unique_ptr<Private_Key> copy_key(const Private_Key& key);
+
+}
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pubkey.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/pubkey.cpp
new file mode 100644
index 0000000000..99d8927663
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pubkey.cpp
@@ -0,0 +1,350 @@
+/*
+* (C) 1999-2010,2015,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/pubkey.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/bigint.h>
+#include <botan/pk_ops.h>
+#include <botan/internal/ct_utils.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+secure_vector<uint8_t> PK_Decryptor::decrypt(const uint8_t in[], size_t length) const
+ {
+ uint8_t valid_mask = 0;
+
+ secure_vector<uint8_t> decoded = do_decrypt(valid_mask, in, length);
+
+ if(valid_mask == 0)
+ throw Decoding_Error("Invalid public key ciphertext, cannot decrypt");
+
+ return decoded;
+ }
+
+secure_vector<uint8_t>
+PK_Decryptor::decrypt_or_random(const uint8_t in[],
+ size_t length,
+ size_t expected_pt_len,
+ RandomNumberGenerator& rng,
+ const uint8_t required_content_bytes[],
+ const uint8_t required_content_offsets[],
+ size_t required_contents_length) const
+ {
+ const secure_vector<uint8_t> fake_pms = rng.random_vec(expected_pt_len);
+
+ uint8_t valid_mask = 0;
+ secure_vector<uint8_t> decoded = do_decrypt(valid_mask, in, length);
+
+ valid_mask &= CT::is_equal(decoded.size(), expected_pt_len);
+
+ decoded.resize(expected_pt_len);
+
+ for(size_t i = 0; i != required_contents_length; ++i)
+ {
+ /*
+ These values are chosen by the application and for TLS are constants,
+ so this early failure via assert is fine since we know 0,1 < 48
+
+ If there is a protocol that has content checks on the key where
+ the expected offsets are controllable by the attacker this could
+ still leak.
+
+ Alternately could always reduce the offset modulo the length?
+ */
+
+ const uint8_t exp = required_content_bytes[i];
+ const uint8_t off = required_content_offsets[i];
+
+ BOTAN_ASSERT(off < expected_pt_len, "Offset in range of plaintext");
+
+ valid_mask &= CT::is_equal(decoded[off], exp);
+ }
+
+ CT::conditional_copy_mem(valid_mask,
+ /*output*/decoded.data(),
+ /*from0*/decoded.data(),
+ /*from1*/fake_pms.data(),
+ expected_pt_len);
+
+ return decoded;
+ }
+
+secure_vector<uint8_t>
+PK_Decryptor::decrypt_or_random(const uint8_t in[],
+ size_t length,
+ size_t expected_pt_len,
+ RandomNumberGenerator& rng) const
+ {
+ return decrypt_or_random(in, length, expected_pt_len, rng,
+ nullptr, nullptr, 0);
+ }
+
+PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& padding,
+ const std::string& 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<uint8_t>
+PK_Encryptor_EME::enc(const uint8_t in[], size_t length, RandomNumberGenerator& rng) const
+ {
+ return unlock(m_op->encrypt(in, length, rng));
+ }
+
+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,
+ RandomNumberGenerator& rng,
+ const std::string& padding,
+ const std::string& 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<uint8_t> PK_Decryptor_EME::do_decrypt(uint8_t& valid_mask,
+ const uint8_t in[], size_t in_len) const
+ {
+ return m_op->decrypt(valid_mask, in, in_len);
+ }
+
+PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& param,
+ const std::string& 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<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& out_shared_key,
+ size_t desired_shared_key_len,
+ Botan::RandomNumberGenerator& rng,
+ const uint8_t salt[],
+ size_t salt_len)
+ {
+ m_op->kem_encrypt(out_encapsulated_key,
+ out_shared_key,
+ desired_shared_key_len,
+ rng,
+ salt,
+ salt_len);
+ }
+
+PK_KEM_Decryptor::PK_KEM_Decryptor(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& param,
+ const std::string& 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<uint8_t> PK_KEM_Decryptor::decrypt(const uint8_t encap_key[],
+ size_t encap_key_len,
+ size_t desired_shared_key_len,
+ const uint8_t salt[],
+ size_t salt_len)
+ {
+ return m_op->kem_decrypt(encap_key, encap_key_len,
+ desired_shared_key_len,
+ salt, salt_len);
+ }
+
+PK_Key_Agreement::PK_Key_Agreement(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& kdf,
+ const std::string& 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 uint8_t in[], size_t in_len,
+ const uint8_t salt[],
+ size_t salt_len) const
+ {
+ return m_op->agree(key_len, in, in_len, salt, salt_len);
+ }
+
+PK_Signer::PK_Signer(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& emsa,
+ Signature_Format format,
+ const std::string& 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;
+ m_parts = key.message_parts();
+ m_part_size = key.message_part_size();
+ }
+
+PK_Signer::~PK_Signer() { /* for unique_ptr */ }
+
+void PK_Signer::update(const uint8_t in[], size_t length)
+ {
+ m_op->update(in, length);
+ }
+
+namespace {
+
+std::vector<uint8_t> der_encode_signature(const std::vector<uint8_t>& sig,
+ size_t parts,
+ size_t part_size)
+ {
+ if(sig.size() % parts != 0 || sig.size() != parts * part_size)
+ throw Encoding_Error("Unexpected size for DER signature");
+
+ std::vector<BigInt> sig_parts(parts);
+ for(size_t i = 0; i != sig_parts.size(); ++i)
+ sig_parts[i].binary_decode(&sig[part_size*i], part_size);
+
+ std::vector<uint8_t> output;
+ DER_Encoder(output)
+ .start_cons(SEQUENCE)
+ .encode_list(sig_parts)
+ .end_cons();
+ return output;
+ }
+
+}
+
+std::vector<uint8_t> PK_Signer::signature(RandomNumberGenerator& rng)
+ {
+ const std::vector<uint8_t> sig = unlock(m_op->sign(rng));
+
+ if(m_sig_format == IEEE_1363)
+ {
+ return sig;
+ }
+ else if(m_sig_format == DER_SEQUENCE)
+ {
+ return der_encode_signature(sig, m_parts, m_part_size);
+ }
+ else
+ throw Internal_Error("PK_Signer: Invalid signature format enum");
+ }
+
+PK_Verifier::PK_Verifier(const Public_Key& key,
+ const std::string& emsa,
+ Signature_Format format,
+ const std::string& 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;
+ m_parts = key.message_parts();
+ m_part_size = key.message_part_size();
+ }
+
+PK_Verifier::~PK_Verifier() { /* for unique_ptr */ }
+
+void PK_Verifier::set_input_format(Signature_Format format)
+ {
+ if(format != IEEE_1363 && m_parts == 1)
+ throw Invalid_Argument("PK_Verifier: This algorithm does not support DER encoding");
+ m_sig_format = format;
+ }
+
+bool PK_Verifier::verify_message(const uint8_t msg[], size_t msg_length,
+ const uint8_t sig[], size_t sig_length)
+ {
+ update(msg, msg_length);
+ return check_signature(sig, sig_length);
+ }
+
+void PK_Verifier::update(const uint8_t in[], size_t length)
+ {
+ m_op->update(in, length);
+ }
+
+bool PK_Verifier::check_signature(const uint8_t sig[], size_t length)
+ {
+ try {
+ if(m_sig_format == IEEE_1363)
+ {
+ return m_op->is_valid_signature(sig, length);
+ }
+ else if(m_sig_format == DER_SEQUENCE)
+ {
+ std::vector<uint8_t> real_sig;
+ BER_Decoder decoder(sig, length);
+ BER_Decoder ber_sig = decoder.start_cons(SEQUENCE);
+
+ BOTAN_ASSERT_NOMSG(m_parts != 0 && m_part_size != 0);
+
+ size_t count = 0;
+
+ while(ber_sig.more_items())
+ {
+ BigInt sig_part;
+ ber_sig.decode(sig_part);
+ real_sig += BigInt::encode_1363(sig_part, m_part_size);
+ ++count;
+ }
+
+ if(count != m_parts)
+ throw Decoding_Error("PK_Verifier: signature size invalid");
+
+ const std::vector<uint8_t> reencoded =
+ der_encode_signature(real_sig, m_parts, m_part_size);
+
+ if(reencoded.size() != length ||
+ same_mem(reencoded.data(), sig, reencoded.size()) == false)
+ {
+ throw Decoding_Error("PK_Verifier: signature is not the canonical DER encoding");
+ }
+
+ return m_op->is_valid_signature(real_sig.data(), real_sig.size());
+ }
+ else
+ throw Internal_Error("PK_Verifier: Invalid signature format enum");
+ }
+ catch(Invalid_Argument&) { return false; }
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/pubkey.h b/src/libs/3rdparty/botan/src/lib/pubkey/pubkey.h
new file mode 100644
index 0000000000..a33142079f
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/pubkey.h
@@ -0,0 +1,771 @@
+/*
+* Public Key Interface
+* (C) 1999-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PUBKEY_H_
+#define BOTAN_PUBKEY_H_
+
+#include <botan/pk_keys.h>
+#include <botan/pk_ops_fwd.h>
+#include <botan/symkey.h>
+
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ #include <botan/system_rng.h>
+ #define BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS
+#endif
+
+namespace Botan {
+
+class RandomNumberGenerator;
+
+/**
+* The two types of signature format supported by Botan.
+*/
+enum Signature_Format { IEEE_1363, DER_SEQUENCE };
+
+/**
+* Public Key Encryptor
+* This is the primary interface for public key encryption
+*/
+class BOTAN_PUBLIC_API(2,0) PK_Encryptor
+ {
+ public:
+
+ /**
+ * Encrypt a message.
+ * @param in the message as a byte array
+ * @param length the length of the above byte array
+ * @param rng the random number source to use
+ * @return encrypted message
+ */
+ std::vector<uint8_t> encrypt(const uint8_t in[], size_t length,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(in, length, rng);
+ }
+
+ /**
+ * Encrypt a message.
+ * @param in the message
+ * @param rng the random number source to use
+ * @return encrypted message
+ */
+ template<typename Alloc>
+ std::vector<uint8_t> encrypt(const std::vector<uint8_t, Alloc>& in,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(in.data(), in.size(), rng);
+ }
+
+ /**
+ * Return the maximum allowed message size in bytes.
+ * @return maximum message size in bytes
+ */
+ virtual size_t maximum_input_size() const = 0;
+
+ PK_Encryptor() = default;
+ virtual ~PK_Encryptor() = default;
+
+ PK_Encryptor(const PK_Encryptor&) = delete;
+ PK_Encryptor& operator=(const PK_Encryptor&) = delete;
+
+ private:
+ virtual std::vector<uint8_t> enc(const uint8_t[], size_t,
+ RandomNumberGenerator&) const = 0;
+ };
+
+/**
+* Public Key Decryptor
+*/
+class BOTAN_PUBLIC_API(2,0) PK_Decryptor
+ {
+ public:
+ /**
+ * Decrypt a ciphertext, throwing an exception if the input
+ * seems to be invalid (eg due to an accidental or malicious
+ * error in the ciphertext).
+ *
+ * @param in the ciphertext as a byte array
+ * @param length the length of the above byte array
+ * @return decrypted message
+ */
+ secure_vector<uint8_t> decrypt(const uint8_t in[], size_t length) const;
+
+ /**
+ * Same as above, but taking a vector
+ * @param in the ciphertext
+ * @return decrypted message
+ */
+ template<typename Alloc>
+ secure_vector<uint8_t> decrypt(const std::vector<uint8_t, Alloc>& in) const
+ {
+ return decrypt(in.data(), in.size());
+ }
+
+ /**
+ * Decrypt a ciphertext. If the ciphertext is invalid (eg due to
+ * invalid padding) or is not the expected length, instead
+ * returns a random string of the expected length. Use to avoid
+ * oracle attacks, especially against PKCS #1 v1.5 decryption.
+ */
+ secure_vector<uint8_t>
+ decrypt_or_random(const uint8_t in[],
+ size_t length,
+ size_t expected_pt_len,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Decrypt a ciphertext. If the ciphertext is invalid (eg due to
+ * invalid padding) or is not the expected length, instead
+ * returns a random string of the expected length. Use to avoid
+ * oracle attacks, especially against PKCS #1 v1.5 decryption.
+ *
+ * Additionally checks (also in const time) that:
+ * contents[required_content_offsets[i]] == required_content_bytes[i]
+ * for 0 <= i < required_contents
+ *
+ * Used for example in TLS, which encodes the client version in
+ * the content bytes: if there is any timing variation the version
+ * check can be used as an oracle to recover the key.
+ */
+ secure_vector<uint8_t>
+ decrypt_or_random(const uint8_t in[],
+ size_t length,
+ size_t expected_pt_len,
+ RandomNumberGenerator& rng,
+ const uint8_t required_content_bytes[],
+ const uint8_t required_content_offsets[],
+ size_t required_contents) const;
+
+ PK_Decryptor() = default;
+ virtual ~PK_Decryptor() = default;
+
+ PK_Decryptor(const PK_Decryptor&) = delete;
+ PK_Decryptor& operator=(const PK_Decryptor&) = delete;
+
+ private:
+ virtual secure_vector<uint8_t> do_decrypt(uint8_t& valid_mask,
+ const uint8_t in[], size_t in_len) const = 0;
+ };
+
+/**
+* Public Key Signer. Use the sign_message() functions for small
+* messages. Use multiple calls update() to process large messages and
+* generate the signature by finally calling signature().
+*/
+class BOTAN_PUBLIC_API(2,0) PK_Signer final
+ {
+ public:
+
+ /**
+ * Construct a PK Signer.
+ * @param key the key to use inside this signer
+ * @param rng the random generator to use
+ * @param emsa the EMSA to use
+ * An example would be "EMSA1(SHA-224)".
+ * @param format the signature format to use
+ * @param provider the provider 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
+ * @param length the length of the above byte array
+ * @param rng the rng to use
+ * @return signature
+ */
+ std::vector<uint8_t> sign_message(const uint8_t in[], size_t length,
+ RandomNumberGenerator& rng)
+ {
+ this->update(in, length);
+ return this->signature(rng);
+ }
+
+ /**
+ * Sign a message.
+ * @param in the message to sign
+ * @param rng the rng to use
+ * @return signature
+ */
+ std::vector<uint8_t> sign_message(const std::vector<uint8_t>& in,
+ RandomNumberGenerator& rng)
+ { return sign_message(in.data(), in.size(), rng); }
+
+ /**
+ * Sign a message.
+ * @param in the message to sign
+ * @param rng the rng to use
+ * @return signature
+ */
+ std::vector<uint8_t> sign_message(const secure_vector<uint8_t>& in,
+ RandomNumberGenerator& rng)
+ { return sign_message(in.data(), in.size(), rng); }
+
+ /**
+ * Add a message part (single byte).
+ * @param in the byte to add
+ */
+ void update(uint8_t in) { update(&in, 1); }
+
+ /**
+ * Add a message part.
+ * @param in the message part to add as a byte array
+ * @param length the length of the above byte array
+ */
+ void update(const uint8_t in[], size_t length);
+
+ /**
+ * Add a message part.
+ * @param in the message part to add
+ */
+ void update(const std::vector<uint8_t>& in) { update(in.data(), in.size()); }
+
+ /**
+ * Add a message part.
+ * @param in the message part to add
+ */
+ void update(const std::string& in)
+ {
+ update(cast_char_ptr_to_uint8(in.data()), in.size());
+ }
+
+ /**
+ * Get the signature of the so far processed message (provided by the
+ * calls to update()).
+ * @param rng the rng to use
+ * @return signature of the total message
+ */
+ std::vector<uint8_t> signature(RandomNumberGenerator& rng);
+
+ /**
+ * Set the output format of the signature.
+ * @param format the signature format to use
+ */
+ void set_output_format(Signature_Format format) { m_sig_format = format; }
+ private:
+ std::unique_ptr<PK_Ops::Signature> m_op;
+ Signature_Format m_sig_format;
+ size_t m_parts, m_part_size;
+ };
+
+/**
+* Public Key Verifier. Use the verify_message() functions for small
+* messages. Use multiple calls update() to process large messages and
+* verify the signature by finally calling check_signature().
+*/
+class BOTAN_PUBLIC_API(2,0) PK_Verifier final
+ {
+ public:
+ /**
+ * Construct a PK Verifier.
+ * @param pub_key the public key to verify against
+ * @param emsa the EMSA to use (eg "EMSA3(SHA-1)")
+ * @param format the signature format to use
+ * @param provider the provider to use
+ */
+ PK_Verifier(const Public_Key& pub_key,
+ const std::string& emsa,
+ 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
+ * @param msg_length the length of the above byte array msg
+ * @param sig the signature as a byte array
+ * @param sig_length the length of the above byte array sig
+ * @return true if the signature is valid
+ */
+ bool verify_message(const uint8_t msg[], size_t msg_length,
+ const uint8_t sig[], size_t sig_length);
+ /**
+ * Verify a signature.
+ * @param msg the message that the signature belongs to
+ * @param sig the signature
+ * @return true if the signature is valid
+ */
+ template<typename Alloc, typename Alloc2>
+ bool verify_message(const std::vector<uint8_t, Alloc>& msg,
+ const std::vector<uint8_t, Alloc2>& sig)
+ {
+ return verify_message(msg.data(), msg.size(),
+ sig.data(), sig.size());
+ }
+
+ /**
+ * Add a message part (single byte) of the message corresponding to the
+ * signature to be verified.
+ * @param in the byte to add
+ */
+ void update(uint8_t in) { update(&in, 1); }
+
+ /**
+ * Add a message part of the message corresponding to the
+ * signature to be verified.
+ * @param msg_part the new message part as a byte array
+ * @param length the length of the above byte array
+ */
+ void update(const uint8_t msg_part[], size_t length);
+
+ /**
+ * Add a message part of the message corresponding to the
+ * signature to be verified.
+ * @param in the new message part
+ */
+ void update(const std::vector<uint8_t>& in)
+ { update(in.data(), in.size()); }
+
+ /**
+ * Add a message part of the message corresponding to the
+ * signature to be verified.
+ */
+ void update(const std::string& in)
+ {
+ update(cast_char_ptr_to_uint8(in.data()), in.size());
+ }
+
+ /**
+ * Check the signature of the buffered message, i.e. the one build
+ * by successive calls to update.
+ * @param sig the signature to be verified as a byte array
+ * @param length the length of the above byte array
+ * @return true if the signature is valid, false otherwise
+ */
+ bool check_signature(const uint8_t sig[], size_t length);
+
+ /**
+ * Check the signature of the buffered message, i.e. the one build
+ * by successive calls to update.
+ * @param sig the signature to be verified
+ * @return true if the signature is valid, false otherwise
+ */
+ template<typename Alloc>
+ bool check_signature(const std::vector<uint8_t, Alloc>& sig)
+ {
+ return check_signature(sig.data(), sig.size());
+ }
+
+ /**
+ * Set the format of the signatures fed to this verifier.
+ * @param format the signature format to use
+ */
+ void set_input_format(Signature_Format format);
+
+ private:
+ std::unique_ptr<PK_Ops::Verification> m_op;
+ Signature_Format m_sig_format;
+ size_t m_parts, m_part_size;
+ };
+
+/**
+* Key used for key agreement
+*/
+class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final
+ {
+ public:
+
+ /**
+ * Construct a PK Key Agreement.
+ * @param key the key to use
+ * @param rng the random generator 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)
+ */
+ 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
+ * @param in the other parties key
+ * @param in_len the length of in in bytes
+ * @param params extra derivation params
+ * @param params_len the length of params in bytes
+ */
+ SymmetricKey derive_key(size_t key_len,
+ const uint8_t in[],
+ size_t in_len,
+ const uint8_t params[],
+ size_t params_len) const;
+
+ /*
+ * Perform Key Agreement Operation
+ * @param key_len the desired key output size
+ * @param in the other parties key
+ * @param in_len the length of in in bytes
+ * @param params extra derivation params
+ * @param params_len the length of params in bytes
+ */
+ SymmetricKey derive_key(size_t key_len,
+ const std::vector<uint8_t>& in,
+ const uint8_t params[],
+ size_t params_len) const
+ {
+ return derive_key(key_len, in.data(), in.size(),
+ params, params_len);
+ }
+
+ /*
+ * Perform Key Agreement Operation
+ * @param key_len the desired key output size
+ * @param in the other parties key
+ * @param in_len the length of in in bytes
+ * @param params extra derivation params
+ */
+ SymmetricKey derive_key(size_t key_len,
+ const uint8_t in[], size_t in_len,
+ const std::string& params = "") const
+ {
+ return derive_key(key_len, in, in_len,
+ cast_char_ptr_to_uint8(params.data()),
+ params.length());
+ }
+
+ /*
+ * Perform Key Agreement Operation
+ * @param key_len the desired key output size
+ * @param in the other parties key
+ * @param params extra derivation params
+ */
+ SymmetricKey derive_key(size_t key_len,
+ const std::vector<uint8_t>& in,
+ const std::string& params = "") const
+ {
+ return derive_key(key_len, in.data(), in.size(),
+ cast_char_ptr_to_uint8(params.data()),
+ params.length());
+ }
+
+ private:
+ std::unique_ptr<PK_Ops::Key_Agreement> m_op;
+ };
+
+/**
+* Encryption using a standard message recovery algorithm like RSA or
+* ElGamal, paired with an encoding scheme like OAEP.
+*/
+class BOTAN_PUBLIC_API(2,0) 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 encryptor
+ * @param rng the RNG to use
+ * @param padding the message encoding scheme to use (eg "OAEP(SHA-256)")
+ * @param provider the provider to use
+ */
+ 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<uint8_t> enc(const uint8_t[], size_t,
+ RandomNumberGenerator& rng) const override;
+
+ std::unique_ptr<PK_Ops::Encryption> m_op;
+ };
+
+/**
+* Decryption with an MR algorithm and an EME.
+*/
+class BOTAN_PUBLIC_API(2,0) PK_Decryptor_EME final : public PK_Decryptor
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the decryptor
+ * @param rng the random generator to use
+ * @param eme the EME to use
+ * @param provider the provider to use
+ */
+ 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 eme 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<uint8_t> do_decrypt(uint8_t& valid_mask,
+ const uint8_t in[],
+ size_t in_len) const override;
+
+ std::unique_ptr<PK_Ops::Decryption> m_op;
+ };
+
+/**
+* Public Key Key Encapsulation Mechanism Encryption.
+*/
+class BOTAN_PUBLIC_API(2,0) PK_KEM_Encryptor final
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the encryptor
+ * @param rng the RNG to use
+ * @param kem_param additional KEM parameters
+ * @param provider the provider to use
+ */
+ 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;
+
+ /**
+ * Generate a shared key for data encryption.
+ * @param out_encapsulated_key the generated encapsulated key
+ * @param out_shared_key the generated shared key
+ * @param desired_shared_key_len desired size of the shared key in bytes
+ * @param rng the RNG to use
+ * @param salt a salt value used in the KDF
+ * @param salt_len size of the salt value in bytes
+ */
+ void encrypt(secure_vector<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& out_shared_key,
+ size_t desired_shared_key_len,
+ Botan::RandomNumberGenerator& rng,
+ const uint8_t salt[],
+ size_t salt_len);
+
+ /**
+ * Generate a shared key for data encryption.
+ * @param out_encapsulated_key the generated encapsulated key
+ * @param out_shared_key the generated shared key
+ * @param desired_shared_key_len desired size of the shared key in bytes
+ * @param rng the RNG to use
+ * @param salt a salt value used in the KDF
+ */
+ template<typename Alloc>
+ void encrypt(secure_vector<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& out_shared_key,
+ size_t desired_shared_key_len,
+ Botan::RandomNumberGenerator& rng,
+ const std::vector<uint8_t, Alloc>& salt)
+ {
+ this->encrypt(out_encapsulated_key,
+ out_shared_key,
+ desired_shared_key_len,
+ rng,
+ salt.data(), salt.size());
+ }
+
+
+ /**
+ * Generate a shared key for data encryption.
+ * @param out_encapsulated_key the generated encapsulated key
+ * @param out_shared_key the generated shared key
+ * @param desired_shared_key_len desired size of the shared key in bytes
+ * @param rng the RNG to use
+ */
+ void encrypt(secure_vector<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& out_shared_key,
+ size_t desired_shared_key_len,
+ Botan::RandomNumberGenerator& rng)
+ {
+ this->encrypt(out_encapsulated_key,
+ out_shared_key,
+ desired_shared_key_len,
+ rng,
+ nullptr,
+ 0);
+ }
+
+ private:
+ std::unique_ptr<PK_Ops::KEM_Encryption> m_op;
+ };
+
+/**
+* Public Key Key Encapsulation Mechanism Decryption.
+*/
+class BOTAN_PUBLIC_API(2,0) PK_KEM_Decryptor final
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the decryptor
+ * @param rng the RNG to use
+ * @param kem_param additional KEM parameters
+ * @param provider the provider to use
+ */
+ 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;
+
+ /**
+ * Decrypts the shared key for data encryption.
+ * @param encap_key the encapsulated key
+ * @param encap_key_len size of the encapsulated key in bytes
+ * @param desired_shared_key_len desired size of the shared key in bytes
+ * @param salt a salt value used in the KDF
+ * @param salt_len size of the salt value in bytes
+ * @return the shared data encryption key
+ */
+ secure_vector<uint8_t> decrypt(const uint8_t encap_key[],
+ size_t encap_key_len,
+ size_t desired_shared_key_len,
+ const uint8_t salt[],
+ size_t salt_len);
+
+ /**
+ * Decrypts the shared key for data encryption.
+ * @param encap_key the encapsulated key
+ * @param encap_key_len size of the encapsulated key in bytes
+ * @param desired_shared_key_len desired size of the shared key in bytes
+ * @return the shared data encryption key
+ */
+ secure_vector<uint8_t> decrypt(const uint8_t encap_key[],
+ size_t encap_key_len,
+ size_t desired_shared_key_len)
+ {
+ return this->decrypt(encap_key, encap_key_len,
+ desired_shared_key_len,
+ nullptr, 0);
+ }
+
+ /**
+ * Decrypts the shared key for data encryption.
+ * @param encap_key the encapsulated key
+ * @param desired_shared_key_len desired size of the shared key in bytes
+ * @param salt a salt value used in the KDF
+ * @return the shared data encryption key
+ */
+ template<typename Alloc1, typename Alloc2>
+ secure_vector<uint8_t> decrypt(const std::vector<uint8_t, Alloc1>& encap_key,
+ size_t desired_shared_key_len,
+ const std::vector<uint8_t, Alloc2>& salt)
+ {
+ return this->decrypt(encap_key.data(), encap_key.size(),
+ desired_shared_key_len,
+ salt.data(), salt.size());
+ }
+
+ private:
+ std::unique_ptr<PK_Ops::KEM_Decryption> m_op;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/rsa/info.txt b/src/libs/3rdparty/botan/src/lib/pubkey/rsa/info.txt
new file mode 100644
index 0000000000..9fc9354b83
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/rsa/info.txt
@@ -0,0 +1,10 @@
+<defines>
+RSA -> 20160730
+</defines>
+
+<requires>
+keypair
+numbertheory
+emsa_pssr
+sha2_32
+</requires>
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/rsa/rsa.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/rsa/rsa.cpp
new file mode 100644
index 0000000000..eb4c612ae0
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/rsa/rsa.cpp
@@ -0,0 +1,579 @@
+/*
+* RSA
+* (C) 1999-2010,2015,2016,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/rsa.h>
+#include <botan/internal/pk_ops_impl.h>
+#include <botan/keypair.h>
+#include <botan/blinding.h>
+#include <botan/reducer.h>
+#include <botan/workfactor.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pow_mod.h>
+#include <botan/monty.h>
+#include <botan/internal/monty_exp.h>
+
+#if defined(BOTAN_HAS_OPENSSL)
+ #include <botan/internal/openssl.h>
+#endif
+
+#if defined(BOTAN_TARGET_OS_HAS_THREADS)
+ #include <future>
+#endif
+
+namespace Botan {
+
+size_t RSA_PublicKey::key_length() const
+ {
+ return m_n.bits();
+ }
+
+size_t RSA_PublicKey::estimated_strength() const
+ {
+ return if_work_factor(key_length());
+ }
+
+AlgorithmIdentifier RSA_PublicKey::algorithm_identifier() const
+ {
+ return AlgorithmIdentifier(get_oid(),
+ AlgorithmIdentifier::USE_NULL_PARAM);
+ }
+
+std::vector<uint8_t> RSA_PublicKey::public_key_bits() const
+ {
+ std::vector<uint8_t> output;
+ DER_Encoder der(output);
+ der.start_cons(SEQUENCE)
+ .encode(m_n)
+ .encode(m_e)
+ .end_cons();
+
+ return output;
+ }
+
+RSA_PublicKey::RSA_PublicKey(const AlgorithmIdentifier&,
+ const std::vector<uint8_t>& key_bits)
+ {
+ BER_Decoder(key_bits)
+ .start_cons(SEQUENCE)
+ .decode(m_n)
+ .decode(m_e)
+ .end_cons();
+ }
+
+/*
+* Check RSA Public Parameters
+*/
+bool RSA_PublicKey::check_key(RandomNumberGenerator&, bool) const
+ {
+ if(m_n < 35 || m_n.is_even() || m_e < 3 || m_e.is_even())
+ return false;
+ return true;
+ }
+
+secure_vector<uint8_t> RSA_PrivateKey::private_key_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(static_cast<size_t>(0))
+ .encode(m_n)
+ .encode(m_e)
+ .encode(m_d)
+ .encode(m_p)
+ .encode(m_q)
+ .encode(m_d1)
+ .encode(m_d2)
+ .encode(m_c)
+ .end_cons()
+ .get_contents();
+ }
+
+RSA_PrivateKey::RSA_PrivateKey(const AlgorithmIdentifier&,
+ const secure_vector<uint8_t>& key_bits)
+ {
+ BER_Decoder(key_bits)
+ .start_cons(SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #1 key format version")
+ .decode(m_n)
+ .decode(m_e)
+ .decode(m_d)
+ .decode(m_p)
+ .decode(m_q)
+ .decode(m_d1)
+ .decode(m_d2)
+ .decode(m_c)
+ .end_cons();
+ }
+
+RSA_PrivateKey::RSA_PrivateKey(const BigInt& prime1,
+ const BigInt& prime2,
+ const BigInt& exp,
+ const BigInt& d_exp,
+ const BigInt& mod) :
+ m_d{ d_exp }, m_p{ prime1 }, m_q{ prime2 }, m_d1{}, m_d2{}, m_c{ inverse_mod( m_q, m_p ) }
+ {
+ m_n = mod.is_nonzero() ? mod : m_p * m_q;
+ m_e = exp;
+
+ if(m_d == 0)
+ {
+ const BigInt phi_n = lcm(m_p - 1, m_q - 1);
+ m_d = inverse_mod(m_e, phi_n);
+ }
+
+ m_d1 = m_d % (m_p - 1);
+ m_d2 = m_d % (m_q - 1);
+ }
+
+/*
+* Create a RSA private key
+*/
+RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng,
+ size_t bits, size_t exp)
+ {
+ if(bits < 1024)
+ throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
+ std::to_string(bits) + " bits long");
+ if(exp < 3 || exp % 2 == 0)
+ throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
+
+ m_e = exp;
+
+ const size_t p_bits = (bits + 1) / 2;
+ const size_t q_bits = bits - p_bits;
+
+ do
+ {
+ m_p = generate_rsa_prime(rng, rng, p_bits, m_e);
+ m_q = generate_rsa_prime(rng, rng, q_bits, m_e);
+ m_n = m_p * m_q;
+ } while(m_n.bits() != bits);
+
+ // FIXME: lcm calls gcd which is not const time
+ const BigInt phi_n = lcm(m_p - 1, m_q - 1);
+ // FIXME: this uses binary ext gcd because phi_n is even
+ m_d = inverse_mod(m_e, phi_n);
+ m_d1 = m_d % (m_p - 1);
+ m_d2 = m_d % (m_q - 1);
+ m_c = inverse_mod(m_q, m_p);
+ }
+
+/*
+* Check Private RSA Parameters
+*/
+bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(m_n < 35 || m_n.is_even() || m_e < 3 || m_e.is_even())
+ return false;
+
+ if(m_d < 2 || m_p < 3 || m_q < 3 || m_p*m_q != m_n)
+ return false;
+
+ if(m_d1 != m_d % (m_p - 1) || m_d2 != m_d % (m_q - 1) || m_c != inverse_mod(m_q, m_p))
+ return false;
+
+ const size_t prob = (strong) ? 128 : 12;
+
+ if(!is_prime(m_p, rng, prob) || !is_prime(m_q, rng, prob))
+ return false;
+
+ if(strong)
+ {
+ if((m_e * m_d) % lcm(m_p - 1, m_q - 1) != 1)
+ return false;
+
+ return KeyPair::signature_consistency_check(rng, *this, "EMSA4(SHA-256)");
+ }
+
+ return true;
+ }
+
+namespace {
+
+/**
+* RSA private (decrypt/sign) operation
+*/
+class RSA_Private_Operation
+ {
+ protected:
+ size_t get_max_input_bits() const { return (m_mod_bits - 1); }
+
+ const size_t exp_blinding_bits = 64;
+
+ explicit RSA_Private_Operation(const RSA_PrivateKey& rsa, RandomNumberGenerator& rng) :
+ m_key(rsa),
+ m_mod_p(m_key.get_p()),
+ m_mod_q(m_key.get_q()),
+ m_monty_p(std::make_shared<Montgomery_Params>(m_key.get_p(), m_mod_p)),
+ m_monty_q(std::make_shared<Montgomery_Params>(m_key.get_q(), m_mod_q)),
+ m_powermod_e_n(m_key.get_e(), m_key.get_n()),
+ m_blinder(m_key.get_n(),
+ rng,
+ [this](const BigInt& k) { return m_powermod_e_n(k); },
+ [this](const BigInt& k) { return inverse_mod(k, m_key.get_n()); }),
+ m_blinding_bits(64),
+ m_mod_bytes(m_key.get_n().bytes()),
+ m_mod_bits(m_key.get_n().bits()),
+ m_max_d1_bits(m_key.get_p().bits() + m_blinding_bits),
+ m_max_d2_bits(m_key.get_q().bits() + m_blinding_bits)
+ {
+ }
+
+ BigInt blinded_private_op(const BigInt& m) const
+ {
+ if(m >= m_key.get_n())
+ throw Invalid_Argument("RSA private op - input is too large");
+
+ return m_blinder.unblind(private_op(m_blinder.blind(m)));
+ }
+
+ BigInt private_op(const BigInt& m) const
+ {
+ const size_t powm_window = 4;
+
+ const BigInt d1_mask(m_blinder.rng(), m_blinding_bits);
+
+#if defined(BOTAN_TARGET_OS_HAS_THREADS)
+ auto future_j1 = std::async(std::launch::async, [this, &m, &d1_mask, powm_window]() {
+ const BigInt masked_d1 = m_key.get_d1() + (d1_mask * (m_key.get_p() - 1));
+ auto powm_d1_p = monty_precompute(m_monty_p, m, powm_window);
+ return monty_execute(*powm_d1_p, masked_d1, m_max_d1_bits);
+ });
+#else
+ const BigInt masked_d1 = m_key.get_d1() + (d1_mask * (m_key.get_p() - 1));
+ auto powm_d1_p = monty_precompute(m_monty_p, m, powm_window);
+ BigInt j1 = monty_execute(*powm_d1_p, masked_d1, m_max_d1_bits);
+#endif
+
+ const BigInt d2_mask(m_blinder.rng(), m_blinding_bits);
+ const BigInt masked_d2 = m_key.get_d2() + (d2_mask * (m_key.get_q() - 1));
+ auto powm_d2_q = monty_precompute(m_monty_q, m, powm_window);
+ const BigInt j2 = monty_execute(*powm_d2_q, masked_d2, m_max_d2_bits);
+
+ /*
+ * To recover the final value from the CRT representation (j1,j2)
+ * we use Garner's algorithm:
+ * c = q^-1 mod p (this is precomputed)
+ * h = c*(j1-j2) mod p
+ * m = j2 + h*q
+ */
+
+#if defined(BOTAN_TARGET_OS_HAS_THREADS)
+ BigInt j1 = future_j1.get();
+#endif
+
+ /*
+ To prevent a side channel that allows detecting case where j1 < j2,
+ add p to j1 before reducing [computing c*(p+j1-j2) mod p]
+ */
+ j1 = m_mod_p.reduce(sub_mul(m_key.get_p() + j1, j2, m_key.get_c()));
+ return mul_add(j1, m_key.get_q(), j2);
+ }
+
+ const RSA_PrivateKey& m_key;
+
+ // TODO these could all be computed once and stored in the key object
+ Modular_Reducer m_mod_p;
+ Modular_Reducer m_mod_q;
+ std::shared_ptr<const Montgomery_Params> m_monty_p;
+ std::shared_ptr<const Montgomery_Params> m_monty_q;
+
+ Fixed_Exponent_Power_Mod m_powermod_e_n;
+ Blinder m_blinder;
+ const size_t m_blinding_bits;
+ const size_t m_mod_bytes;
+ const size_t m_mod_bits;
+ const size_t m_max_d1_bits;
+ const size_t m_max_d2_bits;
+ };
+
+class RSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA,
+ private RSA_Private_Operation
+ {
+ public:
+
+ size_t max_input_bits() const override { return get_max_input_bits(); }
+
+ RSA_Signature_Operation(const RSA_PrivateKey& rsa, const std::string& emsa, RandomNumberGenerator& rng) :
+ PK_Ops::Signature_with_EMSA(emsa),
+ RSA_Private_Operation(rsa, rng)
+ {
+ }
+
+ secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator&) override
+ {
+ const BigInt m(msg, msg_len);
+ const BigInt x = blinded_private_op(m);
+ const BigInt c = m_powermod_e_n(x);
+ BOTAN_ASSERT(m == c, "RSA sign consistency check");
+ return BigInt::encode_1363(x, m_mod_bytes);
+ }
+ };
+
+class RSA_Decryption_Operation final : public PK_Ops::Decryption_with_EME,
+ private RSA_Private_Operation
+ {
+ public:
+
+ RSA_Decryption_Operation(const RSA_PrivateKey& rsa, const std::string& eme, RandomNumberGenerator& rng) :
+ PK_Ops::Decryption_with_EME(eme),
+ RSA_Private_Operation(rsa, rng)
+ {
+ }
+
+ secure_vector<uint8_t> raw_decrypt(const uint8_t msg[], size_t msg_len) override
+ {
+ const BigInt m(msg, msg_len);
+ const BigInt x = blinded_private_op(m);
+ const BigInt c = m_powermod_e_n(x);
+ BOTAN_ASSERT(m == c, "RSA decrypt consistency check");
+ return BigInt::encode_1363(x, m_mod_bytes);
+ }
+ };
+
+class RSA_KEM_Decryption_Operation final : public PK_Ops::KEM_Decryption_with_KDF,
+ private RSA_Private_Operation
+ {
+ public:
+
+ RSA_KEM_Decryption_Operation(const RSA_PrivateKey& key,
+ const std::string& kdf,
+ RandomNumberGenerator& rng) :
+ PK_Ops::KEM_Decryption_with_KDF(kdf),
+ RSA_Private_Operation(key, rng)
+ {}
+
+ secure_vector<uint8_t>
+ raw_kem_decrypt(const uint8_t encap_key[], size_t len) override
+ {
+ const BigInt m(encap_key, len);
+ const BigInt x = blinded_private_op(m);
+ const BigInt c = m_powermod_e_n(x);
+ BOTAN_ASSERT(m == c, "RSA KEM consistency check");
+ return BigInt::encode_1363(x, m_mod_bytes);
+ }
+ };
+
+/**
+* RSA public (encrypt/verify) operation
+*/
+class RSA_Public_Operation
+ {
+ public:
+ explicit RSA_Public_Operation(const RSA_PublicKey& rsa) :
+ m_n(rsa.get_n()),
+ m_e(rsa.get_e()),
+ m_monty_n(std::make_shared<Montgomery_Params>(m_n))
+ {}
+
+ size_t get_max_input_bits() const { return (m_n.bits() - 1); }
+
+ protected:
+ BigInt public_op(const BigInt& m) const
+ {
+ if(m >= m_n)
+ throw Invalid_Argument("RSA public op - input is too large");
+
+ const size_t powm_window = 1;
+
+ auto powm_m_n = monty_precompute(m_monty_n, m, powm_window, false);
+ return monty_execute_vartime(*powm_m_n, m_e);
+ }
+
+ const BigInt& get_n() const { return m_n; }
+
+ const BigInt& m_n;
+ const BigInt& m_e;
+ std::shared_ptr<Montgomery_Params> m_monty_n;
+ };
+
+class RSA_Encryption_Operation final : public PK_Ops::Encryption_with_EME,
+ private RSA_Public_Operation
+ {
+ public:
+
+ RSA_Encryption_Operation(const RSA_PublicKey& rsa, const std::string& eme) :
+ PK_Ops::Encryption_with_EME(eme),
+ RSA_Public_Operation(rsa)
+ {
+ }
+
+ size_t max_raw_input_bits() const override { return get_max_input_bits(); }
+
+ secure_vector<uint8_t> raw_encrypt(const uint8_t msg[], size_t msg_len,
+ RandomNumberGenerator&) override
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_1363(public_op(m), m_n.bytes());
+ }
+ };
+
+class RSA_Verify_Operation final : public PK_Ops::Verification_with_EMSA,
+ private RSA_Public_Operation
+ {
+ public:
+
+ size_t max_input_bits() const override { return get_max_input_bits(); }
+
+ RSA_Verify_Operation(const RSA_PublicKey& rsa, const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
+ RSA_Public_Operation(rsa)
+ {
+ }
+
+ bool with_recovery() const override { return true; }
+
+ secure_vector<uint8_t> verify_mr(const uint8_t msg[], size_t msg_len) override
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_locked(public_op(m));
+ }
+ };
+
+class RSA_KEM_Encryption_Operation final : public PK_Ops::KEM_Encryption_with_KDF,
+ private RSA_Public_Operation
+ {
+ public:
+
+ RSA_KEM_Encryption_Operation(const RSA_PublicKey& key,
+ const std::string& kdf) :
+ PK_Ops::KEM_Encryption_with_KDF(kdf),
+ RSA_Public_Operation(key) {}
+
+ private:
+ void raw_kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
+ secure_vector<uint8_t>& raw_shared_key,
+ Botan::RandomNumberGenerator& rng) override
+ {
+ const BigInt r = BigInt::random_integer(rng, 1, get_n());
+ const BigInt c = public_op(r);
+
+ out_encapsulated_key = BigInt::encode_locked(c);
+ raw_shared_key = BigInt::encode_locked(r);
+ }
+ };
+
+}
+
+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 Lookup_Error("OpenSSL RSA provider rejected key:" + std::string(e.what()));
+ }
+ }
+#endif
+
+ 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);
+ }
+
+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 Lookup_Error("OpenSSL RSA provider rejected key:" + std::string(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/libs/3rdparty/botan/src/lib/pubkey/rsa/rsa.h b/src/libs/3rdparty/botan/src/lib/pubkey/rsa/rsa.h
new file mode 100644
index 0000000000..ad4fceab99
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/rsa/rsa.h
@@ -0,0 +1,164 @@
+/*
+* RSA
+* (C) 1999-2008,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_RSA_H_
+#define BOTAN_RSA_H_
+
+#include <botan/pk_keys.h>
+#include <botan/bigint.h>
+
+namespace Botan {
+
+/**
+* RSA Public Key
+*/
+class BOTAN_PUBLIC_API(2,0) RSA_PublicKey : public virtual Public_Key
+ {
+ public:
+ /**
+ * Load a public key.
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits DER encoded public key bits
+ */
+ RSA_PublicKey(const AlgorithmIdentifier& alg_id,
+ const std::vector<uint8_t>& key_bits);
+
+ /**
+ * Create a public key.
+ * @arg n the modulus
+ * @arg e the exponent
+ */
+ RSA_PublicKey(const BigInt& n, const BigInt& e) :
+ m_n(n), m_e(e) {}
+
+ std::string algo_name() const override { return "RSA"; }
+
+ bool check_key(RandomNumberGenerator& rng, bool) const override;
+
+ AlgorithmIdentifier algorithm_identifier() const override;
+
+ std::vector<uint8_t> public_key_bits() const override;
+
+ /**
+ * @return public modulus
+ */
+ const BigInt& get_n() const { return m_n; }
+
+ /**
+ * @return public exponent
+ */
+ const BigInt& get_e() const { return m_e; }
+
+ size_t key_length() const override;
+ 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() = default;
+
+ BigInt m_n, m_e;
+ };
+
+/**
+* RSA Private Key
+*/
+class BOTAN_PUBLIC_API(2,0) RSA_PrivateKey final : public Private_Key, public RSA_PublicKey
+ {
+ public:
+ /**
+ * Load a private key.
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits PKCS#1 RSAPrivateKey bits
+ */
+ RSA_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& key_bits);
+
+ /**
+ * Construct a private key from the specified parameters.
+ * @param p the first prime
+ * @param q the second prime
+ * @param e the exponent
+ * @param d if specified, this has to be d with
+ * exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish to
+ * the constructor to calculate it.
+ * @param n if specified, this must be n = p * q. Leave it as 0
+ * if you wish to the constructor to calculate it.
+ */
+ RSA_PrivateKey(const BigInt& p, const BigInt& q,
+ const BigInt& e, const BigInt& d = 0,
+ const BigInt& n = 0);
+
+ /**
+ * Create a new private key with the specified bit length
+ * @param rng the random number generator to use
+ * @param bits the desired bit length of the private key
+ * @param exp the public exponent to be used
+ */
+ RSA_PrivateKey(RandomNumberGenerator& rng,
+ size_t bits, size_t exp = 65537);
+
+ bool check_key(RandomNumberGenerator& rng, bool) const override;
+
+ /**
+ * Get the first prime p.
+ * @return prime p
+ */
+ const BigInt& get_p() const { return m_p; }
+
+ /**
+ * Get the second prime q.
+ * @return prime q
+ */
+ const BigInt& get_q() const { return m_q; }
+
+ /**
+ * Get d with exp * d = 1 mod (p - 1, q - 1).
+ * @return d
+ */
+ const BigInt& get_d() const { return m_d; }
+
+ const BigInt& get_c() const { return m_c; }
+ const BigInt& get_d1() const { return m_d1; }
+ const BigInt& get_d2() const { return m_d2; }
+
+ secure_vector<uint8_t> private_key_bits() 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;
+ };
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/workfactor.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/workfactor.cpp
new file mode 100644
index 0000000000..71604c06bb
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/workfactor.cpp
@@ -0,0 +1,64 @@
+/*
+* Public Key Work Factor Functions
+* (C) 1999-2007,2012 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/workfactor.h>
+#include <algorithm>
+#include <cmath>
+
+namespace Botan {
+
+size_t ecp_work_factor(size_t bits)
+ {
+ return bits / 2;
+ }
+
+namespace {
+
+size_t nfs_workfactor(size_t bits, double k)
+ {
+ // approximates natural logarithm of integer of given bitsize
+ const double log2_e = std::log2(std::exp(1));
+ const double log_p = bits / log2_e;
+
+ const double log_log_p = std::log(log_p);
+
+ // RFC 3766: k * e^((1.92 + o(1)) * cubrt(ln(n) * (ln(ln(n)))^2))
+ const double est = 1.92 * std::pow(log_p * log_log_p * log_log_p, 1.0/3.0);
+
+ // return log2 of the workfactor
+ return static_cast<size_t>(std::log2(k) + log2_e * est);
+ }
+
+}
+
+size_t if_work_factor(size_t bits)
+ {
+ // RFC 3766 estimates k at .02 and o(1) to be effectively zero for sizes of interest
+
+ return nfs_workfactor(bits, .02);
+ }
+
+size_t dl_work_factor(size_t bits)
+ {
+ // Lacking better estimates...
+ return if_work_factor(bits);
+ }
+
+size_t dl_exponent_size(size_t bits)
+ {
+ /*
+ This uses a slightly tweaked version of the standard work factor
+ function above. It assumes k is 1 (thus overestimating the strength
+ of the prime group by 5-6 bits), and always returns at least 128 bits
+ (this only matters for very small primes).
+ */
+ const size_t MIN_WORKFACTOR = 64;
+
+ return 2 * std::max<size_t>(MIN_WORKFACTOR, nfs_workfactor(bits, 1));
+ }
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/workfactor.h b/src/libs/3rdparty/botan/src/lib/pubkey/workfactor.h
new file mode 100644
index 0000000000..0eea246d7e
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/workfactor.h
@@ -0,0 +1,50 @@
+/*
+* Public Key Work Factor Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_WORKFACTOR_H_
+#define BOTAN_WORKFACTOR_H_
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/**
+* Estimate work factor for discrete logarithm
+* @param prime_group_size size of the group in bits
+* @return estimated security level for this group
+*/
+BOTAN_PUBLIC_API(2,0) size_t dl_work_factor(size_t prime_group_size);
+
+/**
+* Return the appropriate exponent size to use for a particular prime
+* group. This is twice the size of the estimated cost of breaking the
+* key using an index calculus attack; the assumption is that if an
+* arbitrary discrete log on a group of size bits would take about 2^n
+* effort, and thus using an exponent of size 2^(2*n) implies that all
+* available attacks are about as easy (as e.g Pollard's kangaroo
+* algorithm can compute the DL in sqrt(x) operations) while minimizing
+* the exponent size for performance reasons.
+*/
+BOTAN_PUBLIC_API(2,0) size_t dl_exponent_size(size_t prime_group_size);
+
+/**
+* Estimate work factor for integer factorization
+* @param n_bits size of modulus in bits
+* @return estimated security level for this modulus
+*/
+BOTAN_PUBLIC_API(2,0) size_t if_work_factor(size_t n_bits);
+
+/**
+* Estimate work factor for EC discrete logarithm
+* @param prime_group_size size of the group in bits
+* @return estimated security level for this group
+*/
+BOTAN_PUBLIC_API(2,0) size_t ecp_work_factor(size_t prime_group_size);
+
+}
+
+#endif
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/x509_key.cpp b/src/libs/3rdparty/botan/src/lib/pubkey/x509_key.cpp
new file mode 100644
index 0000000000..6e49d953a4
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/x509_key.cpp
@@ -0,0 +1,106 @@
+/*
+* X.509 Public Key
+* (C) 1999-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/x509_key.h>
+#include <botan/data_src.h>
+#include <botan/ber_dec.h>
+#include <botan/pem.h>
+#include <botan/alg_id.h>
+#include <botan/pk_algs.h>
+
+namespace Botan {
+
+namespace X509 {
+
+std::vector<uint8_t> BER_encode(const Public_Key& key)
+ {
+ // keeping it around for compat
+ return key.subject_public_key();
+ }
+
+/*
+* PEM encode a X.509 public key
+*/
+std::string PEM_encode(const Public_Key& key)
+ {
+ return PEM_Code::encode(key.subject_public_key(),
+ "PUBLIC KEY");
+ }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(DataSource& source)
+ {
+ try {
+ AlgorithmIdentifier alg_id;
+ std::vector<uint8_t> key_bits;
+
+ if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+ {
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .decode(alg_id)
+ .decode(key_bits, BIT_STRING)
+ .end_cons();
+ }
+ else
+ {
+ DataSource_Memory ber(
+ PEM_Code::decode_check_label(source, "PUBLIC KEY")
+ );
+
+ BER_Decoder(ber)
+ .start_cons(SEQUENCE)
+ .decode(alg_id)
+ .decode(key_bits, BIT_STRING)
+ .end_cons();
+ }
+
+ if(key_bits.empty())
+ throw Decoding_Error("X.509 public key decoding failed");
+
+ return load_public_key(alg_id, key_bits).release();
+ }
+ catch(Decoding_Error& e)
+ {
+ throw Decoding_Error("X.509 public key decoding failed: " + std::string(e.what()));
+ }
+ }
+
+#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(const std::string& fsname)
+ {
+ DataSource_Stream source(fsname, true);
+ return X509::load_key(source);
+ }
+#endif
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(const std::vector<uint8_t>& mem)
+ {
+ DataSource_Memory source(mem);
+ return X509::load_key(source);
+ }
+
+/*
+* Make a copy of this public key
+*/
+Public_Key* copy_key(const Public_Key& key)
+ {
+ DataSource_Memory source(PEM_encode(key));
+ return X509::load_key(source);
+ }
+
+}
+
+}
diff --git a/src/libs/3rdparty/botan/src/lib/pubkey/x509_key.h b/src/libs/3rdparty/botan/src/lib/pubkey/x509_key.h
new file mode 100644
index 0000000000..58d537bbe7
--- /dev/null
+++ b/src/libs/3rdparty/botan/src/lib/pubkey/x509_key.h
@@ -0,0 +1,80 @@
+/*
+* X.509 Public Key
+* (C) 1999-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_X509_PUBLIC_KEY_H_
+#define BOTAN_X509_PUBLIC_KEY_H_
+
+#include <botan/pk_keys.h>
+#include <botan/types.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+class RandomNumberGenerator;
+class DataSource;
+
+/**
+* The two types of X509 encoding supported by Botan.
+* This enum is not used anymore, and will be removed in a future major release.
+*/
+enum X509_Encoding { RAW_BER, PEM };
+
+/**
+* This namespace contains functions for handling X.509 public keys
+*/
+namespace X509 {
+
+/**
+* BER encode a key
+* @param key the public key to encode
+* @return BER encoding of this key
+*/
+BOTAN_PUBLIC_API(2,0) std::vector<uint8_t> BER_encode(const Public_Key& key);
+
+/**
+* PEM encode a public key into a string.
+* @param key the key to encode
+* @return PEM encoded key
+*/
+BOTAN_PUBLIC_API(2,0) std::string PEM_encode(const Public_Key& key);
+
+/**
+* Create a public key from a data source.
+* @param source the source providing the DER or PEM encoded key
+* @return new public key object
+*/
+BOTAN_PUBLIC_API(2,0) Public_Key* load_key(DataSource& source);
+
+#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
+/**
+* Create a public key from a file
+* @param filename pathname to the file to load
+* @return new public key object
+*/
+BOTAN_PUBLIC_API(2,0) Public_Key* load_key(const std::string& filename);
+#endif
+
+/**
+* Create a public key from a memory region.
+* @param enc the memory region containing the DER or PEM encoded key
+* @return new public key object
+*/
+BOTAN_PUBLIC_API(2,0) Public_Key* load_key(const std::vector<uint8_t>& enc);
+
+/**
+* Copy a key.
+* @param key the public key to copy
+* @return new public key object
+*/
+BOTAN_PUBLIC_API(2,0) Public_Key* copy_key(const Public_Key& key);
+
+}
+
+}
+
+#endif