aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/pubkey
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/pubkey')
-rw-r--r--src/lib/pubkey/blinding.cpp49
-rw-r--r--src/lib/pubkey/blinding.h46
-rw-r--r--src/lib/pubkey/dh/dh.cpp98
-rw-r--r--src/lib/pubkey/dh/dh.h94
-rw-r--r--src/lib/pubkey/dh/info.txt16
-rw-r--r--src/lib/pubkey/dl_algo/dl_algo.cpp91
-rw-r--r--src/lib/pubkey/dl_algo/dl_algo.h116
-rw-r--r--src/lib/pubkey/dl_algo/info.txt8
-rw-r--r--src/lib/pubkey/dl_group/dl_group.cpp337
-rw-r--r--src/lib/pubkey/dl_group/dl_group.h170
-rw-r--r--src/lib/pubkey/dl_group/info.txt10
-rw-r--r--src/lib/pubkey/dl_group/named.cpp360
-rw-r--r--src/lib/pubkey/dlies/dlies.cpp146
-rw-r--r--src/lib/pubkey/dlies/dlies.h71
-rw-r--r--src/lib/pubkey/dlies/info.txt7
-rw-r--r--src/lib/pubkey/dsa/dsa.cpp143
-rw-r--r--src/lib/pubkey/dsa/dsa.h107
-rw-r--r--src/lib/pubkey/dsa/info.txt9
-rw-r--r--src/lib/pubkey/ec_group/ec_group.cpp134
-rw-r--r--src/lib/pubkey/ec_group/ec_group.h148
-rw-r--r--src/lib/pubkey/ec_group/info.txt10
-rw-r--r--src/lib/pubkey/ec_group/named.cpp307
-rw-r--r--src/lib/pubkey/ecc_key/ecc_key.cpp148
-rw-r--r--src/lib/pubkey/ecc_key/ecc_key.h121
-rw-r--r--src/lib/pubkey/ecc_key/info.txt10
-rw-r--r--src/lib/pubkey/ecdh/ecdh.cpp35
-rw-r--r--src/lib/pubkey/ecdh/ecdh.h107
-rw-r--r--src/lib/pubkey/ecdh/info.txt10
-rw-r--r--src/lib/pubkey/ecdsa/ecdsa.cpp97
-rw-r--r--src/lib/pubkey/ecdsa/ecdsa.h138
-rw-r--r--src/lib/pubkey/ecdsa/info.txt9
-rw-r--r--src/lib/pubkey/elgamal/elgamal.cpp135
-rw-r--r--src/lib/pubkey/elgamal/elgamal.h96
-rw-r--r--src/lib/pubkey/elgamal/info.txt9
-rw-r--r--src/lib/pubkey/gost_3410/gost_3410.cpp176
-rw-r--r--src/lib/pubkey/gost_3410/gost_3410.h139
-rw-r--r--src/lib/pubkey/gost_3410/info.txt13
-rw-r--r--src/lib/pubkey/if_algo/if_algo.cpp143
-rw-r--r--src/lib/pubkey/if_algo/if_algo.h108
-rw-r--r--src/lib/pubkey/if_algo/info.txt10
-rw-r--r--src/lib/pubkey/info.txt41
-rw-r--r--src/lib/pubkey/keypair/info.txt5
-rw-r--r--src/lib/pubkey/keypair/keypair.cpp81
-rw-r--r--src/lib/pubkey/keypair/keypair.h47
-rw-r--r--src/lib/pubkey/nr/info.txt9
-rw-r--r--src/lib/pubkey/nr/nr.cpp143
-rw-r--r--src/lib/pubkey/nr/nr.h104
-rw-r--r--src/lib/pubkey/pk_algs.cpp160
-rw-r--r--src/lib/pubkey/pk_algs.h24
-rw-r--r--src/lib/pubkey/pk_keys.cpp55
-rw-r--r--src/lib/pubkey/pk_keys.h149
-rw-r--r--src/lib/pubkey/pk_ops.h163
-rw-r--r--src/lib/pubkey/pkcs8.cpp284
-rw-r--r--src/lib/pubkey/pkcs8.h141
-rw-r--r--src/lib/pubkey/pubkey.cpp386
-rw-r--r--src/lib/pubkey/pubkey.h461
-rw-r--r--src/lib/pubkey/rsa/info.txt8
-rw-r--r--src/lib/pubkey/rsa/rsa.cpp121
-rw-r--r--src/lib/pubkey/rsa/rsa.h155
-rw-r--r--src/lib/pubkey/rw/info.txt8
-rw-r--r--src/lib/pubkey/rw/rw.cpp130
-rw-r--r--src/lib/pubkey/rw/rw.h107
-rw-r--r--src/lib/pubkey/workfactor.cpp50
-rw-r--r--src/lib/pubkey/workfactor.h24
-rw-r--r--src/lib/pubkey/x509_key.cpp111
-rw-r--r--src/lib/pubkey/x509_key.h74
66 files changed, 7022 insertions, 0 deletions
diff --git a/src/lib/pubkey/blinding.cpp b/src/lib/pubkey/blinding.cpp
new file mode 100644
index 000000000..c4c0e3b6e
--- /dev/null
+++ b/src/lib/pubkey/blinding.cpp
@@ -0,0 +1,49 @@
+/*
+* Blinding for public key operations
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/blinding.h>
+#include <botan/numthry.h>
+
+namespace Botan {
+
+/*
+* Blinder Constructor
+*/
+Blinder::Blinder(const BigInt& e, const BigInt& d, const BigInt& n)
+ {
+ if(e < 1 || d < 1 || n < 1)
+ throw Invalid_Argument("Blinder: Arguments too small");
+
+ reducer = Modular_Reducer(n);
+ this->e = e;
+ this->d = d;
+ }
+
+/*
+* Blind a number
+*/
+BigInt Blinder::blind(const BigInt& i) const
+ {
+ if(!reducer.initialized())
+ return i;
+
+ e = reducer.square(e);
+ d = reducer.square(d);
+ return reducer.multiply(i, e);
+ }
+
+/*
+* Unblind a number
+*/
+BigInt Blinder::unblind(const BigInt& i) const
+ {
+ if(!reducer.initialized())
+ return i;
+ return reducer.multiply(i, d);
+ }
+
+}
diff --git a/src/lib/pubkey/blinding.h b/src/lib/pubkey/blinding.h
new file mode 100644
index 000000000..712030e4d
--- /dev/null
+++ b/src/lib/pubkey/blinding.h
@@ -0,0 +1,46 @@
+/*
+* Blinding for public key operations
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BLINDER_H__
+#define BOTAN_BLINDER_H__
+
+#include <botan/bigint.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+/**
+* Blinding Function Object
+*/
+class BOTAN_DLL Blinder
+ {
+ public:
+ BigInt blind(const BigInt& x) const;
+ BigInt unblind(const BigInt& x) const;
+
+ bool initialized() const { return reducer.initialized(); }
+
+ Blinder() {}
+
+ /**
+ * Construct a blinder
+ * @param mask the forward (blinding) mask
+ * @param inverse_mask the inverse of mask (depends on algo)
+ * @param modulus of the group operations are performed in
+ */
+ Blinder(const BigInt& mask,
+ const BigInt& inverse_mask,
+ const BigInt& modulus);
+
+ private:
+ Modular_Reducer reducer;
+ mutable BigInt e, d;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/dh/dh.cpp b/src/lib/pubkey/dh/dh.cpp
new file mode 100644
index 000000000..55d53518a
--- /dev/null
+++ b/src/lib/pubkey/dh/dh.cpp
@@ -0,0 +1,98 @@
+/*
+* Diffie-Hellman
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dh.h>
+#include <botan/numthry.h>
+#include <botan/workfactor.h>
+
+namespace Botan {
+
+/*
+* DH_PublicKey Constructor
+*/
+DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ }
+
+/*
+* Return the public value for key agreement
+*/
+std::vector<byte> DH_PublicKey::public_value() const
+ {
+ return unlock(BigInt::encode_1363(y, group_p().bytes()));
+ }
+
+/*
+* Create a DH private key
+*/
+DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ group = grp;
+ x = x_arg;
+
+ if(x == 0)
+ {
+ const BigInt& p = group_p();
+ x.randomize(rng, 2 * dl_work_factor(p.bits()));
+ }
+
+ if(y == 0)
+ y = power_mod(group_g(), x, group_p());
+
+ if(x == 0)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*
+* Load a DH private key
+*/
+DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng) :
+ DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
+ {
+ if(y == 0)
+ y = power_mod(group_g(), x, group_p());
+
+ load_check(rng);
+ }
+
+/*
+* Return the public value for key agreement
+*/
+std::vector<byte> DH_PrivateKey::public_value() const
+ {
+ return DH_PublicKey::public_value();
+ }
+
+DH_KA_Operation::DH_KA_Operation(const DH_PrivateKey& dh,
+ RandomNumberGenerator& rng) :
+ p(dh.group_p()), powermod_x_p(dh.get_x(), p)
+ {
+ BigInt k(rng, p.bits() - 1);
+ blinder = Blinder(k, powermod_x_p(inverse_mod(k, p)), p);
+ }
+
+secure_vector<byte> DH_KA_Operation::agree(const byte w[], size_t w_len)
+ {
+ BigInt input = BigInt::decode(w, w_len);
+
+ if(input <= 1 || input >= p - 1)
+ throw Invalid_Argument("DH agreement - invalid key provided");
+
+ BigInt r = blinder.unblind(powermod_x_p(blinder.blind(input)));
+
+ return BigInt::encode_1363(r, p.bytes());
+ }
+
+}
diff --git a/src/lib/pubkey/dh/dh.h b/src/lib/pubkey/dh/dh.h
new file mode 100644
index 000000000..c670399d8
--- /dev/null
+++ b/src/lib/pubkey/dh/dh.h
@@ -0,0 +1,94 @@
+/*
+* Diffie-Hellman
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DIFFIE_HELLMAN_H__
+#define BOTAN_DIFFIE_HELLMAN_H__
+
+#include <botan/dl_algo.h>
+#include <botan/pow_mod.h>
+#include <botan/blinding.h>
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+/**
+* This class represents Diffie-Hellman public keys.
+*/
+class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "DH"; }
+
+ std::vector<byte> public_value() const;
+ size_t max_input_bits() const { return group_p().bits(); }
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
+
+ DH_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& 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() {}
+ };
+
+/**
+* This class represents Diffie-Hellman private keys.
+*/
+class BOTAN_DLL DH_PrivateKey : public DH_PublicKey,
+ public PK_Key_Agreement_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ std::vector<byte> public_value() const;
+
+ /**
+ * Load a DH private key
+ * @param alg_id the algorithm id
+ * @param key_bits the subject public key
+ * @param rng a random number generator
+ */
+ DH_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Construct a private key with predetermined value.
+ * @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);
+ };
+
+/**
+* DH operation
+*/
+class BOTAN_DLL DH_KA_Operation : public PK_Ops::Key_Agreement
+ {
+ public:
+ DH_KA_Operation(const DH_PrivateKey& key,
+ RandomNumberGenerator& rng);
+
+ secure_vector<byte> agree(const byte w[], size_t w_len);
+ private:
+ const BigInt& p;
+
+ Fixed_Exponent_Power_Mod powermod_x_p;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/dh/info.txt b/src/lib/pubkey/dh/info.txt
new file mode 100644
index 000000000..bb2707951
--- /dev/null
+++ b/src/lib/pubkey/dh/info.txt
@@ -0,0 +1,16 @@
+define DIFFIE_HELLMAN 20131128
+
+<header:public>
+dh.h
+</header:public>
+
+<source>
+dh.cpp
+</source>
+
+<requires>
+dl_algo
+dl_group
+libstate
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/dl_algo/dl_algo.cpp b/src/lib/pubkey/dl_algo/dl_algo.cpp
new file mode 100644
index 000000000..92c78ac79
--- /dev/null
+++ b/src/lib/pubkey/dl_algo/dl_algo.cpp
@@ -0,0 +1,91 @@
+/*
+* DL Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dl_algo.h>
+#include <botan/numthry.h>
+#include <botan/workfactor.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+size_t DL_Scheme_PublicKey::estimated_strength() const
+ {
+ return dl_work_factor(group.get_p().bits());
+ }
+
+AlgorithmIdentifier DL_Scheme_PublicKey::algorithm_identifier() const
+ {
+ return AlgorithmIdentifier(get_oid(),
+ group.DER_encode(group_format()));
+ }
+
+std::vector<byte> DL_Scheme_PublicKey::x509_subject_public_key() const
+ {
+ return DER_Encoder().encode(y).get_contents_unlocked();
+ }
+
+DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ DL_Group::Format format)
+ {
+ group.BER_decode(alg_id.parameters, format);
+
+ BER_Decoder(key_bits).decode(y);
+ }
+
+secure_vector<byte> DL_Scheme_PrivateKey::pkcs8_private_key() const
+ {
+ return DER_Encoder().encode(x).get_contents();
+ }
+
+DL_Scheme_PrivateKey::DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ DL_Group::Format format)
+ {
+ group.BER_decode(alg_id.parameters, format);
+
+ BER_Decoder(key_bits).decode(x);
+ }
+
+/*
+* Check Public DL Parameters
+*/
+bool DL_Scheme_PublicKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ if(y < 2 || y >= group_p())
+ return false;
+ if(!group.verify_group(rng, strong))
+ return false;
+ return true;
+ }
+
+/*
+* Check DL Scheme Private Parameters
+*/
+bool DL_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ const BigInt& p = group_p();
+ const BigInt& g = group_g();
+
+ if(y < 2 || y >= p || x < 2 || x >= p)
+ return false;
+ if(!group.verify_group(rng, strong))
+ return false;
+
+ if(!strong)
+ return true;
+
+ if(y != power_mod(g, x, p))
+ return false;
+
+ return true;
+ }
+
+}
diff --git a/src/lib/pubkey/dl_algo/dl_algo.h b/src/lib/pubkey/dl_algo/dl_algo.h
new file mode 100644
index 000000000..abd2acba4
--- /dev/null
+++ b/src/lib/pubkey/dl_algo/dl_algo.h
@@ -0,0 +1,116 @@
+/*
+* DL Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DL_ALGO_H__
+#define BOTAN_DL_ALGO_H__
+
+#include <botan/dl_group.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/**
+* This class represents discrete logarithm (DL) public keys.
+*/
+class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ AlgorithmIdentifier algorithm_identifier() const;
+
+ std::vector<byte> x509_subject_public_key() const;
+
+ /**
+ * Get the DL domain parameters of this key.
+ * @return DL domain parameters of this key
+ */
+ const DL_Group& get_domain() const { return group; }
+
+ /**
+ * Get the public value y with y = g^x mod p where x is the secret key.
+ */
+ const BigInt& get_y() const { return y; }
+
+ /**
+ * Get the prime p of the underlying DL group.
+ * @return prime p
+ */
+ const BigInt& group_p() const { return group.get_p(); }
+
+ /**
+ * Get the prime q of the underlying DL group.
+ * @return prime q
+ */
+ const BigInt& group_q() const { return group.get_q(); }
+
+ /**
+ * Get the generator g of the underlying DL group.
+ * @return generator g
+ */
+ const BigInt& group_g() const { return group.get_g(); }
+
+ /**
+ * Get the underlying groups encoding format.
+ * @return encoding format
+ */
+ virtual DL_Group::Format group_format() const = 0;
+
+ size_t estimated_strength() const override;
+
+ DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ DL_Group::Format group_format);
+
+ protected:
+ DL_Scheme_PublicKey() {}
+
+ /**
+ * The DL public key
+ */
+ BigInt y;
+
+ /**
+ * The DL group
+ */
+ DL_Group group;
+ };
+
+/**
+* This class represents discrete logarithm (DL) private keys.
+*/
+class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get the secret key x.
+ * @return secret key
+ */
+ const BigInt& get_x() const { return x; }
+
+ secure_vector<byte> pkcs8_private_key() const;
+
+ DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ DL_Group::Format group_format);
+
+ protected:
+ DL_Scheme_PrivateKey() {}
+
+ /**
+ * The DL private key
+ */
+ BigInt x;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/dl_algo/info.txt b/src/lib/pubkey/dl_algo/info.txt
new file mode 100644
index 000000000..6f3b3195d
--- /dev/null
+++ b/src/lib/pubkey/dl_algo/info.txt
@@ -0,0 +1,8 @@
+define DL_PUBLIC_KEY_FAMILY 20131128
+
+<requires>
+asn1
+dl_group
+numbertheory
+rng
+</requires>
diff --git a/src/lib/pubkey/dl_group/dl_group.cpp b/src/lib/pubkey/dl_group/dl_group.cpp
new file mode 100644
index 000000000..6fd1beeaa
--- /dev/null
+++ b/src/lib/pubkey/dl_group/dl_group.cpp
@@ -0,0 +1,337 @@
+/*
+* Discrete Logarithm Parameters
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dl_group.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+#include <botan/numthry.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pipe.h>
+#include <botan/pem.h>
+#include <botan/workfactor.h>
+
+namespace Botan {
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group()
+ {
+ initialized = false;
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const std::string& name)
+ {
+ const char* pem = PEM_for_named_group(name);
+
+ if(!pem)
+ throw Invalid_Argument("DL_Group: Unknown group " + name);
+
+ PEM_decode(pem);
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(RandomNumberGenerator& rng,
+ PrimeType type, size_t pbits, size_t qbits)
+ {
+ if(pbits < 512)
+ throw Invalid_Argument("DL_Group: prime size " + std::to_string(pbits) +
+ " is too small");
+
+ if(type == Strong)
+ {
+ p = random_safe_prime(rng, pbits);
+ q = (p - 1) / 2;
+ g = 2;
+ }
+ else if(type == Prime_Subgroup)
+ {
+ if(!qbits)
+ qbits = 2 * dl_work_factor(pbits);
+
+ q = random_prime(rng, qbits);
+ BigInt X;
+ while(p.bits() != pbits || !check_prime(p, rng))
+ {
+ X.randomize(rng, pbits);
+ p = X - (X % (2*q) - 1);
+ }
+
+ g = make_dsa_generator(p, q);
+ }
+ else if(type == DSA_Kosherizer)
+ {
+ qbits = qbits ? qbits : ((pbits <= 1024) ? 160 : 256);
+
+ generate_dsa_primes(rng,
+ global_state().algorithm_factory(),
+ p, q,
+ pbits, qbits);
+
+ g = make_dsa_generator(p, q);
+ }
+
+ initialized = true;
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(RandomNumberGenerator& rng,
+ const std::vector<byte>& seed,
+ size_t pbits, size_t qbits)
+ {
+ if(!generate_dsa_primes(rng,
+ global_state().algorithm_factory(),
+ p, q, pbits, qbits, seed))
+ throw Invalid_Argument("DL_Group: The seed given does not "
+ "generate a DSA group");
+
+ g = make_dsa_generator(p, q);
+
+ initialized = true;
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const BigInt& p1, const BigInt& g1)
+ {
+ initialize(p1, 0, g1);
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const BigInt& p1, const BigInt& q1, const BigInt& g1)
+ {
+ initialize(p1, q1, g1);
+ }
+
+/*
+* DL_Group Initializer
+*/
+void DL_Group::initialize(const BigInt& p1, const BigInt& q1, const BigInt& g1)
+ {
+ if(p1 < 3)
+ throw Invalid_Argument("DL_Group: Prime invalid");
+ if(g1 < 2 || g1 >= p1)
+ throw Invalid_Argument("DL_Group: Generator invalid");
+ if(q1 < 0 || q1 >= p1)
+ throw Invalid_Argument("DL_Group: Subgroup invalid");
+
+ p = p1;
+ g = g1;
+ q = q1;
+
+ initialized = true;
+ }
+
+/*
+* Verify that the group has been set
+*/
+void DL_Group::init_check() const
+ {
+ if(!initialized)
+ throw Invalid_State("DLP group cannot be used uninitialized");
+ }
+
+/*
+* Verify the parameters
+*/
+bool DL_Group::verify_group(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ init_check();
+
+ if(g < 2 || p < 3 || q < 0)
+ return false;
+ if((q != 0) && ((p - 1) % q != 0))
+ return false;
+
+ if(!strong)
+ return true;
+
+ if(!check_prime(p, rng))
+ return false;
+ if((q > 0) && !check_prime(q, rng))
+ return false;
+ return true;
+ }
+
+/*
+* Return the prime
+*/
+const BigInt& DL_Group::get_p() const
+ {
+ init_check();
+ return p;
+ }
+
+/*
+* Return the generator
+*/
+const BigInt& DL_Group::get_g() const
+ {
+ init_check();
+ return g;
+ }
+
+/*
+* Return the subgroup
+*/
+const BigInt& DL_Group::get_q() const
+ {
+ init_check();
+ if(q == 0)
+ throw Invalid_State("DLP group has no q prime specified");
+ return q;
+ }
+
+/*
+* DER encode the parameters
+*/
+std::vector<byte> DL_Group::DER_encode(Format format) const
+ {
+ init_check();
+
+ if((q == 0) && (format != PKCS_3))
+ throw Encoding_Error("The ANSI DL parameter formats require a subgroup");
+
+ if(format == ANSI_X9_57)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(p)
+ .encode(q)
+ .encode(g)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+ else if(format == ANSI_X9_42)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(p)
+ .encode(g)
+ .encode(q)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+ else if(format == PKCS_3)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(p)
+ .encode(g)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
+ }
+
+/*
+* PEM encode the parameters
+*/
+std::string DL_Group::PEM_encode(Format format) const
+ {
+ const std::vector<byte> 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, "X942 DH PARAMETERS");
+ else
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
+ }
+
+/*
+* Decode BER encoded parameters
+*/
+void DL_Group::BER_decode(const std::vector<byte>& data,
+ Format format)
+ {
+ BigInt new_p, new_q, new_g;
+
+ BER_Decoder decoder(data);
+ BER_Decoder ber = decoder.start_cons(SEQUENCE);
+
+ if(format == ANSI_X9_57)
+ {
+ ber.decode(new_p)
+ .decode(new_q)
+ .decode(new_g)
+ .verify_end();
+ }
+ else if(format == ANSI_X9_42)
+ {
+ ber.decode(new_p)
+ .decode(new_g)
+ .decode(new_q)
+ .discard_remaining();
+ }
+ else if(format == PKCS_3)
+ {
+ ber.decode(new_p)
+ .decode(new_g)
+ .discard_remaining();
+ }
+ else
+ throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
+
+ initialize(new_p, new_q, new_g);
+ }
+
+/*
+* Decode PEM encoded parameters
+*/
+void DL_Group::PEM_decode(const std::string& pem)
+ {
+ std::string label;
+
+ auto ber = unlock(PEM_Code::decode(pem, label));
+
+ if(label == "DH PARAMETERS")
+ BER_decode(ber, PKCS_3);
+ else if(label == "DSA PARAMETERS")
+ BER_decode(ber, ANSI_X9_57);
+ else if(label == "X942 DH PARAMETERS")
+ BER_decode(ber, ANSI_X9_42);
+ else
+ throw Decoding_Error("DL_Group: Invalid PEM label " + label);
+ }
+
+/*
+* Create generator of the q-sized subgroup (DSA style generator)
+*/
+BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q)
+ {
+ const BigInt e = (p - 1) / q;
+
+ if(e == 0 || (p - 1) % q > 0)
+ throw std::invalid_argument("make_dsa_generator q does not divide p-1");
+
+ for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i)
+ {
+ BigInt g = power_mod(PRIMES[i], e, p);
+ if(g > 1)
+ return g;
+ }
+
+ throw Internal_Error("DL_Group: Couldn't create a suitable generator");
+ }
+
+}
diff --git a/src/lib/pubkey/dl_group/dl_group.h b/src/lib/pubkey/dl_group/dl_group.h
new file mode 100644
index 000000000..e219bdcbd
--- /dev/null
+++ b/src/lib/pubkey/dl_group/dl_group.h
@@ -0,0 +1,170 @@
+/*
+* Discrete Logarithm Group
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DL_PARAM_H__
+#define BOTAN_DL_PARAM_H__
+
+#include <botan/bigint.h>
+#include <botan/data_src.h>
+
+namespace Botan {
+
+/**
+* This class represents discrete logarithm groups. It holds a prime p,
+* a prime q = (p-1)/2 and g = x^((p-1)/q) mod p.
+*/
+class BOTAN_DLL DL_Group
+ {
+ public:
+
+ /**
+ * Get the prime p.
+ * @return prime p
+ */
+ const BigInt& get_p() const;
+
+ /**
+ * Get the prime q.
+ * @return prime q
+ */
+ const BigInt& get_q() const;
+
+ /**
+ * Get the base g.
+ * @return base g
+ */
+ const BigInt& get_g() const;
+
+ /**
+ * 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,
+ X942_DH_PARAMETERS = ANSI_X9_42,
+ PKCS3_DH_PARAMETERS = PKCS_3
+ };
+
+ /**
+ * Determine the prime creation for DL groups.
+ */
+ enum PrimeType { Strong, Prime_Subgroup, DSA_Kosherizer };
+
+ /**
+ * 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) 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<byte> DER_encode(Format format) 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<byte>& 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);
+
+ /**
+ * 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();
+
+ /**
+ * 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/768" as name.
+ */
+ 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<byte>& seed,
+ size_t pbits = 1024, size_t qbits = 0);
+
+ /**
+ * Create a DL group. The prime q will be determined according to p.
+ * @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);
+
+ /**
+ * Return PEM representation of named DL group
+ */
+ static const char* PEM_for_named_group(const std::string& name);
+ private:
+ static BigInt make_dsa_generator(const BigInt&, const BigInt&);
+
+ void init_check() const;
+ void initialize(const BigInt&, const BigInt&, const BigInt&);
+ bool initialized;
+ BigInt p, q, g;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/dl_group/info.txt b/src/lib/pubkey/dl_group/info.txt
new file mode 100644
index 000000000..26c6f12ca
--- /dev/null
+++ b/src/lib/pubkey/dl_group/info.txt
@@ -0,0 +1,10 @@
+define DL_GROUP 20131128
+
+<requires>
+asn1
+bigint
+filters
+libstate
+numbertheory
+pem
+</requires>
diff --git a/src/lib/pubkey/dl_group/named.cpp b/src/lib/pubkey/dl_group/named.cpp
new file mode 100644
index 000000000..df44f026b
--- /dev/null
+++ b/src/lib/pubkey/dl_group/named.cpp
@@ -0,0 +1,360 @@
+/*
+* List of discrete log groups
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+const char* DL_Group::PEM_for_named_group(const std::string& name)
+ {
+ if(name == "modp/ietf/1024")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIBCgKBgQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si"
+ "UUoIeY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummN+1r"
+ "C/9ctvQGt+3uOGv7Womfpa6fJBF8Sx/mSShmUezmU4H//////////wIBAgKBgH//"
+ "////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6AQXfUx2JzZEopQQ8xxoCbvfK"
+ "jNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9jeiYhdNMb9rWF/65begNb9vcc"
+ "Nf2tRM/S10+SCL4lj/MklDMo9nMpwP//////////"
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/srp/1024")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIBCgKBgQDurwq5rbON1pwz+Ar6j8XoYHJhh3X/PAueojFMnCVldtZ033SW6oHT"
+ "ODtIE9aSxuDg1djiULmL5I5JXB1gidrRXcfXtGFU1rbOjvStabFdSYJVmyl7zxiF"
+ "xSn1ZmYOV+xo7bw8BXJswC/Uy/SXbqqa/VE4/oN2Q1ufxh0vwOsG4wIBAgKBgHdX"
+ "hVzW2cbrThn8BX1H4vQwOTDDuv+eBc9RGKZOErK7azpvukt1QOmcHaQJ60ljcHBq"
+ "7HEoXMXyRySuDrBE7Wiu4+vaMKprW2dHela02K6kwSrNlL3njELilPqzMwcr9jR2"
+ "3h4CuTZgF+pl+ku3VU1+qJx/Qbshrc/jDpfgdYNx"
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/ietf/1536")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIBigKBwQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si"
+ "UUoIeY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummN+1r"
+ "C/9ctvQGt+3uOGv7Womfpa6fJBF8Sx/mSShmUezkWz3CAHy4oWO/BZjaSDYcVdOa"
+ "aRY/qP0kz1+DZV0j3KOtlhxi81YghVK7ntUpB3CWlm1nDDVOSryYBPF0bAjKI3Mn"
+ "//////////8CAQICgcB//////////+SH7VEQtGEaYmMxRcBuDmiUgScERTPmOgEF"
+ "31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Catrao4SLyQtq7MS8/Y3om"
+ "IXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/zJJQzKPZyLZ7hAD5cULHfgsxt"
+ "JBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqldz2qUg7hLSzazhhqnJV5MAni6"
+ "NgRlEbmT//////////8="
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/srp/1536")
+ return
+ "-----BEGIN DH PARAMETERS-----"
+ "MIHHAoHBAJ3vPK+5OSd6sfEqhheke7vbpR30maxMgL7uqWFLGcxNX09fVW4ny95R"
+ "xqlL5GB6KRVYkDug0PhDgLZVu5oi6NzfAop87Gfw0IE0sci5eYkUm2CeC+O6tj1H"
+ "VIOB28Wx/HZOP0tT3Z2hFYv9PiucjPVu3wGVOTSWJ9sv1T0kt8SGZXcuQ31sf4zk"
+ "QnNK98y3roN8Jkrjqb64f4ov6bi1KS5aAh//XpFHnoznoowkQsbzFRgPk0maI03P"
+ "duP+0TX5uwIBAg=="
+ "-----END DH PARAMETERS-----";
+
+ if(name == "modp/ietf/2048")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIICDAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAgKCAQB//////////+SH7VEQtGEa"
+ "YmMxRcBuDmiUgScERTPmOgEF31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4ob"
+ "p/Catrao4SLyQtq7MS8/Y3omIXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/z"
+ "JJQzKPZyLZ7hAD5cULHfgsxtJBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqld"
+ "z2qUg7hLSzazhhqnJV5MAni6NgRlDBC+GUgvIxcbZx3xzzuWDAdDAc2TwdF2A9FH"
+ "2uKu+DemKWTvFeX7SqwLjBzKpL51SrVyiukTDEx9AogKuUctRVZVNH//////////"
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/srp/2048")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIICDAKCAQEArGvbQTJKmpvxZt5eE4lYL69ytmUZh+4H/DGSlD21YFCjcynLtKCZ"
+ "7YGT4HV3Z6E91SMSq0sDMQ3Nf0ip2gT9UOgIOWntt2ewz2CVF5oWOrNmGgX71fqq"
+ "6CkYqZYvC5O4Vfl5k+yXXuqoDXQK2/T/dHNZ0EHVwz6nHSgeRGsUdzvKl7Q6I/uA"
+ "Fna9IHpDbGSB8dK5B4cXRhpbnTLmiPh3SFRFI7UksNV9Xqd6J3XS7PoDLPvb9S+z"
+ "eGFgJ5AE5Xrmr4dOcwPOUymczAQce8MI2CpWmPOo0MOCca41+Onb+7aUtcgD2J96"
+ "5DXeI21SX1R1m2XjcvzWjvIPpxEfnkr/cwIBAgKCAQBWNe2gmSVNTfizby8JxKwX"
+ "17lbMozD9wP+GMlKHtqwKFG5lOXaUEz2wMnwOruz0J7qkYlVpYGYhua/pFTtAn6o"
+ "dAQctPbbs9hnsEqLzQsdWbMNAv3q/VV0FIxUyxeFydwq/LzJ9kuvdVQGugVt+n+6"
+ "OazoIOrhn1OOlA8iNYo7neVL2h0R/cALO16QPSG2MkD46VyDw4ujDS3OmXNEfDuk"
+ "KiKR2pJYar6vU70Tuul2fQGWfe36l9m8MLATyAJyvXNXw6c5gecplM5mAg494YRs"
+ "FStMedRoYcE41xr8dO3920pa5AHsT71yGu8RtqkvqjrNsvG5fmtHeQfTiI/PJX+5"
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/ietf/3072")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIDDAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS"
+ "yv//////////AgECAoIBgH//////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6"
+ "AQXfUx2JzZEopQQ8xxoCbvfKjNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9j"
+ "eiYhdNMb9rWF/65begNb9vccNf2tRM/S10+SCL4lj/MklDMo9nItnuEAPlxQsd+C"
+ "zG0kGw4q6c00ix/UfpJnr8GyrpHuUdbLDjF5qxBCqV3PapSDuEtLNrOGGqclXkwC"
+ "eLo2BGUMEL4ZSC8jFxtnHfHPO5YMB0MBzZPB0XYD0Ufa4q74N6YpZO8V5ftKrAuM"
+ "HMqkvnVKtXKK6RMMTH0CiAq5Ry1FVWIW1pmLhoIoPRnUKpDV745dMnZ9woIsbfeF"
+ "RXU4q66DBj7Zy4fC03DyY9X610ZthJnrj0ZKcCUSsM7ncekTDWl3NfiX/QNsxQQy"
+ "bDsBOZ9kNTIpD5WMC72QBl3wi6u9MK62O4TEYF1so3EEcSfQOnLVmKHtrf5wfohH"
+ "JcFokFSdaWV//////////w=="
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/srp/3072")
+ return
+ "-----BEGIN DH PARAMETERS-----"
+ "MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS"
+ "yv//////////AgEF"
+ "-----END DH PARAMETERS-----";
+
+ if(name == "modp/ietf/4096")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIEDAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQICggIA"
+ "f//////////kh+1RELRhGmJjMUXAbg5olIEnBEUz5joBBd9THYnNkSilBDzHGgJu"
+ "98qM2eadIY2YFYU2+S+KG6fwmra2qOEi8kLauzEvP2N6JiF00xv2tYX/rlt6A1v2"
+ "9xw1/a1Ez9LXT5IIviWP8ySUMyj2ci2e4QA+XFCx34LMbSQbDirpzTSLH9R+kmev"
+ "wbKuke5R1ssOMXmrEEKpXc9qlIO4S0s2s4YapyVeTAJ4ujYEZQwQvhlILyMXG2cd"
+ "8c87lgwHQwHNk8HRdgPRR9rirvg3pilk7xXl+0qsC4wcyqS+dUq1corpEwxMfQKI"
+ "CrlHLUVVYhbWmYuGgig9GdQqkNXvjl0ydn3Cgixt94VFdTirroMGPtnLh8LTcPJj"
+ "1frXRm2EmeuPRkpwJRKwzudx6RMNaXc1+Jf9A2zFBDJsOwE5n2Q1MikPlYwLvZAG"
+ "XfCLq70wrrY7hMRgXWyjcQRxJ9A6ctWYoe2t/nB+iEclwWiQVJCEAI05HglTw/Nr"
+ "xDjNCF7dLZNM4ZOMNXpxHg1KNBpbCoXtEsH05RVqJnRt3eFtgm9HfJdHfgoP32VT"
+ "FD4so6c14C7M2Usn0Ehh0RGd0MMorfP2j7CUuGdxa9fcDe67ELgkDmgDSJPq2C1U"
+ "ydp1TEbH7uDDf9vuSFNgR6b6GuSaAxjM//////////8="
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/srp/4096")
+ return
+ "-----BEGIN DH PARAMETERS-----"
+ "MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQU="
+ "-----END DH PARAMETERS-----";
+
+ if(name == "modp/ietf/6144")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIGDAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA"
+ "JP//////////AoIDAH//////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6AQXf"
+ "Ux2JzZEopQQ8xxoCbvfKjNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9jeiYh"
+ "dNMb9rWF/65begNb9vccNf2tRM/S10+SCL4lj/MklDMo9nItnuEAPlxQsd+CzG0k"
+ "Gw4q6c00ix/UfpJnr8GyrpHuUdbLDjF5qxBCqV3PapSDuEtLNrOGGqclXkwCeLo2"
+ "BGUMEL4ZSC8jFxtnHfHPO5YMB0MBzZPB0XYD0Ufa4q74N6YpZO8V5ftKrAuMHMqk"
+ "vnVKtXKK6RMMTH0CiAq5Ry1FVWIW1pmLhoIoPRnUKpDV745dMnZ9woIsbfeFRXU4"
+ "q66DBj7Zy4fC03DyY9X610ZthJnrj0ZKcCUSsM7ncekTDWl3NfiX/QNsxQQybDsB"
+ "OZ9kNTIpD5WMC72QBl3wi6u9MK62O4TEYF1so3EEcSfQOnLVmKHtrf5wfohHJcFo"
+ "kFSQhACNOR4JU8Pza8Q4zQhe3S2TTOGTjDV6cR4NSjQaWwqF7RLB9OUVaiZ0bd3h"
+ "bYJvR3yXR34KD99lUxQ+LKOnNeAuzNlLJ9BIYdERndDDKK3z9o+wlLhncWvX3A3u"
+ "uxC4JA5oA0iT6tgtVMnadUxGx+7gw3/b7khTYEem+hrkmgFCSRth/VppPjgTYOpu"
+ "WTATI29kuo87Ht0b3vx/ygNWzymHcu2cF6CYANdYNSn2yBPsGIvLk9hDLUSMbR9t"
+ "9efNinaiZzZdZ2pdje2/iiPzZhKlmZAoqJXr16E33HoAm8ZpX6zB5QDjJcl2eBl1"
+ "Cui5DoH6QWvnNzp/e2qvOBejTAZBWtQgGMgFjk8s8+S/32P0eZHUvT8bZkRfB46i"
+ "2/+sLWKl6gPZFaCqVWZHtr9fpHDsCmYvaQfAG/BTy4r3eU3xlANQ6sXb4u07eqhV"
+ "HsUP3/h1jOZY0Ynqrm0rZPYXeUsZHD/0a7ceAjQCH0ezH6Qwdwlflq2Fujprc0p8"
+ "jzbmIBJ//////////wIBAg=="
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/srp/6144")
+ return
+ "-----BEGIN DH PARAMETERS-----"
+ "MIIDCAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA"
+ "JP//////////AgEF"
+ "-----END DH PARAMETERS-----";
+
+ if(name == "modp/ietf/8192")
+ return
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIIDAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R"
+ "WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk"
+ "ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw"
+ "xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4"
+ "Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i"
+ "aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU"
+ "38gfVuiAuW5xYMmA3Zjt09///////////wKCBAB//////////+SH7VEQtGEaYmMx"
+ "RcBuDmiUgScERTPmOgEF31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Ca"
+ "trao4SLyQtq7MS8/Y3omIXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/zJJQz"
+ "KPZyLZ7hAD5cULHfgsxtJBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqldz2qU"
+ "g7hLSzazhhqnJV5MAni6NgRlDBC+GUgvIxcbZx3xzzuWDAdDAc2TwdF2A9FH2uKu"
+ "+DemKWTvFeX7SqwLjBzKpL51SrVyiukTDEx9AogKuUctRVViFtaZi4aCKD0Z1CqQ"
+ "1e+OXTJ2fcKCLG33hUV1OKuugwY+2cuHwtNw8mPV+tdGbYSZ649GSnAlErDO53Hp"
+ "Ew1pdzX4l/0DbMUEMmw7ATmfZDUyKQ+VjAu9kAZd8IurvTCutjuExGBdbKNxBHEn"
+ "0Dpy1Zih7a3+cH6IRyXBaJBUkIQAjTkeCVPD82vEOM0IXt0tk0zhk4w1enEeDUo0"
+ "GlsKhe0SwfTlFWomdG3d4W2Cb0d8l0d+Cg/fZVMUPiyjpzXgLszZSyfQSGHREZ3Q"
+ "wyit8/aPsJS4Z3Fr19wN7rsQuCQOaANIk+rYLVTJ2nVMRsfu4MN/2+5IU2BHpvoa"
+ "5JoBQkkbYf1aaT44E2DqblkwEyNvZLqPOx7dG978f8oDVs8ph3LtnBegmADXWDUp"
+ "9sgT7BiLy5PYQy1EjG0fbfXnzYp2omc2XWdqXY3tv4oj82YSpZmQKKiV69ehN9x6"
+ "AJvGaV+sweUA4yXJdngZdQrouQ6B+kFr5zc6f3tqrzgXo0wGQVrUIBjIBY5PLPPk"
+ "v99j9HmR1L0/G2ZEXweOotv/rC1ipeoD2RWgqlVmR7a/X6Rw7ApmL2kHwBvwU8uK"
+ "93lN8ZQDUOrF2+LtO3qoVR7FD9/4dYzmWNGJ6q5tK2T2F3lLGRw/9Gu3HgI0Ah9H"
+ "sx+kMHcJX5athbo6a3NKfI823wisulHJN4l/cvIcO75bVJlvxmxfYmg53JjdHeQZ"
+ "W0bO6YA6D9PfxX4j9pK7e0m10hIzHVWxzi1yerQaEdo6FfjkvBHHi2XxzrKW8f7c"
+ "X35CRWyRERcCUgG+A4n1q9QNEfhjmjn+MjZ1GDWl5eRDF8HC7v1Opb/RYEP0PLQZ"
+ "gfat7p0DFZ562dE8UzaVCfwfonwW75iHcDpVtRsiy/RM0BKu4LJ5jmKEI0KO/NWk"
+ "DK72v1DY6ohev3Omuf15teGPZ9E0GsgjenXDz8kgBKHFpA42a8RNABdq9xwV5IyG"
+ "034BNyPKrHIjqzv01U8YKHE7K0pv5A+rdEBctziwZMBuzHbp7///////////AgEC"
+ "-----END X942 DH PARAMETERS-----";
+
+ if(name == "modp/srp/8192")
+ return
+ "-----BEGIN DH PARAMETERS-----"
+ "MIIECAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R"
+ "WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk"
+ "ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw"
+ "xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4"
+ "Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i"
+ "aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU"
+ "38gfVuiAuW5xYMmA3Zjt09///////////wIBEw=="
+ "-----END DH PARAMETERS-----";
+
+ if(name == "dsa/jce/1024")
+ return
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIIBHgKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9"
+ "jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX"
+ "58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8V"
+ "IwvMspK5gqLrhAvwWBz1AoGARpYDUS4wJ4zTlHWV2yLuyYJqYyKtyXNE9B10DDJX"
+ "JMj577qn1NgD/4xgnc0QDrxb38+tfGpCX66nhuogUOvpg1HqH9of3yTWlHqmuaoj"
+ "dmlTgC9NfUqOy6BtGXaKJJH/sW0O+cQ6mbX3FnL/bwoktETQc20E04oaEyLa9s3Y"
+ "jJ0="
+ "-----END DSA PARAMETERS-----";
+
+ if(name == "dsa/botan/2048")
+ return
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIICLAKCAQEAkcSKT9+898Aq6V59oSYSK13Shk9Vm4fo50oobVL1m9HeaN/WRdDg"
+ "DGDAgAMYkZgDdO61lKUyv9Z7mgnqxLhmOgeRDmjzlGX7cEDSXfE5MuusQ0elMOy6"
+ "YchU+biA08DDZgCAWHxFVm2t4mvVo5S+CTtMDyS1r/747GxbPlf7iQJam8FnaZMh"
+ "MeFtPJTvyrGNDfBhIDzFPmEDvHLVWUv9QMplOA9EqahR3LB1SV/AM6ilgHGhvXj+"
+ "BS9mVVZI60txnSr+i0iA+NrW8VgYuhePiSdMhwvpuW6wjEbEAEDMLv4d+xsYaN0x"
+ "nePDSjKmOrbrEiQgmkGWgMx5AtFyjU354QIhAIzX1FD4bwrZTu5M5GmodW0evRBY"
+ "JBlD6v+ws1RYXpJNAoIBAA2fXgdhtNvRgz1qsalhoJlsXyIwP3LYTBQPZ8Qx2Uq1"
+ "cVvqgaDJjTnOS8941rnryJXTT+idlAkdWEhhXvFfXobxHZb2yWniA936WDVkIKSc"
+ "tES1lbkBqTPP4HZ7WU8YoHt/kd7NukRriJkPePL/kfL+fNQ/0uRtGOraH3u2YCxh"
+ "f27zpLKE8v2boQo2BC3o+oeiyjZZf+yBFXoUheRAQd8CgwERy4gLvm7UlIFIhvll"
+ "zcMTX1zPE4Nyi/ZbgG+WksCxDWxMCcdabKO0ATyxarLBBfa+I66pAA6rIXiYX5cs"
+ "mAV+HIbkTnIYaI6krg82NtzKdFydzU5q/7Z8y8E9YTE="
+ "-----END DSA PARAMETERS-----";
+
+ if(name == "dsa/botan/3072")
+ return
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIIDLAKCAYEA5LUIgHWWY1heFCRgyi2d/xMviuTIQN2jomZoiRJP5WOLhOiim3rz"
+ "+hIJvmv8S1By7Tsrc4e68/hX9HioAijvNgC3az3Pth0g00RlslBtLK+H3259wM6R"
+ "vS0Wekb2rcwxxTHk+cervbkq3fNbCoBsZikqX14X6WTdCZkDczrEKKs12A6m9oW/"
+ "uovkBo5UGK5eytno/wc94rY+Tn6tNciptwtb1Hz7iNNztm83kxk5sKtxvVWVgJCG"
+ "2gFVM30YWg5Ps2pRmxtiArhZHmACRJzxzTpmOE9tIHOxzXO+ypO68eGmEX0COPIi"
+ "rh7X/tGFqJDn9n+rj+uXU8wTSlGD3+h64llfe1wtn7tCJJ/dWVE+HTOWs+sv2GaE"
+ "8oWoRI/nV6ApiBxAdguU75Gb35dAw4OJWZ7FGm6btRmo4GhJHpzgovz+PLYNZs8N"
+ "+tIKjsaEBIaEphREV1vRck1zUrRKdgB3s71r04XOWwpyUMwL92jagpI4Buuc+7E4"
+ "hDcxthggjHWbAiEAs+vTZOxp74zzuvZDt1c0sWM5suSeXN4bWcHp+0DuDFsCggGA"
+ "K+0h7vg5ZKIwrom7px2ffDnFL8gim047x+WUTTKdoQ8BDqyee69sAJ/E6ylgcj4r"
+ "Vt9GY+TDrIAOkljeL3ZJ0gZ4KJP4Ze/KSY0u7zAHTqXop6smJxKk2UovOwuaku5A"
+ "D7OKPMWaXcfkNtXABLIuNQKDgbUck0B+sy1K4P1Cy0XhLQ7O6KJiOO3iCCp7FSIR"
+ "PGbO+NdFxs88uUX4TS9N4W1Epx3hmCcOE/A1U8iLjTI60LlIob8hA6lJl5tu0W+1"
+ "88lT2Vt8jojKZ9z1pjb7nKOdkkIV96iE7Wx+48ltjZcVQnl0t8Q1EoLhPTdz99KL"
+ "RS8QiSoTx1hzKN6kgntrNpsqjcFyrcWD9R8qZZjFSD5bxGewL5HQWcQC0Y4sJoD3"
+ "dqoG9JKAoscsF8xC1bbnQMXEsas8UcLtCSviotiwU65Xc9FCXtKwjwbi3VBZLfGk"
+ "eMFVkc39EVZP+I/zi3IdQjkv2kcyEtz9jS2IqXagCv/m//tDCjWeZMorNRyiQSOU"
+ "-----END DSA PARAMETERS-----";
+
+ return nullptr;
+ }
+
+}
diff --git a/src/lib/pubkey/dlies/dlies.cpp b/src/lib/pubkey/dlies/dlies.cpp
new file mode 100644
index 000000000..715b55a36
--- /dev/null
+++ b/src/lib/pubkey/dlies/dlies.cpp
@@ -0,0 +1,146 @@
+/*
+* DLIES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dlies.h>
+#include <botan/internal/xor_buf.h>
+
+namespace Botan {
+
+/*
+* DLIES_Encryptor Constructor
+*/
+DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& key,
+ KDF* kdf_obj,
+ MessageAuthenticationCode* mac_obj,
+ size_t mac_kl) :
+ ka(key, "Raw"),
+ kdf(kdf_obj),
+ mac(mac_obj),
+ mac_keylen(mac_kl)
+ {
+ my_key = key.public_value();
+ }
+
+DLIES_Encryptor::~DLIES_Encryptor()
+ {
+ delete kdf;
+ delete mac;
+ }
+
+/*
+* DLIES Encryption
+*/
+std::vector<byte> DLIES_Encryptor::enc(const byte in[], size_t length,
+ RandomNumberGenerator&) const
+ {
+ if(length > maximum_input_size())
+ throw Invalid_Argument("DLIES: Plaintext too large");
+ if(other_key.empty())
+ throw Invalid_State("DLIES: The other key was never set");
+
+ secure_vector<byte> out(my_key.size() + length + mac->output_length());
+ buffer_insert(out, 0, my_key);
+ buffer_insert(out, my_key.size(), in, length);
+
+ secure_vector<byte> vz(my_key.begin(), my_key.end());
+ vz += ka.derive_key(0, other_key).bits_of();
+
+ const size_t K_LENGTH = length + mac_keylen;
+ OctetString K = kdf->derive_key(K_LENGTH, vz);
+
+ if(K.length() != K_LENGTH)
+ throw Encoding_Error("DLIES: KDF did not provide sufficient output");
+ byte* C = &out[my_key.size()];
+
+ xor_buf(C, K.begin() + mac_keylen, length);
+ mac->set_key(K.begin(), mac_keylen);
+
+ mac->update(C, length);
+ for(size_t j = 0; j != 8; ++j)
+ mac->update(0);
+
+ mac->final(C + length);
+
+ return unlock(out);
+ }
+
+/*
+* Set the other parties public key
+*/
+void DLIES_Encryptor::set_other_key(const std::vector<byte>& ok)
+ {
+ other_key = ok;
+ }
+
+/*
+* Return the max size, in bytes, of a message
+*/
+size_t DLIES_Encryptor::maximum_input_size() const
+ {
+ return 32;
+ }
+
+/*
+* DLIES_Decryptor Constructor
+*/
+DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& key,
+ KDF* kdf_obj,
+ MessageAuthenticationCode* mac_obj,
+ size_t mac_kl) :
+ ka(key, "Raw"),
+ kdf(kdf_obj),
+ mac(mac_obj),
+ mac_keylen(mac_kl)
+ {
+ my_key = key.public_value();
+ }
+
+DLIES_Decryptor::~DLIES_Decryptor()
+ {
+ delete kdf;
+ delete mac;
+ }
+
+/*
+* DLIES Decryption
+*/
+secure_vector<byte> DLIES_Decryptor::dec(const byte msg[], size_t length) const
+ {
+ if(length < my_key.size() + mac->output_length())
+ throw Decoding_Error("DLIES decryption: ciphertext is too short");
+
+ const size_t CIPHER_LEN = length - my_key.size() - mac->output_length();
+
+ std::vector<byte> v(msg, msg + my_key.size());
+
+ secure_vector<byte> C(msg + my_key.size(), msg + my_key.size() + CIPHER_LEN);
+
+ secure_vector<byte> T(msg + my_key.size() + CIPHER_LEN,
+ msg + my_key.size() + CIPHER_LEN + mac->output_length());
+
+ secure_vector<byte> vz(msg, msg + my_key.size());
+ vz += ka.derive_key(0, v).bits_of();
+
+ const size_t K_LENGTH = C.size() + mac_keylen;
+ OctetString K = kdf->derive_key(K_LENGTH, vz);
+ if(K.length() != K_LENGTH)
+ throw Encoding_Error("DLIES: KDF did not provide sufficient output");
+
+ mac->set_key(K.begin(), mac_keylen);
+ mac->update(C);
+ for(size_t j = 0; j != 8; ++j)
+ mac->update(0);
+ secure_vector<byte> T2 = mac->final();
+ if(T != T2)
+ throw Decoding_Error("DLIES: message authentication failed");
+
+ xor_buf(C, K.begin() + mac_keylen, C.size());
+
+ return C;
+ }
+
+}
diff --git a/src/lib/pubkey/dlies/dlies.h b/src/lib/pubkey/dlies/dlies.h
new file mode 100644
index 000000000..9739afeb2
--- /dev/null
+++ b/src/lib/pubkey/dlies/dlies.h
@@ -0,0 +1,71 @@
+/*
+* DLIES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DLIES_H__
+#define BOTAN_DLIES_H__
+
+#include <botan/pubkey.h>
+#include <botan/mac.h>
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/**
+* DLIES Encryption
+*/
+class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor
+ {
+ public:
+ DLIES_Encryptor(const PK_Key_Agreement_Key&,
+ KDF* kdf,
+ MessageAuthenticationCode* mac,
+ size_t mac_key_len = 20);
+
+ ~DLIES_Encryptor();
+
+ void set_other_key(const std::vector<byte>&);
+ private:
+ std::vector<byte> enc(const byte[], size_t,
+ RandomNumberGenerator&) const;
+
+ size_t maximum_input_size() const;
+
+ std::vector<byte> other_key, my_key;
+
+ PK_Key_Agreement ka;
+ KDF* kdf;
+ MessageAuthenticationCode* mac;
+ size_t mac_keylen;
+ };
+
+/**
+* DLIES Decryption
+*/
+class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor
+ {
+ public:
+ DLIES_Decryptor(const PK_Key_Agreement_Key&,
+ KDF* kdf,
+ MessageAuthenticationCode* mac,
+ size_t mac_key_len = 20);
+
+ ~DLIES_Decryptor();
+
+ private:
+ secure_vector<byte> dec(const byte[], size_t) const;
+
+ std::vector<byte> my_key;
+
+ PK_Key_Agreement ka;
+ KDF* kdf;
+ MessageAuthenticationCode* mac;
+ size_t mac_keylen;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/dlies/info.txt b/src/lib/pubkey/dlies/info.txt
new file mode 100644
index 000000000..b159cc546
--- /dev/null
+++ b/src/lib/pubkey/dlies/info.txt
@@ -0,0 +1,7 @@
+define DLIES 20131128
+
+<requires>
+kdf
+libstate
+mac
+</requires>
diff --git a/src/lib/pubkey/dsa/dsa.cpp b/src/lib/pubkey/dsa/dsa.cpp
new file mode 100644
index 000000000..5d56d6b89
--- /dev/null
+++ b/src/lib/pubkey/dsa/dsa.cpp
@@ -0,0 +1,143 @@
+/*
+* DSA
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dsa.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <future>
+namespace Botan {
+
+/*
+* DSA_PublicKey Constructor
+*/
+DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ }
+
+/*
+* Create a DSA private key
+*/
+DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ group = grp;
+ x = x_arg;
+
+ if(x == 0)
+ x = BigInt::random_integer(rng, 2, group_q() - 1);
+
+ y = power_mod(group_g(), x, group_p());
+
+ if(x_arg == 0)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng) :
+ DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
+ {
+ y = power_mod(group_g(), x, group_p());
+
+ load_check(rng);
+ }
+
+/*
+* Check Private DSA Parameters
+*/
+bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!DL_Scheme_PrivateKey::check_key(rng, strong) || x >= group_q())
+ return false;
+
+ if(!strong)
+ return true;
+
+ return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)");
+ }
+
+DSA_Signature_Operation::DSA_Signature_Operation(const DSA_PrivateKey& dsa) :
+ q(dsa.group_q()),
+ x(dsa.get_x()),
+ powermod_g_p(dsa.group_g(), dsa.group_p()),
+ mod_q(dsa.group_q())
+ {
+ }
+
+secure_vector<byte>
+DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ rng.add_entropy(msg, msg_len);
+
+ BigInt i(msg, msg_len);
+ BigInt r = 0, s = 0;
+
+ while(r == 0 || s == 0)
+ {
+ BigInt k;
+ do
+ k.randomize(rng, q.bits());
+ while(k >= q);
+
+ auto future_r = std::async(std::launch::async,
+ [&]() { return mod_q.reduce(powermod_g_p(k)); });
+
+ s = inverse_mod(k, q);
+ r = future_r.get();
+ s = mod_q.multiply(s, mul_add(x, r, i));
+ }
+
+ secure_vector<byte> output(2*q.bytes());
+ r.binary_encode(&output[output.size() / 2 - r.bytes()]);
+ s.binary_encode(&output[output.size() - s.bytes()]);
+ return output;
+ }
+
+DSA_Verification_Operation::DSA_Verification_Operation(const DSA_PublicKey& dsa) :
+ q(dsa.group_q()), y(dsa.get_y())
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(dsa.group_g(), dsa.group_p());
+ powermod_y_p = Fixed_Base_Power_Mod(y, dsa.group_p());
+ mod_p = Modular_Reducer(dsa.group_p());
+ mod_q = Modular_Reducer(dsa.group_q());
+ }
+
+bool DSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len)
+ {
+ const BigInt& q = mod_q.get_modulus();
+
+ 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);
+
+ if(r <= 0 || r >= q || s <= 0 || s >= q)
+ return false;
+
+ s = inverse_mod(s, q);
+
+ auto future_s_i = std::async(std::launch::async,
+ [&]() { return powermod_g_p(mod_q.multiply(s, i)); });
+
+ BigInt s_r = powermod_y_p(mod_q.multiply(s, r));
+ BigInt s_i = future_s_i.get();
+
+ s = mod_p.multiply(s_i, s_r);
+
+ return (mod_q.reduce(s) == r);
+ }
+
+}
diff --git a/src/lib/pubkey/dsa/dsa.h b/src/lib/pubkey/dsa/dsa.h
new file mode 100644
index 000000000..7d51cfdd0
--- /dev/null
+++ b/src/lib/pubkey/dsa/dsa.h
@@ -0,0 +1,107 @@
+/*
+* DSA
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DSA_H__
+#define BOTAN_DSA_H__
+
+#include <botan/dl_algo.h>
+#include <botan/pk_ops.h>
+#include <botan/reducer.h>
+#include <botan/pow_mod.h>
+
+namespace Botan {
+
+/**
+* DSA Public Key
+*/
+class BOTAN_DLL DSA_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "DSA"; }
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return group_q().bytes(); }
+ size_t max_input_bits() const { return group_q().bits(); }
+
+ DSA_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits) :
+ DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
+ {
+ }
+
+ DSA_PublicKey(const DL_Group& group, const BigInt& y);
+ protected:
+ DSA_PublicKey() {}
+ };
+
+/**
+* DSA Private Key
+*/
+class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng);
+
+ DSA_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& group,
+ const BigInt& private_key = 0);
+
+ bool check_key(RandomNumberGenerator& rng, bool strong) const;
+ };
+
+/**
+* Object that can create a DSA signature
+*/
+class BOTAN_DLL DSA_Signature_Operation : public PK_Ops::Signature
+ {
+ public:
+ DSA_Signature_Operation(const DSA_PrivateKey& dsa);
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return q.bytes(); }
+ size_t max_input_bits() const { return q.bits(); }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+ private:
+ const BigInt& q;
+ const BigInt& x;
+ Fixed_Base_Power_Mod powermod_g_p;
+ Modular_Reducer mod_q;
+ };
+
+/**
+* Object that can verify a DSA signature
+*/
+class BOTAN_DLL DSA_Verification_Operation : public PK_Ops::Verification
+ {
+ public:
+ DSA_Verification_Operation(const DSA_PublicKey& dsa);
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return q.bytes(); }
+ size_t max_input_bits() const { return q.bits(); }
+
+ bool with_recovery() const { return false; }
+
+ bool verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len);
+ private:
+ const BigInt& q;
+ const BigInt& y;
+
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/dsa/info.txt b/src/lib/pubkey/dsa/info.txt
new file mode 100644
index 000000000..a3f2a1ee4
--- /dev/null
+++ b/src/lib/pubkey/dsa/info.txt
@@ -0,0 +1,9 @@
+define DSA 20131128
+
+<requires>
+dl_algo
+dl_group
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp
new file mode 100644
index 000000000..9143543e4
--- /dev/null
+++ b/src/lib/pubkey/ec_group/ec_group.cpp
@@ -0,0 +1,134 @@
+/*
+* ECC Domain Parameters
+*
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ec_group.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/libstate.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+
+namespace Botan {
+
+EC_Group::EC_Group(const OID& domain_oid)
+ {
+ const char* pem = PEM_for_named_group(OIDS::lookup(domain_oid));
+
+ if(!pem)
+ throw Lookup_Error("No ECC domain data for " + domain_oid.as_string());
+
+ *this = EC_Group(pem);
+ oid = domain_oid.as_string();
+ }
+
+EC_Group::EC_Group(const std::string& str)
+ {
+ if(str == "")
+ return; // no initialization / uninitialized
+
+ try
+ {
+ std::vector<byte> ber =
+ unlock(PEM_Code::decode_check_label(str, "EC PARAMETERS"));
+
+ *this = EC_Group(ber);
+ }
+ catch(Decoding_Error) // hmm, not PEM?
+ {
+ *this = EC_Group(OIDS::lookup(str));
+ }
+ }
+
+EC_Group::EC_Group(const std::vector<byte>& ber_data)
+ {
+ BER_Decoder ber(ber_data);
+ BER_Object obj = ber.get_next_object();
+
+ if(obj.type_tag == NULL_TAG)
+ throw Decoding_Error("Cannot handle ImplicitCA ECDSA parameters");
+ else if(obj.type_tag == OBJECT_ID)
+ {
+ OID dom_par_oid;
+ BER_Decoder(ber_data).decode(dom_par_oid);
+ *this = EC_Group(dom_par_oid);
+ }
+ else if(obj.type_tag == SEQUENCE)
+ {
+ BigInt p, a, b;
+ std::vector<byte> sv_base_point;
+
+ BER_Decoder(ber_data)
+ .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)
+ .end_cons()
+ .decode(sv_base_point, OCTET_STRING)
+ .decode(order)
+ .decode(cofactor)
+ .end_cons()
+ .verify_end();
+
+ curve = CurveGFp(p, a, b);
+ base_point = OS2ECP(sv_base_point, curve);
+ }
+ else
+ throw Decoding_Error("Unexpected tag while decoding ECC domain params");
+ }
+
+std::vector<byte>
+EC_Group::DER_encode(EC_Group_Encoding form) const
+ {
+ if(form == EC_DOMPAR_ENC_EXPLICIT)
+ {
+ const size_t ecpVers1 = 1;
+ OID curve_type("1.2.840.10045.1.1");
+
+ const size_t p_bytes = curve.get_p().bytes();
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(ecpVers1)
+ .start_cons(SEQUENCE)
+ .encode(curve_type)
+ .encode(curve.get_p())
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .encode(BigInt::encode_1363(curve.get_a(), p_bytes),
+ OCTET_STRING)
+ .encode(BigInt::encode_1363(curve.get_b(), p_bytes),
+ OCTET_STRING)
+ .end_cons()
+ .encode(EC2OSP(base_point, PointGFp::UNCOMPRESSED), OCTET_STRING)
+ .encode(order)
+ .encode(cofactor)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+ else if(form == EC_DOMPAR_ENC_OID)
+ return DER_Encoder().encode(OID(get_oid())).get_contents_unlocked();
+ else if(form == EC_DOMPAR_ENC_IMPLICITCA)
+ return DER_Encoder().encode_null().get_contents_unlocked();
+ else
+ throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
+ }
+
+std::string EC_Group::PEM_encode() const
+ {
+ const std::vector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
+ return PEM_Code::encode(der, "EC PARAMETERS");
+ }
+
+}
diff --git a/src/lib/pubkey/ec_group/ec_group.h b/src/lib/pubkey/ec_group/ec_group.h
new file mode 100644
index 000000000..80859bd71
--- /dev/null
+++ b/src/lib/pubkey/ec_group/ec_group.h
@@ -0,0 +1,148 @@
+/*
+* ECC Domain Parameters
+*
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECC_DOMAIN_PARAMETERS_H__
+#define BOTAN_ECC_DOMAIN_PARAMETERS_H__
+
+#include <botan/point_gfp.h>
+#include <botan/curve_gfp.h>
+#include <botan/asn1_oid.h>
+
+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 representing an elliptic curve
+*/
+class BOTAN_DLL EC_Group
+ {
+ 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
+ */
+ EC_Group(const CurveGFp& curve,
+ const PointGFp& base_point,
+ const BigInt& order,
+ const BigInt& cofactor) :
+ curve(curve),
+ base_point(base_point),
+ order(order),
+ cofactor(cofactor),
+ oid("")
+ {}
+
+ /**
+ * Decode a BER encoded ECC domain parameter set
+ * @param ber_encoding the bytes of the BER encoding
+ */
+ EC_Group(const std::vector<byte>& ber_encoding);
+
+ /**
+ * Create an EC domain by OID (or throw if unknown)
+ * @param oid the OID of the EC domain to create
+ */
+ 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
+ */
+ EC_Group(const std::string& pem_or_oid = "");
+
+ /**
+ * Create the DER encoding of this domain
+ * @param form of encoding to use
+ * @returns bytes encododed as DER
+ */
+ std::vector<byte> 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
+ */
+ const CurveGFp& get_curve() const { return curve; }
+
+ /**
+ * Return domain parameter curve
+ * @result domain parameter curve
+ */
+ const PointGFp& get_base_point() const { return base_point; }
+
+ /**
+ * Return the order of the base point
+ * @result order of the base point
+ */
+ const BigInt& get_order() const { return order; }
+
+ /**
+ * Return the cofactor
+ * @result the cofactor
+ */
+ const BigInt& get_cofactor() const { return cofactor; }
+
+ bool initialized() const { return !base_point.is_zero(); }
+
+ /**
+ * Return the OID of these domain parameters
+ * @result the OID
+ */
+ std::string get_oid() const { return oid; }
+
+ bool operator==(const EC_Group& other) const
+ {
+ return ((get_curve() == other.get_curve()) &&
+ (get_base_point() == other.get_base_point()) &&
+ (get_order() == other.get_order()) &&
+ (get_cofactor() == other.get_cofactor()));
+ }
+
+ /**
+ * Return PEM representation of named EC group
+ */
+ static const char* PEM_for_named_group(const std::string& name);
+
+ private:
+ CurveGFp curve;
+ PointGFp base_point;
+ BigInt order, cofactor;
+ std::string oid;
+ };
+
+inline bool operator!=(const EC_Group& lhs,
+ const EC_Group& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+// For compatability with 1.8
+typedef EC_Group EC_Domain_Params;
+
+}
+
+#endif
diff --git a/src/lib/pubkey/ec_group/info.txt b/src/lib/pubkey/ec_group/info.txt
new file mode 100644
index 000000000..661f24473
--- /dev/null
+++ b/src/lib/pubkey/ec_group/info.txt
@@ -0,0 +1,10 @@
+define ECC_GROUP 20131128
+
+<requires>
+asn1
+ec_gfp
+libstate
+numbertheory
+oid_lookup
+pem
+</requires>
diff --git a/src/lib/pubkey/ec_group/named.cpp b/src/lib/pubkey/ec_group/named.cpp
new file mode 100644
index 000000000..86e99db6d
--- /dev/null
+++ b/src/lib/pubkey/ec_group/named.cpp
@@ -0,0 +1,307 @@
+/*
+* List of ECC groups
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ec_group.h>
+
+namespace Botan {
+
+const char* EC_Group::PEM_for_named_group(const std::string& name)
+ {
+ if(name == "secp112r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MHQCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDtt8Kr9i415mgHa+"
+ "rSCIBA5lnvi6BDkW7t6JEXArIgQdBAlIcjmZWl7na1X5wvCYqJzlr4ckwKI+Dg/3"
+ "dQACDwDbfCq/YuNedijfrGVhxQIBAQ=="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp112r2")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MHMCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDmEnwkwF84oKqvZc"
+ "DvAsBA5R3vGBXbXtdPzDTIXXCQQdBEujCrXokrThZJ3QkoZDrc1G9YguN0fe826V"
+ "bpcCDjbfCq/YuNdZfKEFINBLAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp128r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGAAgEBMBwGByqGSM49AQECEQD////9////////////////MCQEEP////3/////"
+ "//////////wEEOh1ecEQefQ92CSZPCzuXtMEIQQWH/dSi4mbLQwoYHylLFuGz1rI"
+ "OVuv6xPALaKS3e16gwIRAP////4AAAAAdaMNG5A4oRUCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp128r2")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MH8CAQEwHAYHKoZIzj0BAQIRAP////3///////////////8wJAQQ1gMZmNGzu/6/"
+ "Wcybv/mu4QQQXu78o4DQKRncLGVYu22KXQQhBHtqpdheVymD5vsyp83rwUAntpFq"
+ "iU067nEG/oBfw0tEAhA/////f////74AJHIGE7WjAgEE"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp160k1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGYAgEBMCAGByqGSM49AQECFQD////////////////////+//+sczAsBBQAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAQUAAAAAAAAAAAAAAAAAAAAAAAAAAcEKQQ7TDgs43qh"
+ "kqQBnnYwNvT13U1+u5OM+TUxj9zta8KChlMXM8PwPE/uAhUBAAAAAAAAAAAAAbj6"
+ "Ft+rmsoWtrMCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp160r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGYAgEBMCAGByqGSM49AQECFQD/////////////////////f////zAsBBT/////"
+ "////////////////f////AQUHJe+/FS9eotlrPifgdTUrcVl+kUEKQRKlrVojvVz"
+ "KEZkaYlow4u5E8v8giOmKFUxaJR9WdzJEgQjUTd6xfsyAhUBAAAAAAAAAAAAAfTI"
+ "+Seu08p1IlcCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp160r2")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGYAgEBMCAGByqGSM49AQECFQD////////////////////+//+sczAsBBT/////"
+ "///////////////+//+scAQUtOE00/tZ64urVydJBGZNWvUDiLoEKQRS3LA0KToR"
+ "fh9P8Rsw9xmdMUTObf6v/vLjMfKW4HH6DfmYLP6n1D8uAhUBAAAAAAAAAAAAADUe"
+ "54aoGPOhoWsCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp192k1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGwAgEBMCQGByqGSM49AQECGQD//////////////////////////v//7jcwNAQY"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAMEMQTbT/EOwFfpriawfQKAt/Q0HaXRsergbH2bLy9tnFYop4RBY9AVvoY0QIKq"
+ "iNleL50CGQD///////////////4m8vwXD2lGanTe/Y0CAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp192r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY"
+ "/////////////////////v/////////8BBhkIQUZ5ZyA5w+n6atyJDBJ/rje7MFG"
+ "ubEEMQQYjagOsDCQ9ny/IOtDoYgA9P8K/YL/EBIHGSuV/8jaeGMQEe1rJM3Vc/l3"
+ "oR55SBECGQD///////////////+Z3vg2FGvJsbTSKDECAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp224k1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHIAgEBMCgGByqGSM49AQECHQD///////////////////////////////7//+Vt"
+ "MDwEHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAUEOQShRVszTfCZ3zD8KKFppGfp5HB1qQ9+ZQ62t6Rcfgif"
+ "7X+6NEKCyvvW9+MZ98CwvVniykvbVW1hpQIdAQAAAAAAAAAAAAAAAAAB3OjS7GGE"
+ "yvCpcXafsfcCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp224r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHIAgEBMCgGByqGSM49AQECHQD/////////////////////AAAAAAAAAAAAAAAB"
+ "MDwEHP////////////////////7///////////////4EHLQFCoUMBLOr9UEyVlBE"
+ "sLfXv9i6Jws5QyNV/7QEOQS3Dgy9a7S/fzITkLlKA8HTVsIRIjQygNYRXB0hvTdj"
+ "iLX3I/tMIt/mzUN1oFoHR2RE1YGZhQB+NAIdAP//////////////////FqLguPA+"
+ "E90pRVxcKj0CAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp256k1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHgAgEBMCwGByqGSM49AQECIQD////////////////////////////////////+"
+ "///8LzBEBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQgAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcEQQR5vmZ++dy7rFWgYpXOhwsHApv8"
+ "2y3OKNlZ8oFbFvgXmEg62ncmo8RlXaT7/A4RCKj9F7RIpoVUGZxH0I/7ENS4AiEA"
+ "/////////////////////rqu3OavSKA7v9JejNA2QUECAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp256r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHgAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////"
+ "/////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6"
+ "k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEQQRrF9Hy4SxCR/i85uVjpEDydwN9"
+ "gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA"
+ "/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp384r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIIBQAIBATA8BgcqhkjOPQEBAjEA////////////////////////////////////"
+ "//////7/////AAAAAAAAAAD/////MGQEMP//////////////////////////////"
+ "///////////+/////wAAAAAAAAAA/////AQwszEvp+I+5+SYjgVr4/gtGRgdnG7+"
+ "gUESAxQIj1ATh1rGVjmNii7RnSqFyO3T7CrvBGEEqofKIr6LBTeOscce8yCtdG4d"
+ "O2KLp5uYWfdB4IJUKjhVAvJdv1UpbDpUXjhydgq3NhfeSpYmLG9dnpi/kpLcKfj0"
+ "Hb0omhR86doxE7XwuMAKYLHOHX6BnXpDHXyQ6g5fAjEA////////////////////"
+ "////////////x2NNgfQ3Ld9YGg2ySLCneuzsGWrMxSlzAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "secp521r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////"
+ "//////////////////////////////////////////////////8wgYgEQgH/////"
+ "////////////////////////////////////////////////////////////////"
+ "/////////////////ARCAFGVPrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ"
+ "4VYZOVHsfpN7FlLAvTuxvwc1c9+IPSw08e9FH9RrUD8ABIGFBADGhY4GtwQE6c2e"
+ "PstmI5W0QpxkgTkFP7Uh+CivYGtNPbqhS1537+dZKP4dwSei/6jeM0izwYVqQpv5"
+ "fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm"
+ "QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////"
+ "////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "1.3.6.1.4.1.8301.3.1.2.9.0.38")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////"
+ "//////////////////////////////////////////////////8wgYgEQgH/////"
+ "////////////////////////////////////////////////////////////////"
+ "/////////////////ARCAFGVPrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ"
+ "4VYZOVHsfpN7FlLAvTuxvwc1c9+IPSw08e9FH9RrUD8ABIGFBADGhY4GtwQE6c2e"
+ "PstmI5W0QpxkgTkFP7Uh+CivYGtNPbqhS1537+dZKP4dwSei/6jeM0izwYVqQpv5"
+ "fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm"
+ "QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////"
+ "////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "brainpool160r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGYAgEBMCAGByqGSM49AQECFQDpXkpfc3BZ3GDfx62Vs9gTlRViDzAsBBQ0Dnvi"
+ "ooDrdOK+YbradF2X6PfDAAQUHliahZVCNBITT6otveyVyNhnXlgEKQS+1a8W6j9q"
+ "T2KTjEYx61r3vbzbwxZny0d6Go7DOPlHQWacl2MW2mMhAhUA6V5KX3NwWdxg31mR"
+ "1FApQJ5g/AkCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "brainpool192r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGwAgEBMCQGByqGSM49AQECGQDDAvQdkyo2zaejRjCT0Y23j85HbeGoYpcwNAQY"
+ "apEXQHax4OGcOcAx/oaFwcrgQOXGmijvBBhGmijvfCjMo9xyHQRPRJa8yn70FG+/"
+ "JckEMQTAoGR+qrakh1OwM8VssPCQCi9cSFM3X9YUtpCGar1buItfSCjBSQAC5nc/"
+ "ovopm48CGQDDAvQdkyo2zaejRi+enpFrW+jxAprErMECAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "brainpool224r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHIAgEBMCgGByqGSM49AQECHQDXwTSqJkNmhioYMCV10deHsJ8HV5faifV+yMD/"
+ "MDwEHGil5iypzmwcKZgDpsFTC1FOGCrYsAQqWcrSn0MEHCWA9jzP5EE4hwcTsakj"
+ "aeM+ITXSZtuzcjhsQAsEOQQNkCmtLH5c9DQII7KofcaMnkzjF0webv3uEsB9WKpW"
+ "93LAcm8kxrieTs2sJDVLnpnKo/bTdhQCzQIdANfBNKomQ2aGKhgwJXXQ+5jRFrxL"
+ "bd68o6Wnk58CAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "brainpool256r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHgAgEBMCwGByqGSM49AQECIQCp+1fboe6pvD5mCpCdg41ybjv2I9UmICggE0gd"
+ "H25TdzBEBCB9Wgl1/CwwV+72dTBBev/n+4BVwSbcXGzpSktE8zC12QQgJtxcbOlK"
+ "S0TzMLXZu9d8v5WEFilc9+HOa8zcGP+MB7YEQQSL0q65y35XyyxLSC/8gbevud4n"
+ "4eO9I8I6RFO9ms4yYlR++DXD2sT9l/hGGhRhHcnCd0UTLe2OVFwdVMcvBGmXAiEA"
+ "qftX26Huqbw+ZgqQnYONcYw5eqO1Yab3kB4OgpdIVqcCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "brainpool320r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIIBEAIBATA0BgcqhkjOPQEBAikA015HIDa8T7fhPHhe0gHgZfmPz6b29A3vT5K5"
+ "7HiT7Cj81BKx8bMuJzBUBCg+4wtWj7qw+IPM69RtPzu4oqc1E/XredpmGQ6whf+p"
+ "9JLzdal9hg60BChSCIOUnf28QtOtGYZAaIpv4T9BNJVUtJrMMdzNiEU5gW9etKyP"
+ "sfGmBFEEQ71+mvtT2LhSibzEjuW/5vIBN9EKCH6254ceKhClmccQr40NOeIGERT9"
+ "0FVF7BzIq0CTJH93J14HQ//tEXGC6qnHeHeqrGrH01JF0WkujuECKQDTXkcgNrxP"
+ "t+E8eF7SAeBl+Y/PpbaPEqMtSC7H7oZY6YaRVVtExZMRAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "brainpool384r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIIBQAIBATA8BgcqhkjOPQEBAjEAjLkegqM4bSgPXW9+UOZB3xUvcQntVFa0ErHa"
+ "GX+3ESOs06cpkB0acYdHABMxB+xTMGQEMHvDgsY9jBUMPHIICs4Fr6DCvqKOT7In"
+ "hxORZe+6kfkPiqWBSlA61OsEqMfdIs4oJgQwBKjH3SLOKCaLObVUFvBEfC+3feEH"
+ "3NKmLogOpT7rYtV8tDkCldvJlDq3hpb6UEwRBGEEHRxk8GjPRf+ipjqBt8E/a4hH"
+ "o+d+8U/j23/K/gy9EOjoJuA0NtZGqu+HsuJH1K8eir4ddSD5wqRcseuOlc/VUmK3"
+ "Cyn+7Fhk4ZwFT/mRKSgORkYhd5GBEUKCA0EmPFMVAjEAjLkegqM4bSgPXW9+UOZB"
+ "3xUvcQntVFazHxZubKwEJafPOrava3/DEDuIMgLpBGVlAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "brainpool512r1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIIBogIBATBMBgcqhkjOPQEBAkEAqt2duNvpxIs/1OauM8n8B8swjbOzydIO1mOc"
+ "ynAzCHF9TZsAm8ZoQq7NoSrmo4DmKIH/Ly2CxoUoqmBWWDpI8zCBhARAeDCjMYtg"
+ "O4niMnFFrCNMxZTL3Y09+RYQqDRByuqYY7wt7V1aqCU6oQou8cmLmsi1fxEXpyvy"
+ "x7nnwaxNd/yUygRAPfkWEKg0QcrqmGO8Le1dWqglOqEKLvHJi5rItX8RF6cr8se5"
+ "58GsTXf8lMrcCD5nmEBQt1665d0oCb1jgBb3IwSBgQSBruS92C7ZZFohMi6cTGqT"
+ "he2fcLXZFsG0O2Lu9NAJjv87H3ji0NSNUNFoe5O5fV98bVBHQGpeaIs1Igm8ufgi"
+ "fd44XVZjMuzA6r+pz3gi/fIJ9wAkpXsaoADFW4gfgRGy3N5JSl9IXlvKS9iKJ2Ou"
+ "0corL6jwVAZ4zR4POtgIkgJBAKrdnbjb6cSLP9TmrjPJ/AfLMI2zs8nSDtZjnMpw"
+ "MwhwVT5cQUypJhlBhmEZf6wQRx2x04EIXdrdtYeWgpypAGkCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "x962_p192v2")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY"
+ "/////////////////////v/////////8BBjMItbfuVxrJeScDWNkpOWYDDk6ohZo"
+ "2VMEMQTuorrn4Ul4QvLed2nP6cmJwHKtaW9IA0pldNEdabbsemcruCoIPfLysIR9"
+ "6XCy3hUCGQD///////////////5fsack3IBBhkjY3TECAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "x962_p192v3")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY"
+ "/////////////////////v/////////8BBgiEj3COVoFyqdCPa7MyUdgp9RiJWvV"
+ "aRYEMQR9KXeBAMZaHaF4NxZYjc4ri0rujiKPGJY4qQ8iY3M3M0tJ3LZqbcj5l4rK"
+ "dkipQ7ACGQD///////////////96YtAxyD9ClPZA7BMCAQE="
+ "-----END EC PARAMETERS-----";
+
+ if(name == "x962_p239v1")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////"
+ "/zBABB5///////////////9///////+AAAAAAAB///////wEHmsBbDvc8YlB0NZU"
+ "khR1ynGp2y+yfR03eWGFwpQsCgQ9BA/6ljzcqIFszDO4ZCvt+QXD01hXPT8n+707"
+ "PLmqr33r6OTpCl2ubkBUylMLoEZUs2gYziJrOfzLewLxrgIef///////////////"
+ "f///nl6an12QcfvRUiaIkJ0LAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "x962_p239v2")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////"
+ "/zBABB5///////////////9///////+AAAAAAAB///////wEHmF/q2gyV2y7/tUN"
+ "mfAknD/uWLlLoAOMeuhMjIMvLAQ9BDivCdmHJ3BRIMkhu16eJilqPNzy81dXoOr9"
+ "h7gw51sBJeTb6g7HIG2g/AHZsIEyn7VV3m70YCN9/4vkugIef///////////////"
+ "gAAAz6foWUN31BTAOCG8WCBjAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "x962_p239v3")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////"
+ "/zBABB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZUsfTL"
+ "A9anUKMMJQEC1JiHF9m6FattPgQ9BGdoro4Yu5LPzwBclJqixtlIU9DmYLv4VLHJ"
+ "UF/pWhYH5omPOQwGvB1VK60ibztvz+SLboGEma8Y4+1s8wIef///////////////"
+ "f///l13rQbOmBXw8QyFGUmVRAgEB"
+ "-----END EC PARAMETERS-----";
+
+ if(name == "gost_256A")
+ return
+ "-----BEGIN EC PARAMETERS-----"
+ "MIHgAgEBMCwGByqGSM49AQECIQD/////////////////////////////////////"
+ "///9lzBEBCD////////////////////////////////////////9lAQgAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKYEQQQAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAY2R5HHgmJzaJ99QWkU/K3Y1KU8t3yPjsSKsyZyenx4UAiEA"
+ "/////////////////////2xhEHCZWtEARYQbCbdhuJMCAQE="
+ "-----END EC PARAMETERS-----";
+
+ return nullptr;
+ }
+
+}
diff --git a/src/lib/pubkey/ecc_key/ecc_key.cpp b/src/lib/pubkey/ecc_key/ecc_key.cpp
new file mode 100644
index 000000000..c9d4d62fe
--- /dev/null
+++ b/src/lib/pubkey/ecc_key/ecc_key.cpp
@@ -0,0 +1,148 @@
+/*
+* ECC Key implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* Falko Strenzke, FlexSecure GmbH
+* 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ecc_key.h>
+#include <botan/x509_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>
+
+namespace Botan {
+
+size_t EC_PublicKey::estimated_strength() const
+ {
+ return domain().get_curve().get_p().bits() / 2;
+ }
+
+EC_PublicKey::EC_PublicKey(const EC_Group& dom_par,
+ const PointGFp& pub_point) :
+ domain_params(dom_par), public_key(pub_point),
+ domain_encoding(EC_DOMPAR_ENC_EXPLICIT)
+ {
+ if(domain().get_curve() != public_point().get_curve())
+ throw Invalid_Argument("EC_PublicKey: curve mismatch in constructor");
+ }
+
+EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits)
+ {
+ domain_params = EC_Group(alg_id.parameters);
+ domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+
+ public_key = OS2ECP(key_bits, domain().get_curve());
+ }
+
+bool EC_PublicKey::check_key(RandomNumberGenerator&,
+ bool) const
+ {
+ return public_point().on_the_curve();
+ }
+
+AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const
+ {
+ return AlgorithmIdentifier(get_oid(), DER_domain());
+ }
+
+std::vector<byte> EC_PublicKey::x509_subject_public_key() const
+ {
+ return unlock(EC2OSP(public_point(), PointGFp::COMPRESSED));
+ }
+
+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) && (domain_params.get_oid() == ""))
+ throw Invalid_Argument("Invalid encoding form OID specified for "
+ "EC-key object whose corresponding domain "
+ "parameters are without oid");
+
+ domain_encoding = form;
+ }
+
+const BigInt& EC_PrivateKey::private_value() const
+ {
+ if(private_key == 0)
+ throw Invalid_State("EC_PrivateKey::private_value - uninitialized");
+
+ return private_key;
+ }
+
+/**
+* EC_PrivateKey constructor
+*/
+EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Group& ec_group,
+ const BigInt& x)
+ {
+ domain_params = ec_group;
+ domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+
+ if(x == 0)
+ private_key = BigInt::random_integer(rng, 1, domain().get_order());
+ else
+ private_key = x;
+
+ public_key = domain().get_base_point() * private_key;
+
+ BOTAN_ASSERT(public_key.on_the_curve(),
+ "Generated public key point was on the curve");
+ }
+
+secure_vector<byte> EC_PrivateKey::pkcs8_private_key() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(static_cast<size_t>(1))
+ .encode(BigInt::encode_1363(private_key, private_key.bytes()),
+ OCTET_STRING)
+ .end_cons()
+ .get_contents();
+ }
+
+EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits)
+ {
+ domain_params = EC_Group(alg_id.parameters);
+ domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+
+ OID key_parameters;
+ secure_vector<byte> 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(private_key)
+ .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE)
+ .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE)
+ .end_cons();
+
+ if(!key_parameters.empty() && key_parameters != alg_id.oid)
+ throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match");
+
+ if(public_key_bits.empty())
+ {
+ public_key = domain().get_base_point() * private_key;
+
+ BOTAN_ASSERT(public_key.on_the_curve(),
+ "Public point derived from loaded key was on the curve");
+ }
+ else
+ {
+ public_key = OS2ECP(public_key_bits, domain().get_curve());
+ // OS2ECP verifies that the point is on the curve
+ }
+ }
+
+}
diff --git a/src/lib/pubkey/ecc_key/ecc_key.h b/src/lib/pubkey/ecc_key/ecc_key.h
new file mode 100644
index 000000000..de980608a
--- /dev/null
+++ b/src/lib/pubkey/ecc_key/ecc_key.h
@@ -0,0 +1,121 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECC_PUBLIC_KEY_BASE_H__
+#define BOTAN_ECC_PUBLIC_KEY_BASE_H__
+
+#include <botan/ec_group.h>
+#include <botan/pk_keys.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.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_DLL EC_PublicKey : public virtual Public_Key
+ {
+ public:
+ EC_PublicKey(const EC_Group& dom_par,
+ const PointGFp& pub_point);
+
+ EC_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits);
+
+ /**
+ * 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 public_key; }
+
+ AlgorithmIdentifier algorithm_identifier() const;
+
+ std::vector<byte> x509_subject_public_key() const;
+
+ bool check_key(RandomNumberGenerator& rng,
+ bool strong) const;
+
+ /**
+ * 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 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);
+
+ /**
+ * Return the DER encoding of this keys domain in whatever format
+ * is preset for this particular key
+ */
+ std::vector<byte> 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 domain_encoding; }
+
+ size_t estimated_strength() const override;
+
+ protected:
+ EC_PublicKey() : domain_encoding(EC_DOMPAR_ENC_EXPLICIT) {}
+
+ EC_Group domain_params;
+ PointGFp public_key;
+ EC_Group_Encoding domain_encoding;
+ };
+
+/**
+* This abstract class represents ECC private keys
+*/
+class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ EC_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Group& domain,
+ const BigInt& private_key);
+
+ EC_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits);
+
+ secure_vector<byte> pkcs8_private_key() const;
+
+ /**
+ * Get the private key value of this key object.
+ * @result the private key value of this key object
+ */
+ const BigInt& private_value() const;
+ protected:
+ EC_PrivateKey() {}
+
+ BigInt private_key;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/ecc_key/info.txt b/src/lib/pubkey/ecc_key/info.txt
new file mode 100644
index 000000000..6d6d5f0e9
--- /dev/null
+++ b/src/lib/pubkey/ecc_key/info.txt
@@ -0,0 +1,10 @@
+define ECC_PUBLIC_KEY_CRYPTO 20131128
+
+<requires>
+alloc
+asn1
+bigint
+ec_gfp
+ec_group
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/ecdh/ecdh.cpp b/src/lib/pubkey/ecdh/ecdh.cpp
new file mode 100644
index 000000000..0f93a0f97
--- /dev/null
+++ b/src/lib/pubkey/ecdh/ecdh.cpp
@@ -0,0 +1,35 @@
+/*
+* ECDH implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* 2007 Falko Strenzke, FlexSecure GmbH
+* 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ecdh.h>
+
+namespace Botan {
+
+ECDH_KA_Operation::ECDH_KA_Operation(const ECDH_PrivateKey& key) :
+ curve(key.domain().get_curve()),
+ cofactor(key.domain().get_cofactor())
+ {
+ l_times_priv = inverse_mod(cofactor, key.domain().get_order()) *
+ key.private_value();
+ }
+
+secure_vector<byte> ECDH_KA_Operation::agree(const byte w[], size_t w_len)
+ {
+ PointGFp point = OS2ECP(w, w_len, curve);
+
+ PointGFp S = (cofactor * point) * l_times_priv;
+
+ BOTAN_ASSERT(S.on_the_curve(),
+ "ECDH agreed value was on the curve");
+
+ return BigInt::encode_1363(S.get_affine_x(),
+ curve.get_p().bytes());
+ }
+
+}
diff --git a/src/lib/pubkey/ecdh/ecdh.h b/src/lib/pubkey/ecdh/ecdh.h
new file mode 100644
index 000000000..0c5d4e010
--- /dev/null
+++ b/src/lib/pubkey/ecdh/ecdh.h
@@ -0,0 +1,107 @@
+/*
+* ECDH
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDH_KEY_H__
+#define BOTAN_ECDH_KEY_H__
+
+#include <botan/ecc_key.h>
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+/**
+* This class represents ECDH Public Keys.
+*/
+class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey
+ {
+ public:
+
+ ECDH_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& 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 { return "ECDH"; }
+
+ /**
+ * Get the maximum number of bits allowed to be fed to this key.
+ * This is the bitlength of the order of the base point.
+
+ * @return maximum number of input bits
+ */
+ size_t max_input_bits() const { return domain().get_order().bits(); }
+
+ /**
+ * @return public point value
+ */
+ std::vector<byte> public_value() const
+ { return unlock(EC2OSP(public_point(), PointGFp::UNCOMPRESSED)); }
+
+ protected:
+ ECDH_PublicKey() {}
+ };
+
+/**
+* This class represents ECDH Private Keys.
+*/
+class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey,
+ public EC_PrivateKey,
+ public PK_Key_Agreement_Key
+ {
+ public:
+
+ ECDH_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& 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<byte> public_value() const
+ { return ECDH_PublicKey::public_value(); }
+ };
+
+/**
+* ECDH operation
+*/
+class BOTAN_DLL ECDH_KA_Operation : public PK_Ops::Key_Agreement
+ {
+ public:
+ ECDH_KA_Operation(const ECDH_PrivateKey& key);
+
+ secure_vector<byte> agree(const byte w[], size_t w_len);
+ private:
+ const CurveGFp& curve;
+ const BigInt& cofactor;
+ BigInt l_times_priv;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/ecdh/info.txt b/src/lib/pubkey/ecdh/info.txt
new file mode 100644
index 000000000..9277aca9b
--- /dev/null
+++ b/src/lib/pubkey/ecdh/info.txt
@@ -0,0 +1,10 @@
+define ECDH 20131128
+
+<requires>
+alloc
+asn1
+ec_group
+ecc_key
+libstate
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp
new file mode 100644
index 000000000..6ff082649
--- /dev/null
+++ b/src/lib/pubkey/ecdsa/ecdsa.cpp
@@ -0,0 +1,97 @@
+/*
+* ECDSA implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* 2007 Falko Strenzke, FlexSecure GmbH
+* 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ecdsa.h>
+#include <botan/keypair.h>
+
+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-1)");
+ }
+
+ECDSA_Signature_Operation::ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa) :
+ base_point(ecdsa.domain().get_base_point()),
+ order(ecdsa.domain().get_order()),
+ x(ecdsa.private_value()),
+ mod_order(order)
+ {
+ }
+
+secure_vector<byte>
+ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ rng.add_entropy(msg, msg_len);
+
+ BigInt m(msg, msg_len);
+
+ BigInt r = 0, s = 0;
+
+ while(r == 0 || s == 0)
+ {
+ // This contortion is necessary for the tests
+ BigInt k;
+ k.randomize(rng, order.bits());
+
+ while(k >= order)
+ k.randomize(rng, order.bits() - 1);
+
+ PointGFp k_times_P = base_point * k;
+ r = mod_order.reduce(k_times_P.get_affine_x());
+ s = mod_order.multiply(inverse_mod(k, order), mul_add(x, r, m));
+ }
+
+ secure_vector<byte> output(2*order.bytes());
+ r.binary_encode(&output[output.size() / 2 - r.bytes()]);
+ s.binary_encode(&output[output.size() - s.bytes()]);
+ return output;
+ }
+
+ECDSA_Verification_Operation::ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa) :
+ base_point(ecdsa.domain().get_base_point()),
+ public_point(ecdsa.public_point()),
+ order(ecdsa.domain().get_order())
+ {
+ }
+
+bool ECDSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len)
+ {
+ if(sig_len != order.bytes()*2)
+ return false;
+
+ BigInt e(msg, msg_len);
+
+ BigInt r(sig, sig_len / 2);
+ BigInt s(sig + sig_len / 2, sig_len / 2);
+
+ if(r <= 0 || r >= order || s <= 0 || s >= order)
+ return false;
+
+ BigInt w = inverse_mod(s, order);
+
+ PointGFp R = w * multi_exponentiate(base_point, e,
+ public_point, r);
+
+ if(R.is_zero())
+ return false;
+
+ return (R.get_affine_x() % order == r);
+ }
+
+}
diff --git a/src/lib/pubkey/ecdsa/ecdsa.h b/src/lib/pubkey/ecdsa/ecdsa.h
new file mode 100644
index 000000000..e37fa1562
--- /dev/null
+++ b/src/lib/pubkey/ecdsa/ecdsa.h
@@ -0,0 +1,138 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_KEY_H__
+#define BOTAN_ECDSA_KEY_H__
+
+#include <botan/ecc_key.h>
+#include <botan/reducer.h>
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+/**
+* This class represents ECDSA Public Keys.
+*/
+class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey
+ {
+ public:
+
+ /**
+ * 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
+ */
+ ECDSA_PublicKey(const EC_Group& dom_par,
+ const PointGFp& public_point) :
+ EC_PublicKey(dom_par, public_point) {}
+
+ ECDSA_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits) :
+ EC_PublicKey(alg_id, key_bits) {}
+
+ /**
+ * Get this keys algorithm name.
+ * @result this keys algorithm name ("ECDSA")
+ */
+ std::string algo_name() const { return "ECDSA"; }
+
+ /**
+ * Get the maximum number of bits allowed to be fed to this key.
+ * This is the bitlength of the order of the base point.
+ * @result the maximum number of input bits
+ */
+ size_t max_input_bits() const { return domain().get_order().bits(); }
+
+ size_t message_parts() const { return 2; }
+
+ size_t message_part_size() const
+ { return domain().get_order().bytes(); }
+
+ protected:
+ ECDSA_PublicKey() {}
+ };
+
+/**
+* This class represents ECDSA Private Keys
+*/
+class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey,
+ public EC_PrivateKey
+ {
+ public:
+
+ /**
+ * Load a private key
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits PKCS #8 structure
+ */
+ ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& 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, generate a ney 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;
+ };
+
+/**
+* ECDSA signature operation
+*/
+class BOTAN_DLL ECDSA_Signature_Operation : public PK_Ops::Signature
+ {
+ public:
+ ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa);
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return order.bytes(); }
+ size_t max_input_bits() const { return order.bits(); }
+
+ private:
+ const PointGFp& base_point;
+ const BigInt& order;
+ const BigInt& x;
+ Modular_Reducer mod_order;
+ };
+
+/**
+* ECDSA verification operation
+*/
+class BOTAN_DLL ECDSA_Verification_Operation : public PK_Ops::Verification
+ {
+ public:
+ ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa);
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return order.bytes(); }
+ size_t max_input_bits() const { return order.bits(); }
+
+ bool with_recovery() const { return false; }
+
+ bool verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len);
+ private:
+ const PointGFp& base_point;
+ const PointGFp& public_point;
+ const BigInt& order;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/ecdsa/info.txt b/src/lib/pubkey/ecdsa/info.txt
new file mode 100644
index 000000000..fcf688402
--- /dev/null
+++ b/src/lib/pubkey/ecdsa/info.txt
@@ -0,0 +1,9 @@
+define ECDSA 20131128
+
+<requires>
+asn1
+ec_group
+ecc_key
+numbertheory
+rng
+</requires>
diff --git a/src/lib/pubkey/elgamal/elgamal.cpp b/src/lib/pubkey/elgamal/elgamal.cpp
new file mode 100644
index 000000000..c8a9ba9d0
--- /dev/null
+++ b/src/lib/pubkey/elgamal/elgamal.cpp
@@ -0,0 +1,135 @@
+/*
+* ElGamal
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/elgamal.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/workfactor.h>
+
+namespace Botan {
+
+/*
+* ElGamal_PublicKey Constructor
+*/
+ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ }
+
+/*
+* ElGamal_PrivateKey Constructor
+*/
+ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ group = grp;
+ x = x_arg;
+
+ if(x == 0)
+ x.randomize(rng, 2 * dl_work_factor(group_p().bits()));
+
+ y = power_mod(group_g(), x, group_p());
+
+ if(x_arg == 0)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng) :
+ DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
+ {
+ y = power_mod(group_g(), x, group_p());
+ load_check(rng);
+ }
+
+/*
+* Check Private ElGamal Parameters
+*/
+bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ if(!DL_Scheme_PrivateKey::check_key(rng, strong))
+ return false;
+
+ if(!strong)
+ return true;
+
+ return KeyPair::encryption_consistency_check(rng, *this, "EME1(SHA-1)");
+ }
+
+ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key)
+ {
+ const BigInt& p = key.group_p();
+
+ powermod_g_p = Fixed_Base_Power_Mod(key.group_g(), p);
+ powermod_y_p = Fixed_Base_Power_Mod(key.get_y(), p);
+ mod_p = Modular_Reducer(p);
+ }
+
+secure_vector<byte>
+ElGamal_Encryption_Operation::encrypt(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ const BigInt& p = mod_p.get_modulus();
+
+ BigInt m(msg, msg_len);
+
+ if(m >= p)
+ throw Invalid_Argument("ElGamal encryption: Input is too large");
+
+ BigInt k(rng, 2 * dl_work_factor(p.bits()));
+
+ BigInt a = powermod_g_p(k);
+ BigInt b = mod_p.multiply(m, powermod_y_p(k));
+
+ secure_vector<byte> output(2*p.bytes());
+ a.binary_encode(&output[p.bytes() - a.bytes()]);
+ b.binary_encode(&output[output.size() / 2 + (p.bytes() - b.bytes())]);
+ return output;
+ }
+
+ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key,
+ RandomNumberGenerator& rng)
+ {
+ const BigInt& p = key.group_p();
+
+ powermod_x_p = Fixed_Exponent_Power_Mod(key.get_x(), p);
+ mod_p = Modular_Reducer(p);
+
+ BigInt k(rng, p.bits() - 1);
+ blinder = Blinder(k, powermod_x_p(k), p);
+ }
+
+secure_vector<byte>
+ElGamal_Decryption_Operation::decrypt(const byte msg[], size_t msg_len)
+ {
+ const BigInt& p = mod_p.get_modulus();
+
+ const size_t p_bytes = p.bytes();
+
+ if(msg_len != 2 * p_bytes)
+ throw Invalid_Argument("ElGamal decryption: Invalid message");
+
+ BigInt a(msg, p_bytes);
+ BigInt b(msg + p_bytes, p_bytes);
+
+ if(a >= p || b >= p)
+ throw Invalid_Argument("ElGamal decryption: Invalid message");
+
+ a = blinder.blind(a);
+
+ BigInt r = mod_p.multiply(b, inverse_mod(powermod_x_p(a), p));
+
+ return BigInt::encode_locked(blinder.unblind(r));
+ }
+
+}
diff --git a/src/lib/pubkey/elgamal/elgamal.h b/src/lib/pubkey/elgamal/elgamal.h
new file mode 100644
index 000000000..9566bcca6
--- /dev/null
+++ b/src/lib/pubkey/elgamal/elgamal.h
@@ -0,0 +1,96 @@
+/*
+* ElGamal
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ELGAMAL_H__
+#define BOTAN_ELGAMAL_H__
+
+#include <botan/dl_algo.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+#include <botan/blinding.h>
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+/**
+* ElGamal Public Key
+*/
+class BOTAN_DLL ElGamal_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "ElGamal"; }
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
+
+ size_t max_input_bits() const { return (group_p().bits() - 1); }
+
+ ElGamal_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits) :
+ DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
+ {}
+
+ ElGamal_PublicKey(const DL_Group& group, const BigInt& y);
+ protected:
+ ElGamal_PublicKey() {}
+ };
+
+/**
+* ElGamal Private Key
+*/
+class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng);
+
+ ElGamal_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& group,
+ const BigInt& priv_key = 0);
+ };
+
+/**
+* ElGamal encryption operation
+*/
+class BOTAN_DLL ElGamal_Encryption_Operation : public PK_Ops::Encryption
+ {
+ public:
+ size_t max_input_bits() const { return mod_p.get_modulus().bits() - 1; }
+
+ ElGamal_Encryption_Operation(const ElGamal_PublicKey& key);
+
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+
+ private:
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p;
+ };
+
+/**
+* ElGamal decryption operation
+*/
+class BOTAN_DLL ElGamal_Decryption_Operation : public PK_Ops::Decryption
+ {
+ public:
+ size_t max_input_bits() const { return mod_p.get_modulus().bits() - 1; }
+
+ ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key,
+ RandomNumberGenerator& rng);
+
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len);
+ private:
+ Fixed_Exponent_Power_Mod powermod_x_p;
+ Modular_Reducer mod_p;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/elgamal/info.txt b/src/lib/pubkey/elgamal/info.txt
new file mode 100644
index 000000000..4fe20e828
--- /dev/null
+++ b/src/lib/pubkey/elgamal/info.txt
@@ -0,0 +1,9 @@
+define ELGAMAL 20131128
+
+<requires>
+dl_algo
+dl_group
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/gost_3410/gost_3410.cpp b/src/lib/pubkey/gost_3410/gost_3410.cpp
new file mode 100644
index 000000000..9a1e6d85b
--- /dev/null
+++ b/src/lib/pubkey/gost_3410/gost_3410.cpp
@@ -0,0 +1,176 @@
+/*
+* GOST 34.10-2001 implemenation
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/gost_3410.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+std::vector<byte> GOST_3410_PublicKey::x509_subject_public_key() const
+ {
+ // Trust CryptoPro to come up with something obnoxious
+ const BigInt x = public_point().get_affine_x();
+ const BigInt y = public_point().get_affine_y();
+
+ size_t part_size = std::max(x.bytes(), y.bytes());
+
+ std::vector<byte> bits(2*part_size);
+
+ x.binary_encode(&bits[part_size - x.bytes()]);
+ y.binary_encode(&bits[2*part_size - y.bytes()]);
+
+ // Keys are stored in little endian format (WTF)
+ for(size_t i = 0; i != part_size / 2; ++i)
+ {
+ std::swap(bits[i], bits[part_size-1-i]);
+ std::swap(bits[part_size+i], bits[2*part_size-1-i]);
+ }
+
+ return DER_Encoder().encode(bits, OCTET_STRING).get_contents_unlocked();
+ }
+
+AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
+ {
+ std::vector<byte> params =
+ DER_Encoder().start_cons(SEQUENCE)
+ .encode(OID(domain().get_oid()))
+ .end_cons()
+ .get_contents_unlocked();
+
+ return AlgorithmIdentifier(get_oid(), params);
+ }
+
+GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits)
+ {
+ OID ecc_param_id;
+
+ // Also includes hash and cipher OIDs... brilliant design guys
+ BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id);
+
+ domain_params = EC_Group(ecc_param_id);
+
+ secure_vector<byte> bits;
+ BER_Decoder(key_bits).decode(bits, OCTET_STRING);
+
+ const size_t part_size = bits.size() / 2;
+
+ // Keys are stored in little endian format (WTF)
+ for(size_t i = 0; i != part_size / 2; ++i)
+ {
+ std::swap(bits[i], bits[part_size-1-i]);
+ std::swap(bits[part_size+i], bits[2*part_size-1-i]);
+ }
+
+ BigInt x(&bits[0], part_size);
+ BigInt y(&bits[part_size], part_size);
+
+ public_key = PointGFp(domain().get_curve(), x, y);
+
+ BOTAN_ASSERT(public_key.on_the_curve(),
+ "Loaded GOST 34.10 public key is on the curve");
+ }
+
+namespace {
+
+BigInt decode_le(const byte msg[], size_t msg_len)
+ {
+ secure_vector<byte> msg_le(msg, msg + msg_len);
+
+ for(size_t i = 0; i != msg_le.size() / 2; ++i)
+ std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
+
+ return BigInt(&msg_le[0], msg_le.size());
+ }
+
+}
+
+GOST_3410_Signature_Operation::GOST_3410_Signature_Operation(
+ const GOST_3410_PrivateKey& gost_3410) :
+
+ base_point(gost_3410.domain().get_base_point()),
+ order(gost_3410.domain().get_order()),
+ x(gost_3410.private_value())
+ {
+ }
+
+secure_vector<byte>
+GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ BigInt k;
+ do
+ k.randomize(rng, order.bits()-1);
+ while(k >= order);
+
+ BigInt e = decode_le(msg, msg_len);
+
+ e %= order;
+ if(e == 0)
+ e = 1;
+
+ PointGFp k_times_P = base_point * k;
+
+ BOTAN_ASSERT(k_times_P.on_the_curve(),
+ "GOST 34.10 k*g is on the curve");
+
+ BigInt r = k_times_P.get_affine_x() % order;
+
+ BigInt s = (r*x + k*e) % order;
+
+ if(r == 0 || s == 0)
+ throw Invalid_State("GOST 34.10: r == 0 || s == 0");
+
+ secure_vector<byte> output(2*order.bytes());
+ s.binary_encode(&output[output.size() / 2 - s.bytes()]);
+ r.binary_encode(&output[output.size() - r.bytes()]);
+ return output;
+ }
+
+GOST_3410_Verification_Operation::GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost) :
+ base_point(gost.domain().get_base_point()),
+ public_point(gost.public_point()),
+ order(gost.domain().get_order())
+ {
+ }
+
+bool GOST_3410_Verification_Operation::verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len)
+ {
+ if(sig_len != order.bytes()*2)
+ return false;
+
+ BigInt e = decode_le(msg, msg_len);
+
+ BigInt s(sig, sig_len / 2);
+ BigInt r(sig + sig_len / 2, sig_len / 2);
+
+ if(r <= 0 || r >= order || s <= 0 || s >= order)
+ return false;
+
+ e %= order;
+ if(e == 0)
+ e = 1;
+
+ BigInt v = inverse_mod(e, order);
+
+ BigInt z1 = (s*v) % order;
+ BigInt z2 = (-r*v) % order;
+
+ PointGFp R = multi_exponentiate(base_point, z1,
+ public_point, z2);
+
+ if(R.is_zero())
+ return false;
+
+ return (R.get_affine_x() == r);
+ }
+
+}
diff --git a/src/lib/pubkey/gost_3410/gost_3410.h b/src/lib/pubkey/gost_3410/gost_3410.h
new file mode 100644
index 000000000..6b1506b10
--- /dev/null
+++ b/src/lib/pubkey/gost_3410/gost_3410.h
@@ -0,0 +1,139 @@
+/*
+* GOST 34.10-2001
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_GOST_3410_KEY_H__
+#define BOTAN_GOST_3410_KEY_H__
+
+#include <botan/ecc_key.h>
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+/**
+* GOST-34.10 Public Key
+*/
+class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey
+ {
+ public:
+
+ /**
+ * 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
+ */
+ GOST_3410_PublicKey(const EC_Group& dom_par,
+ const PointGFp& public_point) :
+ EC_PublicKey(dom_par, public_point) {}
+
+ /**
+ * Construct from X.509 algorithm id and subject public key bits
+ */
+ GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits);
+
+ /**
+ * Get this keys algorithm name.
+ * @result this keys algorithm name
+ */
+ std::string algo_name() const { return "GOST-34.10"; }
+
+ AlgorithmIdentifier algorithm_identifier() const;
+
+ std::vector<byte> x509_subject_public_key() const;
+
+ /**
+ * Get the maximum number of bits allowed to be fed to this key.
+ * This is the bitlength of the order of the base point.
+
+ * @result the maximum number of input bits
+ */
+ size_t max_input_bits() const { return domain().get_order().bits(); }
+
+ size_t message_parts() const { return 2; }
+
+ size_t message_part_size() const
+ { return domain().get_order().bytes(); }
+
+ protected:
+ GOST_3410_PublicKey() {}
+ };
+
+/**
+* GOST-34.10 Private Key
+*/
+class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey,
+ public EC_PrivateKey
+ {
+ public:
+
+ GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& 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
+ */
+ GOST_3410_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Group& domain,
+ const BigInt& x = 0) :
+ EC_PrivateKey(rng, domain, x) {}
+
+ AlgorithmIdentifier pkcs8_algorithm_identifier() const
+ { return EC_PublicKey::algorithm_identifier(); }
+ };
+
+/**
+* GOST-34.10 signature operation
+*/
+class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature
+ {
+ public:
+ GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410);
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return order.bytes(); }
+ size_t max_input_bits() const { return order.bits(); }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+
+ private:
+ const PointGFp& base_point;
+ const BigInt& order;
+ const BigInt& x;
+ };
+
+/**
+* GOST-34.10 verification operation
+*/
+class BOTAN_DLL GOST_3410_Verification_Operation : public PK_Ops::Verification
+ {
+ public:
+ GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost);
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return order.bytes(); }
+ size_t max_input_bits() const { return order.bits(); }
+
+ bool with_recovery() const { return false; }
+
+ bool verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len);
+ private:
+ const PointGFp& base_point;
+ const PointGFp& public_point;
+ const BigInt& order;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/gost_3410/info.txt b/src/lib/pubkey/gost_3410/info.txt
new file mode 100644
index 000000000..63521d3dd
--- /dev/null
+++ b/src/lib/pubkey/gost_3410/info.txt
@@ -0,0 +1,13 @@
+define GOST_34_10_2001 20131128
+
+load_on auto
+
+<requires>
+alloc
+asn1
+ec_group
+ecc_key
+libstate
+numbertheory
+rng
+</requires>
diff --git a/src/lib/pubkey/if_algo/if_algo.cpp b/src/lib/pubkey/if_algo/if_algo.cpp
new file mode 100644
index 000000000..f6aeb69db
--- /dev/null
+++ b/src/lib/pubkey/if_algo/if_algo.cpp
@@ -0,0 +1,143 @@
+/*
+* IF Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/if_algo.h>
+#include <botan/numthry.h>
+#include <botan/workfactor.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+size_t IF_Scheme_PublicKey::estimated_strength() const
+ {
+ return dl_work_factor(n.bits());
+ }
+
+AlgorithmIdentifier IF_Scheme_PublicKey::algorithm_identifier() const
+ {
+ return AlgorithmIdentifier(get_oid(),
+ AlgorithmIdentifier::USE_NULL_PARAM);
+ }
+
+std::vector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(n)
+ .encode(e)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+
+IF_Scheme_PublicKey::IF_Scheme_PublicKey(const AlgorithmIdentifier&,
+ const secure_vector<byte>& key_bits)
+ {
+ BER_Decoder(key_bits)
+ .start_cons(SEQUENCE)
+ .decode(n)
+ .decode(e)
+ .verify_end()
+ .end_cons();
+ }
+
+/*
+* Check IF Scheme Public Parameters
+*/
+bool IF_Scheme_PublicKey::check_key(RandomNumberGenerator&, bool) const
+ {
+ if(n < 35 || n.is_even() || e < 2)
+ return false;
+ return true;
+ }
+
+secure_vector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(static_cast<size_t>(0))
+ .encode(n)
+ .encode(e)
+ .encode(d)
+ .encode(p)
+ .encode(q)
+ .encode(d1)
+ .encode(d2)
+ .encode(c)
+ .end_cons()
+ .get_contents();
+ }
+
+IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
+ const AlgorithmIdentifier&,
+ const secure_vector<byte>& key_bits)
+ {
+ BER_Decoder(key_bits)
+ .start_cons(SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #1 key format version")
+ .decode(n)
+ .decode(e)
+ .decode(d)
+ .decode(p)
+ .decode(q)
+ .decode(d1)
+ .decode(d2)
+ .decode(c)
+ .end_cons();
+
+ load_check(rng);
+ }
+
+IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
+ const BigInt& prime1,
+ const BigInt& prime2,
+ const BigInt& exp,
+ const BigInt& d_exp,
+ const BigInt& mod)
+ {
+ p = prime1;
+ q = prime2;
+ e = exp;
+ d = d_exp;
+ n = mod.is_nonzero() ? mod : p * q;
+
+ if(d == 0)
+ {
+ BigInt inv_for_d = lcm(p - 1, q - 1);
+ if(e.is_even())
+ inv_for_d >>= 1;
+
+ d = inverse_mod(e, inv_for_d);
+ }
+
+ d1 = d % (p - 1);
+ d2 = d % (q - 1);
+ c = inverse_mod(q, p);
+
+ load_check(rng);
+ }
+
+/*
+* Check IF Scheme Private Parameters
+*/
+bool IF_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ if(n < 35 || n.is_even() || e < 2 || d < 2 || p < 3 || q < 3 || p*q != n)
+ return false;
+
+ if(!strong)
+ return true;
+
+ if(d1 != d % (p - 1) || d2 != d % (q - 1) || c != inverse_mod(q, p))
+ return false;
+ if(!check_prime(p, rng) || !check_prime(q, rng))
+ return false;
+ return true;
+ }
+
+}
diff --git a/src/lib/pubkey/if_algo/if_algo.h b/src/lib/pubkey/if_algo/if_algo.h
new file mode 100644
index 000000000..7dd6d19f0
--- /dev/null
+++ b/src/lib/pubkey/if_algo/if_algo.h
@@ -0,0 +1,108 @@
+/*
+* IF Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IF_ALGO_H__
+#define BOTAN_IF_ALGO_H__
+
+#include <botan/bigint.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/**
+* This class represents public keys
+* of integer factorization based (IF) public key schemes.
+*/
+class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key
+ {
+ public:
+ IF_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits);
+
+ IF_Scheme_PublicKey(const BigInt& n, const BigInt& e) :
+ n(n), e(e) {}
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ AlgorithmIdentifier algorithm_identifier() const;
+
+ std::vector<byte> x509_subject_public_key() const;
+
+ /**
+ * @return public modulus
+ */
+ const BigInt& get_n() const { return n; }
+
+ /**
+ * @return public exponent
+ */
+ const BigInt& get_e() const { return e; }
+
+ size_t max_input_bits() const { return (n.bits() - 1); }
+
+ size_t estimated_strength() const override;
+
+ protected:
+ IF_Scheme_PublicKey() {}
+
+ BigInt n, e;
+ };
+
+/**
+* This class represents public keys
+* of integer factorization based (IF) public key schemes.
+*/
+class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+
+ IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
+ const BigInt& prime1, const BigInt& prime2,
+ const BigInt& exp, const BigInt& d_exp,
+ const BigInt& mod);
+
+ IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits);
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get the first prime p.
+ * @return prime p
+ */
+ const BigInt& get_p() const { return p; }
+
+ /**
+ * Get the second prime q.
+ * @return prime q
+ */
+ const BigInt& get_q() const { return q; }
+
+ /**
+ * Get d with exp * d = 1 mod (p - 1, q - 1).
+ * @return d
+ */
+ const BigInt& get_d() const { return d; }
+
+ const BigInt& get_c() const { return c; }
+ const BigInt& get_d1() const { return d1; }
+ const BigInt& get_d2() const { return d2; }
+
+ secure_vector<byte> pkcs8_private_key() const;
+
+ protected:
+ IF_Scheme_PrivateKey() {}
+
+ BigInt d, p, q, d1, d2, c;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/if_algo/info.txt b/src/lib/pubkey/if_algo/info.txt
new file mode 100644
index 000000000..e4d2dbb5e
--- /dev/null
+++ b/src/lib/pubkey/if_algo/info.txt
@@ -0,0 +1,10 @@
+define IF_PUBLIC_KEY_FAMILY 20131128
+
+load_on dep
+
+<requires>
+asn1
+bigint
+libstate
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/info.txt b/src/lib/pubkey/info.txt
new file mode 100644
index 000000000..27a332b5c
--- /dev/null
+++ b/src/lib/pubkey/info.txt
@@ -0,0 +1,41 @@
+define PUBLIC_KEY_CRYPTO 20131128
+
+<source>
+blinding.cpp
+pk_algs.cpp
+pk_keys.cpp
+pkcs8.cpp
+pubkey.cpp
+workfactor.cpp
+x509_key.cpp
+</source>
+
+<header:public>
+blinding.h
+pk_keys.h
+pk_ops.h
+pkcs8.h
+pubkey.h
+x509_key.h
+workfactor.h
+</header:public>
+
+<header:internal>
+pk_algs.h
+</header:internal>
+
+<requires>
+alloc
+asn1
+bigint
+engine
+filters
+kdf
+libstate
+oid_lookup
+pbe
+pem
+pk_pad
+rng
+algo_base
+</requires>
diff --git a/src/lib/pubkey/keypair/info.txt b/src/lib/pubkey/keypair/info.txt
new file mode 100644
index 000000000..10fb2013b
--- /dev/null
+++ b/src/lib/pubkey/keypair/info.txt
@@ -0,0 +1,5 @@
+define KEYPAIR_TESTING 20131128
+
+<requires>
+libstate
+</requires>
diff --git a/src/lib/pubkey/keypair/keypair.cpp b/src/lib/pubkey/keypair/keypair.cpp
new file mode 100644
index 000000000..a8631062d
--- /dev/null
+++ b/src/lib/pubkey/keypair/keypair.cpp
@@ -0,0 +1,81 @@
+/*
+* Keypair Checks
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/keypair.h>
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+namespace KeyPair {
+
+/*
+* Check an encryption key pair for consistency
+*/
+bool encryption_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& key,
+ const std::string& padding)
+ {
+ PK_Encryptor_EME encryptor(key, padding);
+ PK_Decryptor_EME decryptor(key, padding);
+
+ /*
+ 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<byte> plaintext =
+ unlock(rng.random_vec(encryptor.maximum_input_size() - 1));
+
+ std::vector<byte> ciphertext = encryptor.encrypt(plaintext, rng);
+ if(ciphertext == plaintext)
+ return false;
+
+ std::vector<byte> decrypted = unlock(decryptor.decrypt(ciphertext));
+
+ return (plaintext == decrypted);
+ }
+
+/*
+* Check a signature key pair for consistency
+*/
+bool signature_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& key,
+ const std::string& padding)
+ {
+ PK_Signer signer(key, padding);
+ PK_Verifier verifier(key, padding);
+
+ std::vector<byte> message = unlock(rng.random_vec(16));
+
+ std::vector<byte> 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
+ ++message[0];
+
+ if(verifier.verify_message(message, signature))
+ return false;
+
+ return true;
+ }
+
+}
+
+}
diff --git a/src/lib/pubkey/keypair/keypair.h b/src/lib/pubkey/keypair/keypair.h
new file mode 100644
index 000000000..c7b128e53
--- /dev/null
+++ b/src/lib/pubkey/keypair/keypair.h
@@ -0,0 +1,47 @@
+/*
+* Keypair Checks
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#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 key the key to test
+* @param padding the encryption padding method to use
+* @return true if consistent otherwise false
+*/
+BOTAN_DLL bool
+encryption_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& 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 key the key to test
+* @param padding the signature padding method to use
+* @return true if consistent otherwise false
+*/
+BOTAN_DLL bool
+signature_consistency_check(RandomNumberGenerator& rng,
+ const Private_Key& key,
+ const std::string& padding);
+
+}
+
+}
+
+#endif
diff --git a/src/lib/pubkey/nr/info.txt b/src/lib/pubkey/nr/info.txt
new file mode 100644
index 000000000..8c2816fe7
--- /dev/null
+++ b/src/lib/pubkey/nr/info.txt
@@ -0,0 +1,9 @@
+define NYBERG_RUEPPEL 20131128
+
+<requires>
+dl_algo
+dl_group
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/nr/nr.cpp b/src/lib/pubkey/nr/nr.cpp
new file mode 100644
index 000000000..87cf3d038
--- /dev/null
+++ b/src/lib/pubkey/nr/nr.cpp
@@ -0,0 +1,143 @@
+/*
+* Nyberg-Rueppel
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/nr.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <future>
+
+namespace Botan {
+
+NR_PublicKey::NR_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits) :
+ DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
+ {
+ }
+
+/*
+* NR_PublicKey Constructor
+*/
+NR_PublicKey::NR_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ }
+
+/*
+* Create a NR private key
+*/
+NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ group = grp;
+ x = x_arg;
+
+ if(x == 0)
+ x = BigInt::random_integer(rng, 2, group_q() - 1);
+
+ y = power_mod(group_g(), x, group_p());
+
+ if(x_arg == 0)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+NR_PrivateKey::NR_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng) :
+ DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
+ {
+ y = power_mod(group_g(), x, group_p());
+
+ load_check(rng);
+ }
+
+/*
+* Check Private Nyberg-Rueppel Parameters
+*/
+bool NR_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!DL_Scheme_PrivateKey::check_key(rng, strong) || x >= group_q())
+ return false;
+
+ if(!strong)
+ return true;
+
+ return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)");
+ }
+
+NR_Signature_Operation::NR_Signature_Operation(const NR_PrivateKey& nr) :
+ q(nr.group_q()),
+ x(nr.get_x()),
+ powermod_g_p(nr.group_g(), nr.group_p()),
+ mod_q(nr.group_q())
+ {
+ }
+
+secure_vector<byte>
+NR_Signature_Operation::sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ rng.add_entropy(msg, msg_len);
+
+ BigInt f(msg, msg_len);
+
+ if(f >= q)
+ throw Invalid_Argument("NR_Signature_Operation: Input is out of range");
+
+ BigInt c, d;
+
+ while(c == 0)
+ {
+ BigInt k;
+ do
+ k.randomize(rng, q.bits());
+ while(k >= q);
+
+ c = mod_q.reduce(powermod_g_p(k) + f);
+ d = mod_q.reduce(k - x * c);
+ }
+
+ secure_vector<byte> output(2*q.bytes());
+ c.binary_encode(&output[output.size() / 2 - c.bytes()]);
+ d.binary_encode(&output[output.size() - d.bytes()]);
+ return output;
+ }
+
+NR_Verification_Operation::NR_Verification_Operation(const NR_PublicKey& nr) :
+ q(nr.group_q()), y(nr.get_y())
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(nr.group_g(), nr.group_p());
+ powermod_y_p = Fixed_Base_Power_Mod(y, nr.group_p());
+ mod_p = Modular_Reducer(nr.group_p());
+ mod_q = Modular_Reducer(nr.group_q());
+ }
+
+secure_vector<byte>
+NR_Verification_Operation::verify_mr(const byte msg[], size_t msg_len)
+ {
+ const BigInt& q = mod_q.get_modulus();
+
+ if(msg_len != 2*q.bytes())
+ throw Invalid_Argument("NR verification: Invalid signature");
+
+ BigInt c(msg, q.bytes());
+ BigInt d(msg + q.bytes(), q.bytes());
+
+ if(c.is_zero() || c >= q || d >= q)
+ throw Invalid_Argument("NR verification: Invalid signature");
+
+ auto future_y_c = std::async(std::launch::async, powermod_y_p, c);
+ BigInt g_d = powermod_g_p(d);
+
+ BigInt i = mod_p.multiply(g_d, future_y_c.get());
+ return BigInt::encode_locked(mod_q.reduce(c - i));
+ }
+
+}
diff --git a/src/lib/pubkey/nr/nr.h b/src/lib/pubkey/nr/nr.h
new file mode 100644
index 000000000..5be336a21
--- /dev/null
+++ b/src/lib/pubkey/nr/nr.h
@@ -0,0 +1,104 @@
+/*
+* Nyberg-Rueppel
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NYBERG_RUEPPEL_H__
+#define BOTAN_NYBERG_RUEPPEL_H__
+
+#include <botan/dl_algo.h>
+#include <botan/pk_ops.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+/**
+* Nyberg-Rueppel Public Key
+*/
+class BOTAN_DLL NR_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "NR"; }
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return group_q().bytes(); }
+ size_t max_input_bits() const { return (group_q().bits() - 1); }
+
+ NR_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits);
+
+ NR_PublicKey(const DL_Group& group, const BigInt& pub_key);
+ protected:
+ NR_PublicKey() {}
+ };
+
+/**
+* Nyberg-Rueppel Private Key
+*/
+class BOTAN_DLL NR_PrivateKey : public NR_PublicKey,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool strong) const;
+
+ NR_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng);
+
+ NR_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& group,
+ const BigInt& x = 0);
+ };
+
+/**
+* Nyberg-Rueppel signature operation
+*/
+class BOTAN_DLL NR_Signature_Operation : public PK_Ops::Signature
+ {
+ public:
+ NR_Signature_Operation(const NR_PrivateKey& nr);
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return q.bytes(); }
+ size_t max_input_bits() const { return (q.bits() - 1); }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+ private:
+ const BigInt& q;
+ const BigInt& x;
+ Fixed_Base_Power_Mod powermod_g_p;
+ Modular_Reducer mod_q;
+ };
+
+/**
+* Nyberg-Rueppel verification operation
+*/
+class BOTAN_DLL NR_Verification_Operation : public PK_Ops::Verification
+ {
+ public:
+ NR_Verification_Operation(const NR_PublicKey& nr);
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return q.bytes(); }
+ size_t max_input_bits() const { return (q.bits() - 1); }
+
+ bool with_recovery() const { return true; }
+
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len);
+ private:
+ const BigInt& q;
+ const BigInt& y;
+
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/pk_algs.cpp b/src/lib/pubkey/pk_algs.cpp
new file mode 100644
index 000000000..9673199e0
--- /dev/null
+++ b/src/lib/pubkey/pk_algs.cpp
@@ -0,0 +1,160 @@
+/*
+* PK Key
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/pk_algs.h>
+#include <botan/oids.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_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ #include <botan/gost_3410.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr.h>
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ #include <botan/rw.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elgamal.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ #include <botan/ecdh.h>
+#endif
+
+namespace Botan {
+
+Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits)
+ {
+ const std::string alg_name = OIDS::lookup(alg_id.oid);
+ if(alg_name == "")
+ throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string());
+
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA")
+ return new RSA_PublicKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(alg_name == "RW")
+ return new RW_PublicKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA")
+ return new DSA_PublicKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(alg_name == "DH")
+ return new DH_PublicKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ if(alg_name == "NR")
+ return new NR_PublicKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(alg_name == "ElGamal")
+ return new ElGamal_PublicKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA")
+ return new ECDSA_PublicKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ if(alg_name == "GOST-34.10")
+ return new GOST_3410_PublicKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ if(alg_name == "ECDH")
+ return new ECDH_PublicKey(alg_id, key_bits);
+#endif
+
+ return nullptr;
+ }
+
+Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng)
+ {
+ const std::string alg_name = OIDS::lookup(alg_id.oid);
+ if(alg_name == "")
+ throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string());
+
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA")
+ return new RSA_PrivateKey(alg_id, key_bits, rng);
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(alg_name == "RW")
+ return new RW_PrivateKey(alg_id, key_bits, rng);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA")
+ return new DSA_PrivateKey(alg_id, key_bits, rng);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(alg_name == "DH")
+ return new DH_PrivateKey(alg_id, key_bits, rng);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ if(alg_name == "NR")
+ return new NR_PrivateKey(alg_id, key_bits, rng);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(alg_name == "ElGamal")
+ return new ElGamal_PrivateKey(alg_id, key_bits, rng);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA")
+ return new ECDSA_PrivateKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ if(alg_name == "GOST-34.10")
+ return new GOST_3410_PrivateKey(alg_id, key_bits);
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ if(alg_name == "ECDH")
+ return new ECDH_PrivateKey(alg_id, key_bits);
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/src/lib/pubkey/pk_algs.h b/src/lib/pubkey/pk_algs.h
new file mode 100644
index 000000000..d8f24a1b8
--- /dev/null
+++ b/src/lib/pubkey/pk_algs.h
@@ -0,0 +1,24 @@
+/*
+* PK Key Factory
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_KEY_FACTORY_H__
+#define BOTAN_PK_KEY_FACTORY_H__
+
+#include <botan/pk_keys.h>
+
+namespace Botan {
+
+Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits);
+
+Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng);
+
+}
+
+#endif
diff --git a/src/lib/pubkey/pk_keys.cpp b/src/lib/pubkey/pk_keys.cpp
new file mode 100644
index 000000000..c19c676ab
--- /dev/null
+++ b/src/lib/pubkey/pk_keys.cpp
@@ -0,0 +1,55 @@
+/*
+* PK Key Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pk_keys.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+
+namespace Botan {
+
+/*
+* 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");
+ }
+ }
+
+/*
+* Run checks on a loaded public key
+*/
+void Public_Key::load_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD))
+ throw Invalid_Argument(algo_name() + ": Invalid public key");
+ }
+
+/*
+* Run checks on a loaded private key
+*/
+void Private_Key::load_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD))
+ throw Invalid_Argument(algo_name() + ": Invalid private key");
+ }
+
+/*
+* Run checks on a generated private key
+*/
+void Private_Key::gen_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE))
+ throw Self_Test_Failure(algo_name() + " private key generation failed");
+ }
+
+}
diff --git a/src/lib/pubkey/pk_keys.h b/src/lib/pubkey/pk_keys.h
new file mode 100644
index 000000000..a8585c154
--- /dev/null
+++ b/src/lib/pubkey/pk_keys.h
@@ -0,0 +1,149 @@
+/*
+* PK Key Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#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/rng.h>
+
+namespace Botan {
+
+/**
+* Public Key Base Class.
+*/
+class BOTAN_DLL Public_Key
+ {
+ public:
+ /**
+ * 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;
+
+ /**
+ * 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;
+
+ /**
+ * Find out the number of message parts supported by this scheme.
+ * @return number of message parts
+ */
+ virtual size_t message_parts() const { return 1; }
+
+ /**
+ * Find out the message part size supported by this scheme/key.
+ * @return size of the message parts in bits
+ */
+ virtual size_t message_part_size() const { return 0; }
+
+ /**
+ * Get the maximum message size in bits supported by this public key.
+ * @return maximum message size in bits
+ */
+ virtual size_t max_input_bits() const = 0;
+
+ /**
+ * @return X.509 AlgorithmIdentifier for this key
+ */
+ virtual AlgorithmIdentifier algorithm_identifier() const = 0;
+
+ /**
+ * @return X.509 subject key encoding for this key object
+ */
+ virtual std::vector<byte> x509_subject_public_key() const = 0;
+
+ virtual ~Public_Key() {}
+ protected:
+ /**
+ * Self-test after loading a key
+ * @param rng a random number generator
+ */
+ virtual void load_check(RandomNumberGenerator& rng) const;
+ };
+
+/**
+* Private Key Base Class
+*/
+class BOTAN_DLL Private_Key : public virtual Public_Key
+ {
+ public:
+ /**
+ * @return PKCS #8 private key encoding for this key object
+ */
+ virtual secure_vector<byte> pkcs8_private_key() const = 0;
+
+ /**
+ * @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(); }
+
+ protected:
+ /**
+ * Self-test after loading a key
+ * @param rng a random number generator
+ */
+ void load_check(RandomNumberGenerator& rng) const;
+
+ /**
+ * Self-test after generating a key
+ * @param rng a random number generator
+ */
+ void gen_check(RandomNumberGenerator& rng) const;
+ };
+
+/**
+* PK Secret Value Derivation Key
+*/
+class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key
+ {
+ public:
+ /*
+ * @return public component of this key
+ */
+ virtual std::vector<byte> public_value() const = 0;
+
+ virtual ~PK_Key_Agreement_Key() {}
+ };
+
+/*
+* Typedefs
+*/
+typedef PK_Key_Agreement_Key PK_KA_Key;
+typedef Public_Key X509_PublicKey;
+typedef Private_Key PKCS8_PrivateKey;
+
+}
+
+#endif
diff --git a/src/lib/pubkey/pk_ops.h b/src/lib/pubkey/pk_ops.h
new file mode 100644
index 000000000..8a08ef430
--- /dev/null
+++ b/src/lib/pubkey/pk_ops.h
@@ -0,0 +1,163 @@
+/*
+* PK Operation Types
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_OPERATIONS_H__
+#define BOTAN_PK_OPERATIONS_H__
+
+#include <botan/secmem.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+namespace PK_Ops {
+
+/**
+* Public key encryption interface
+*/
+class BOTAN_DLL Encryption
+ {
+ public:
+ virtual size_t max_input_bits() const = 0;
+
+ virtual secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) = 0;
+
+ virtual ~Encryption() {}
+ };
+
+/**
+* Public key decryption interface
+*/
+class BOTAN_DLL Decryption
+ {
+ public:
+ virtual size_t max_input_bits() const = 0;
+
+ virtual secure_vector<byte> decrypt(const byte msg[],
+ size_t msg_len) = 0;
+
+ virtual ~Decryption() {}
+ };
+
+/**
+* Public key signature creation interface
+*/
+class BOTAN_DLL Signature
+ {
+ public:
+ /**
+ * Find out the number of message parts supported by this scheme.
+ * @return number of message parts
+ */
+ virtual size_t message_parts() const { return 1; }
+
+ /**
+ * Find out the message part size supported by this scheme/key.
+ * @return size of the message parts
+ */
+ virtual size_t message_part_size() const { return 0; }
+
+ /**
+ * 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;
+
+ /*
+ * Perform a signature operation
+ * @param msg the message
+ * @param msg_len the length of msg in bytes
+ * @param rng a random number generator
+ */
+ virtual secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) = 0;
+
+ virtual ~Signature() {}
+ };
+
+/**
+* Public key signature verification interface
+*/
+class BOTAN_DLL Verification
+ {
+ public:
+ /**
+ * 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;
+
+ /**
+ * Find out the number of message parts supported by this scheme.
+ * @return number of message parts
+ */
+ virtual size_t message_parts() const { return 1; }
+
+ /**
+ * Find out the message part size supported by this scheme/key.
+ * @return size of the message parts
+ */
+ virtual size_t message_part_size() const { return 0; }
+
+ /**
+ * @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 byte[], size_t,
+ const byte[], 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<byte> verify_mr(const byte[],
+ size_t)
+ {
+ throw Invalid_State("Message recovery not supported");
+ }
+
+ virtual ~Verification() {}
+ };
+
+/**
+* A generic key agreement Operation (eg DH or ECDH)
+*/
+class BOTAN_DLL Key_Agreement
+ {
+ public:
+ /*
+ * Perform a key agreement operation
+ * @param w the other key value
+ * @param w_len the length of w in bytes
+ * @returns the agreed key
+ */
+ virtual secure_vector<byte> agree(const byte w[], size_t w_len) = 0;
+
+ virtual ~Key_Agreement() {}
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/lib/pubkey/pkcs8.cpp b/src/lib/pubkey/pkcs8.cpp
new file mode 100644
index 000000000..0dd97a866
--- /dev/null
+++ b/src/lib/pubkey/pkcs8.cpp
@@ -0,0 +1,284 @@
+/*
+* PKCS #8
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pkcs8.h>
+#include <botan/get_pbe.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/internal/pk_algs.h>
+#include <memory>
+
+namespace Botan {
+
+namespace PKCS8 {
+
+namespace {
+
+/*
+* Get info from an EncryptedPrivateKeyInfo
+*/
+secure_vector<byte> PKCS8_extract(DataSource& source,
+ AlgorithmIdentifier& pbe_alg_id)
+ {
+ secure_vector<byte> 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<byte> PKCS8_decode(
+ DataSource& source,
+ std::function<std::pair<bool,std::string> ()> get_passphrase,
+ AlgorithmIdentifier& pk_alg_id)
+ {
+ AlgorithmIdentifier pbe_alg_id;
+ secure_vector<byte> key_data, key;
+ bool is_encrypted = true;
+
+ try {
+ if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+ key_data = PKCS8_extract(source, pbe_alg_id);
+ else
+ {
+ std::string label;
+ key_data = PEM_Code::decode(source, label);
+ 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()));
+ }
+
+ if(!is_encrypted)
+ key = key_data;
+
+ const size_t MAX_TRIES = 3;
+
+ size_t tries = 0;
+ while(true)
+ {
+ try {
+ if(MAX_TRIES && tries >= MAX_TRIES)
+ break;
+
+ if(is_encrypted)
+ {
+ std::pair<bool, std::string> pass = get_passphrase();
+
+ if(pass.first == false)
+ break;
+
+ Pipe decryptor(get_pbe(pbe_alg_id.oid, pbe_alg_id.parameters, pass.second));
+
+ decryptor.process_msg(key_data);
+ key = decryptor.read_all();
+ }
+
+ 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();
+
+ break;
+ }
+ catch(Decoding_Error)
+ {
+ ++tries;
+ }
+ }
+
+ if(key.empty())
+ throw Decoding_Error("PKCS #8 private key decoding failed");
+ return key;
+ }
+
+}
+
+/*
+* BER encode a PKCS #8 private key, unencrypted
+*/
+secure_vector<byte> BER_encode(const Private_Key& key)
+ {
+ const size_t PKCS8_VERSION = 0;
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(key.pkcs8_algorithm_identifier())
+ .encode(key.pkcs8_private_key(), OCTET_STRING)
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* 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");
+ }
+
+/*
+* BER encode a PKCS #8 private key, encrypted
+*/
+std::vector<byte> BER_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ std::chrono::milliseconds msec,
+ const std::string& pbe_algo)
+ {
+ const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,AES-256/CBC)";
+
+ std::unique_ptr<PBE> pbe(
+ get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE),
+ pass,
+ msec,
+ rng));
+
+ AlgorithmIdentifier pbe_algid(pbe->get_oid(), pbe->encode_params());
+
+ Pipe key_encrytor(pbe.release());
+ key_encrytor.process_msg(PKCS8::BER_encode(key));
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(pbe_algid)
+ .encode(key_encrytor.read_all(), OCTET_STRING)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+
+/*
+* 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 == "")
+ return PEM_encode(key);
+
+ return PEM_Code::encode(PKCS8::BER_encode(key, rng, pass, msec, pbe_algo),
+ "ENCRYPTED PRIVATE KEY");
+ }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ std::function<std::pair<bool, std::string> ()> get_pass)
+ {
+ AlgorithmIdentifier alg_id;
+ secure_vector<byte> pkcs8_key = PKCS8_decode(source, get_pass, alg_id);
+
+ const std::string alg_name = OIDS::lookup(alg_id.oid);
+ if(alg_name == "" || alg_name == alg_id.oid.as_string())
+ throw PKCS8_Exception("Unknown algorithm OID: " +
+ alg_id.oid.as_string());
+
+ return make_private_key(alg_id, pkcs8_key, rng);
+ }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ std::function<std::pair<bool, std::string> ()> get_pass)
+ {
+ DataSource_Stream source(fsname, true);
+ return PKCS8::load_key(source, rng, get_pass);
+ }
+
+namespace {
+
+class Single_Shot_Passphrase
+ {
+ public:
+ Single_Shot_Passphrase(const std::string& pass) :
+ passphrase(pass), first(true) {}
+
+ std::pair<bool, std::string> operator()()
+ {
+ if(first)
+ {
+ first = false;
+ return std::make_pair(true, passphrase);
+ }
+ else
+ return std::make_pair(false, "");
+ }
+
+ private:
+ std::string passphrase;
+ bool first;
+ };
+
+}
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const std::string& pass)
+ {
+ return PKCS8::load_key(source, rng, Single_Shot_Passphrase(pass));
+ }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ const std::string& pass)
+ {
+ return PKCS8::load_key(fsname, rng, Single_Shot_Passphrase(pass));
+ }
+
+/*
+* Make a copy of this private key
+*/
+Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ DataSource_Memory source(PEM_encode(key));
+ return PKCS8::load_key(source, rng);
+ }
+
+}
+
+}
diff --git a/src/lib/pubkey/pkcs8.h b/src/lib/pubkey/pkcs8.h
new file mode 100644
index 000000000..302003ad4
--- /dev/null
+++ b/src/lib/pubkey/pkcs8.h
@@ -0,0 +1,141 @@
+/*
+* PKCS #8
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PKCS8_H__
+#define BOTAN_PKCS8_H__
+
+#include <botan/x509_key.h>
+#include <functional>
+#include <chrono>
+
+namespace Botan {
+
+/**
+* PKCS #8 General Exception
+*/
+struct BOTAN_DLL PKCS8_Exception : public Decoding_Error
+ {
+ 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_DLL secure_vector<byte> 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_DLL 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_DLL std::vector<byte>
+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_DLL 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 = "");
+
+/**
+* Load a key from a data source.
+* @param source the data source providing the encoded key
+* @param rng the rng to use
+* @param get_passphrase a function that returns passphrases
+* @return loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(
+ DataSource& source,
+ RandomNumberGenerator& rng,
+ std::function<std::pair<bool, std::string> ()> get_passphrase);
+
+/** Load a key from a data source.
+* @param source the data source providing the encoded key
+* @param rng the rng to use
+* @param pass the passphrase to decrypt the key. Provide an empty
+* string if the key is not encrypted
+* @return loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const std::string& pass = "");
+
+/**
+* Load a key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng the rng to use
+* @param get_passphrase a function that returns passphrases
+* @return loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(
+ const std::string& filename,
+ RandomNumberGenerator& rng,
+ std::function<std::pair<bool, std::string> ()> get_passphrase);
+
+/** Load a key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng the rng to use
+* @param pass the passphrase to decrypt the key. Provide an empty
+* string if the key is not encrypted
+* @return loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const std::string& pass = "");
+
+/**
+* Copy an existing encoded key object.
+* @param key the key to copy
+* @param rng the rng to use
+* @return new copy of the key
+*/
+BOTAN_DLL Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng);
+
+}
+
+}
+
+#endif
diff --git a/src/lib/pubkey/pubkey.cpp b/src/lib/pubkey/pubkey.cpp
new file mode 100644
index 000000000..313d54c16
--- /dev/null
+++ b/src/lib/pubkey/pubkey.cpp
@@ -0,0 +1,386 @@
+/*
+* Public Key Base
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pubkey.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/bigint.h>
+#include <botan/parsing.h>
+#include <botan/libstate.h>
+#include <botan/engine.h>
+#include <botan/lookup.h>
+#include <botan/internal/bit_ops.h>
+#include <memory>
+
+namespace Botan {
+
+/*
+* PK_Encryptor_EME Constructor
+*/
+PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key,
+ const std::string& eme_name)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+ RandomNumberGenerator& rng = global_state().global_rng();
+
+ while(const Engine* engine = i.next())
+ {
+ op = engine->get_encryption_op(key, rng);
+ if(op)
+ break;
+ }
+
+ if(!op)
+ throw Lookup_Error("Encryption with " + key.algo_name() + " not supported");
+
+ eme = (eme_name == "Raw") ? nullptr : get_eme(eme_name);
+ }
+
+/*
+* Encrypt a message
+*/
+std::vector<byte>
+PK_Encryptor_EME::enc(const byte in[],
+ size_t length,
+ RandomNumberGenerator& rng) const
+ {
+ if(eme)
+ {
+ secure_vector<byte> encoded =
+ eme->encode(in, length, op->max_input_bits(), rng);
+
+ if(8*(encoded.size() - 1) + high_bit(encoded[0]) > op->max_input_bits())
+ throw Invalid_Argument("PK_Encryptor_EME: Input is too large");
+
+ return unlock(op->encrypt(&encoded[0], encoded.size(), rng));
+ }
+ else
+ {
+ if(8*(length - 1) + high_bit(in[0]) > op->max_input_bits())
+ throw Invalid_Argument("PK_Encryptor_EME: Input is too large");
+
+ return unlock(op->encrypt(&in[0], length, rng));
+ }
+ }
+
+/*
+* Return the max size, in bytes, of a message
+*/
+size_t PK_Encryptor_EME::maximum_input_size() const
+ {
+ if(!eme)
+ return (op->max_input_bits() / 8);
+ else
+ return eme->maximum_input_size(op->max_input_bits());
+ }
+
+/*
+* PK_Decryptor_EME Constructor
+*/
+PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key,
+ const std::string& eme_name)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+ RandomNumberGenerator& rng = global_state().global_rng();
+
+ while(const Engine* engine = i.next())
+ {
+ op = engine->get_decryption_op(key, rng);
+ if(op)
+ break;
+ }
+
+ if(!op)
+ throw Lookup_Error("Decryption with " + key.algo_name() + " not supported");
+
+ eme = (eme_name == "Raw") ? nullptr : get_eme(eme_name);
+ }
+
+/*
+* Decrypt a message
+*/
+secure_vector<byte> PK_Decryptor_EME::dec(const byte msg[],
+ size_t length) const
+ {
+ try {
+ secure_vector<byte> decrypted = op->decrypt(msg, length);
+ if(eme)
+ return eme->decode(decrypted, op->max_input_bits());
+ else
+ return decrypted;
+ }
+ catch(Invalid_Argument)
+ {
+ throw Decoding_Error("PK_Decryptor_EME: Input is invalid");
+ }
+ }
+
+/*
+* PK_Signer Constructor
+*/
+PK_Signer::PK_Signer(const Private_Key& key,
+ const std::string& emsa_name,
+ Signature_Format format,
+ Fault_Protection prot)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+ RandomNumberGenerator& rng = global_state().global_rng();
+
+ op = nullptr;
+ verify_op = nullptr;
+
+ while(const Engine* engine = i.next())
+ {
+ if(!op)
+ op = engine->get_signature_op(key, rng);
+
+ if(!verify_op && prot == ENABLE_FAULT_PROTECTION)
+ verify_op = engine->get_verify_op(key, rng);
+
+ if(op && (verify_op || prot == DISABLE_FAULT_PROTECTION))
+ break;
+ }
+
+ if(!op || (!verify_op && prot == ENABLE_FAULT_PROTECTION))
+ throw Lookup_Error("Signing with " + key.algo_name() + " not supported");
+
+ emsa = get_emsa(emsa_name);
+ sig_format = format;
+ }
+
+/*
+* Sign a message
+*/
+std::vector<byte> PK_Signer::sign_message(const byte msg[], size_t length,
+ RandomNumberGenerator& rng)
+ {
+ update(msg, length);
+ return signature(rng);
+ }
+
+/*
+* Add more to the message to be signed
+*/
+void PK_Signer::update(const byte in[], size_t length)
+ {
+ emsa->update(in, length);
+ }
+
+/*
+* Check the signature we just created, to help prevent fault attacks
+*/
+bool PK_Signer::self_test_signature(const std::vector<byte>& msg,
+ const std::vector<byte>& sig) const
+ {
+ if(!verify_op)
+ return true; // checking disabled, assume ok
+
+ if(verify_op->with_recovery())
+ {
+ std::vector<byte> recovered =
+ unlock(verify_op->verify_mr(&sig[0], sig.size()));
+
+ if(msg.size() > recovered.size())
+ {
+ size_t extra_0s = msg.size() - recovered.size();
+
+ for(size_t i = 0; i != extra_0s; ++i)
+ if(msg[i] != 0)
+ return false;
+
+ return same_mem(&msg[extra_0s], &recovered[0], recovered.size());
+ }
+
+ return (recovered == msg);
+ }
+ else
+ return verify_op->verify(&msg[0], msg.size(),
+ &sig[0], sig.size());
+ }
+
+/*
+* Create a signature
+*/
+std::vector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
+ {
+ std::vector<byte> encoded = unlock(emsa->encoding_of(emsa->raw_data(),
+ op->max_input_bits(),
+ rng));
+
+ std::vector<byte> plain_sig = unlock(op->sign(&encoded[0], encoded.size(), rng));
+
+ BOTAN_ASSERT(self_test_signature(encoded, plain_sig), "Signature was consistent");
+
+ if(op->message_parts() == 1 || sig_format == IEEE_1363)
+ return plain_sig;
+
+ if(sig_format == DER_SEQUENCE)
+ {
+ if(plain_sig.size() % op->message_parts())
+ throw Encoding_Error("PK_Signer: strange signature size found");
+ const size_t SIZE_OF_PART = plain_sig.size() / op->message_parts();
+
+ std::vector<BigInt> sig_parts(op->message_parts());
+ for(size_t j = 0; j != sig_parts.size(); ++j)
+ sig_parts[j].binary_decode(&plain_sig[SIZE_OF_PART*j], SIZE_OF_PART);
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_list(sig_parts)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+ else
+ throw Encoding_Error("PK_Signer: Unknown signature format " +
+ std::to_string(sig_format));
+ }
+
+/*
+* PK_Verifier Constructor
+*/
+PK_Verifier::PK_Verifier(const Public_Key& key,
+ const std::string& emsa_name,
+ Signature_Format format)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+ RandomNumberGenerator& rng = global_state().global_rng();
+
+ while(const Engine* engine = i.next())
+ {
+ op = engine->get_verify_op(key, rng);
+ if(op)
+ break;
+ }
+
+ if(!op)
+ throw Lookup_Error("Verification with " + key.algo_name() + " not supported");
+
+ emsa = get_emsa(emsa_name);
+ sig_format = format;
+ }
+
+/*
+* Set the signature format
+*/
+void PK_Verifier::set_input_format(Signature_Format format)
+ {
+ if(op->message_parts() == 1 && format != IEEE_1363)
+ throw Invalid_State("PK_Verifier: This algorithm always uses IEEE 1363");
+ sig_format = format;
+ }
+
+/*
+* Verify a message
+*/
+bool PK_Verifier::verify_message(const byte msg[], size_t msg_length,
+ const byte sig[], size_t sig_length)
+ {
+ update(msg, msg_length);
+ return check_signature(sig, sig_length);
+ }
+
+/*
+* Append to the message
+*/
+void PK_Verifier::update(const byte in[], size_t length)
+ {
+ emsa->update(in, length);
+ }
+
+/*
+* Check a signature
+*/
+bool PK_Verifier::check_signature(const byte sig[], size_t length)
+ {
+ try {
+ if(sig_format == IEEE_1363)
+ return validate_signature(emsa->raw_data(), sig, length);
+ else if(sig_format == DER_SEQUENCE)
+ {
+ BER_Decoder decoder(sig, length);
+ BER_Decoder ber_sig = decoder.start_cons(SEQUENCE);
+
+ size_t count = 0;
+ std::vector<byte> real_sig;
+ while(ber_sig.more_items())
+ {
+ BigInt sig_part;
+ ber_sig.decode(sig_part);
+ real_sig += BigInt::encode_1363(sig_part, op->message_part_size());
+ ++count;
+ }
+
+ if(count != op->message_parts())
+ throw Decoding_Error("PK_Verifier: signature size invalid");
+
+ return validate_signature(emsa->raw_data(),
+ &real_sig[0], real_sig.size());
+ }
+ else
+ throw Decoding_Error("PK_Verifier: Unknown signature format " +
+ std::to_string(sig_format));
+ }
+ catch(Invalid_Argument) { return false; }
+ }
+
+/*
+* Verify a signature
+*/
+bool PK_Verifier::validate_signature(const secure_vector<byte>& msg,
+ const byte sig[], size_t sig_len)
+ {
+ if(op->with_recovery())
+ {
+ secure_vector<byte> output_of_key = op->verify_mr(sig, sig_len);
+ return emsa->verify(output_of_key, msg, op->max_input_bits());
+ }
+ else
+ {
+ RandomNumberGenerator& rng = global_state().global_rng();
+
+ secure_vector<byte> encoded =
+ emsa->encoding_of(msg, op->max_input_bits(), rng);
+
+ return op->verify(&encoded[0], encoded.size(), sig, sig_len);
+ }
+ }
+
+/*
+* PK_Key_Agreement Constructor
+*/
+PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& key,
+ const std::string& kdf_name)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+ RandomNumberGenerator& rng = global_state().global_rng();
+
+ while(const Engine* engine = i.next())
+ {
+ op = engine->get_key_agreement_op(key, rng);
+ if(op)
+ break;
+ }
+
+ if(!op)
+ throw Lookup_Error("Key agreement with " + key.algo_name() + " not supported");
+
+ kdf = (kdf_name == "Raw") ? nullptr : get_kdf(kdf_name);
+ }
+
+SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, const byte in[],
+ size_t in_len, const byte params[],
+ size_t params_len) const
+ {
+ secure_vector<byte> z = op->agree(in, in_len);
+
+ if(!kdf)
+ return z;
+
+ return kdf->derive_key(key_len, z, params, params_len);
+ }
+
+}
diff --git a/src/lib/pubkey/pubkey.h b/src/lib/pubkey/pubkey.h
new file mode 100644
index 000000000..cfa46109c
--- /dev/null
+++ b/src/lib/pubkey/pubkey.h
@@ -0,0 +1,461 @@
+/*
+* Public Key Interface
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PUBKEY_H__
+#define BOTAN_PUBKEY_H__
+
+#include <botan/pk_keys.h>
+#include <botan/pk_ops.h>
+#include <botan/symkey.h>
+#include <botan/rng.h>
+#include <botan/eme.h>
+#include <botan/emsa.h>
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/**
+* The two types of signature format supported by Botan.
+*/
+enum Signature_Format { IEEE_1363, DER_SEQUENCE };
+
+/**
+* Enum marking if protection against fault attacks should be used
+*/
+enum Fault_Protection {
+ ENABLE_FAULT_PROTECTION,
+ DISABLE_FAULT_PROTECTION
+};
+
+/**
+* Public Key Encryptor
+*/
+class BOTAN_DLL 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<byte> encrypt(const byte 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<byte> encrypt(const std::vector<byte, Alloc>& in,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(&in[0], 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() {}
+ virtual ~PK_Encryptor() {}
+
+ PK_Encryptor(const PK_Encryptor&) = delete;
+
+ PK_Encryptor& operator=(const PK_Encryptor&) = delete;
+
+ private:
+ virtual std::vector<byte> enc(const byte[], size_t,
+ RandomNumberGenerator&) const = 0;
+ };
+
+/**
+* Public Key Decryptor
+*/
+class BOTAN_DLL PK_Decryptor
+ {
+ public:
+ /**
+ * Decrypt a ciphertext.
+ * @param in the ciphertext as a byte array
+ * @param length the length of the above byte array
+ * @return decrypted message
+ */
+ secure_vector<byte> decrypt(const byte in[], size_t length) const
+ {
+ return dec(in, length);
+ }
+
+ /**
+ * Decrypt a ciphertext.
+ * @param in the ciphertext
+ * @return decrypted message
+ */
+ template<typename Alloc>
+ secure_vector<byte> decrypt(const std::vector<byte, Alloc>& in) const
+ {
+ return dec(&in[0], in.size());
+ }
+
+ PK_Decryptor() {}
+ virtual ~PK_Decryptor() {}
+
+ PK_Decryptor(const PK_Decryptor&) = delete;
+ PK_Decryptor& operator=(const PK_Decryptor&) = delete;
+
+ private:
+ virtual secure_vector<byte> dec(const byte[], size_t) 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_DLL PK_Signer
+ {
+ public:
+ /**
+ * Sign a message.
+ * @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<byte> sign_message(const byte in[], size_t length,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Sign a message.
+ * @param in the message to sign
+ * @param rng the rng to use
+ * @return signature
+ */
+ std::vector<byte> sign_message(const std::vector<byte>& in,
+ RandomNumberGenerator& rng)
+ { return sign_message(&in[0], in.size(), rng); }
+
+ std::vector<byte> sign_message(const secure_vector<byte>& in,
+ RandomNumberGenerator& rng)
+ { return sign_message(&in[0], in.size(), rng); }
+
+ /**
+ * Add a message part (single byte).
+ * @param in the byte to add
+ */
+ void update(byte 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 byte in[], size_t length);
+
+ /**
+ * Add a message part.
+ * @param in the message part to add
+ */
+ void update(const std::vector<byte>& in) { update(&in[0], 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<byte> signature(RandomNumberGenerator& rng);
+
+ /**
+ * Set the output format of the signature.
+ * @param format the signature format to use
+ */
+ void set_output_format(Signature_Format format) { sig_format = format; }
+
+ /**
+ * 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
+ * @param prot says if fault protection should be enabled
+ */
+ PK_Signer(const Private_Key& key,
+ const std::string& emsa,
+ Signature_Format format = IEEE_1363,
+ Fault_Protection prot = ENABLE_FAULT_PROTECTION);
+
+ PK_Signer(const PK_Signer&) = delete;
+ PK_Signer& operator=(const PK_Signer&) = delete;
+
+ ~PK_Signer() { delete op; delete verify_op; delete emsa; }
+ private:
+ bool self_test_signature(const std::vector<byte>& msg,
+ const std::vector<byte>& sig) const;
+
+ PK_Ops::Signature* op;
+ PK_Ops::Verification* verify_op;
+ EMSA* emsa;
+ Signature_Format sig_format;
+ };
+
+/**
+* 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_DLL PK_Verifier
+ {
+ public:
+ /**
+ * 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 byte msg[], size_t msg_length,
+ const byte 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<byte, Alloc>& msg,
+ const std::vector<byte, Alloc2>& sig)
+ {
+ return verify_message(&msg[0], msg.size(),
+ &sig[0], 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(byte 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 byte 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<byte>& in)
+ { update(&in[0], 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 byte 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<byte, Alloc>& sig)
+ {
+ return check_signature(&sig[0], 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);
+
+ /**
+ * 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
+ */
+ PK_Verifier(const Public_Key& pub_key,
+ const std::string& emsa,
+ Signature_Format format = IEEE_1363);
+
+ PK_Verifier(const PK_Verifier&) = delete;
+ PK_Verifier& operator=(const PK_Verifier&) = delete;
+
+ ~PK_Verifier() { delete op; delete emsa; }
+ private:
+ bool validate_signature(const secure_vector<byte>& msg,
+ const byte sig[], size_t sig_len);
+
+ PK_Ops::Verification* op;
+ EMSA* emsa;
+ Signature_Format sig_format;
+ };
+
+/**
+* Key used for key agreement
+*/
+class BOTAN_DLL PK_Key_Agreement
+ {
+ public:
+
+ /*
+ * 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 byte in[],
+ size_t in_len,
+ const byte 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<byte>& in,
+ const byte params[],
+ size_t params_len) const
+ {
+ return derive_key(key_len, &in[0], 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 byte in[], size_t in_len,
+ const std::string& params = "") const
+ {
+ return derive_key(key_len, in, in_len,
+ reinterpret_cast<const byte*>(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<byte>& in,
+ const std::string& params = "") const
+ {
+ return derive_key(key_len, &in[0], in.size(),
+ reinterpret_cast<const byte*>(params.data()),
+ params.length());
+ }
+
+ /**
+ * Construct a PK Key Agreement.
+ * @param key the key to use
+ * @param kdf name of the KDF to use (or 'Raw' for no KDF)
+ */
+ PK_Key_Agreement(const PK_Key_Agreement_Key& key,
+ const std::string& kdf);
+
+ PK_Key_Agreement(const PK_Key_Agreement_Key&) = delete;
+ PK_Key_Agreement& operator=(const PK_Key_Agreement&) = delete;
+
+ ~PK_Key_Agreement() { delete op; delete kdf; }
+ private:
+ PK_Ops::Key_Agreement* op;
+ KDF* kdf;
+ };
+
+/**
+* Encryption with an MR algorithm and an EME.
+*/
+class BOTAN_DLL PK_Encryptor_EME : public PK_Encryptor
+ {
+ public:
+ size_t maximum_input_size() const;
+
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the decryptor
+ * @param eme the EME to use
+ */
+ PK_Encryptor_EME(const Public_Key& key,
+ const std::string& eme);
+
+ ~PK_Encryptor_EME() { delete op; delete eme; }
+ private:
+ std::vector<byte> enc(const byte[], size_t,
+ RandomNumberGenerator& rng) const;
+
+ PK_Ops::Encryption* op;
+ const EME* eme;
+ };
+
+/**
+* Decryption with an MR algorithm and an EME.
+*/
+class BOTAN_DLL PK_Decryptor_EME : public PK_Decryptor
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the encryptor
+ * @param eme the EME to use
+ */
+ PK_Decryptor_EME(const Private_Key& key,
+ const std::string& eme);
+
+ ~PK_Decryptor_EME() { delete op; delete eme; }
+ private:
+ secure_vector<byte> dec(const byte[], size_t) const;
+
+ PK_Ops::Decryption* op;
+ const EME* eme;
+ };
+
+/*
+* Typedefs for compatability with 1.8
+*/
+typedef PK_Encryptor_EME PK_Encryptor_MR_with_EME;
+typedef PK_Decryptor_EME PK_Decryptor_MR_with_EME;
+
+}
+
+#endif
diff --git a/src/lib/pubkey/rsa/info.txt b/src/lib/pubkey/rsa/info.txt
new file mode 100644
index 000000000..6171642bc
--- /dev/null
+++ b/src/lib/pubkey/rsa/info.txt
@@ -0,0 +1,8 @@
+define RSA 20131128
+
+<requires>
+if_algo
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/rsa/rsa.cpp b/src/lib/pubkey/rsa/rsa.cpp
new file mode 100644
index 000000000..199ce6ad8
--- /dev/null
+++ b/src/lib/pubkey/rsa/rsa.cpp
@@ -0,0 +1,121 @@
+/*
+* RSA
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rsa.h>
+#include <botan/parsing.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <future>
+
+namespace Botan {
+
+/*
+* 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");
+
+ e = exp;
+
+ do
+ {
+ p = random_prime(rng, (bits + 1) / 2, e);
+ q = random_prime(rng, bits - p.bits(), e);
+ n = p * q;
+ } while(n.bits() != bits);
+
+ d = inverse_mod(e, lcm(p - 1, q - 1));
+ d1 = d % (p - 1);
+ d2 = d % (q - 1);
+ c = inverse_mod(q, p);
+
+ gen_check(rng);
+ }
+
+/*
+* Check Private RSA Parameters
+*/
+bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!IF_Scheme_PrivateKey::check_key(rng, strong))
+ return false;
+
+ if(!strong)
+ return true;
+
+ if((e * d) % lcm(p - 1, q - 1) != 1)
+ return false;
+
+ return KeyPair::signature_consistency_check(rng, *this, "EMSA4(SHA-1)");
+ }
+
+RSA_Private_Operation::RSA_Private_Operation(const RSA_PrivateKey& rsa,
+ RandomNumberGenerator& rng) :
+ n(rsa.get_n()),
+ q(rsa.get_q()),
+ c(rsa.get_c()),
+ powermod_e_n(rsa.get_e(), rsa.get_n()),
+ powermod_d1_p(rsa.get_d1(), rsa.get_p()),
+ powermod_d2_q(rsa.get_d2(), rsa.get_q()),
+ mod_p(rsa.get_p())
+ {
+ BigInt k(rng, n.bits() - 1);
+ blinder = Blinder(powermod_e_n(k), inverse_mod(k, n), n);
+ }
+
+BigInt RSA_Private_Operation::private_op(const BigInt& m) const
+ {
+ if(m >= n)
+ throw Invalid_Argument("RSA private op - input is too large");
+
+ auto future_j1 = std::async(std::launch::async, powermod_d1_p, m);
+ BigInt j2 = powermod_d2_q(m);
+ BigInt j1 = future_j1.get();
+
+ j1 = mod_p.reduce(sub_mul(j1, j2, c));
+
+ return mul_add(j1, q, j2);
+ }
+
+secure_vector<byte>
+RSA_Private_Operation::sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ rng.add_entropy(msg, msg_len);
+
+ /* We don't check signatures against powermod_e_n here because
+ PK_Signer checks verification consistency for all signature
+ algorithms.
+ */
+
+ const BigInt m(msg, msg_len);
+ const BigInt x = blinder.unblind(private_op(blinder.blind(m)));
+ return BigInt::encode_1363(x, n.bytes());
+ }
+
+/*
+* RSA Decryption Operation
+*/
+secure_vector<byte>
+RSA_Private_Operation::decrypt(const byte msg[], size_t msg_len)
+ {
+ const BigInt m(msg, msg_len);
+ const BigInt x = blinder.unblind(private_op(blinder.blind(m)));
+
+ BOTAN_ASSERT(m == powermod_e_n(x),
+ "RSA decrypt passed consistency check");
+
+ return BigInt::encode_locked(x);
+ }
+
+}
diff --git a/src/lib/pubkey/rsa/rsa.h b/src/lib/pubkey/rsa/rsa.h
new file mode 100644
index 000000000..4d9189d20
--- /dev/null
+++ b/src/lib/pubkey/rsa/rsa.h
@@ -0,0 +1,155 @@
+/*
+* RSA
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RSA_H__
+#define BOTAN_RSA_H__
+
+#include <botan/if_algo.h>
+#include <botan/pk_ops.h>
+#include <botan/reducer.h>
+#include <botan/blinding.h>
+
+namespace Botan {
+
+/**
+* RSA Public Key
+*/
+class BOTAN_DLL RSA_PublicKey : public virtual IF_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "RSA"; }
+
+ RSA_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits) :
+ IF_Scheme_PublicKey(alg_id, key_bits)
+ {}
+
+ /**
+ * Create a RSA_PublicKey
+ * @arg n the modulus
+ * @arg e the exponent
+ */
+ RSA_PublicKey(const BigInt& n, const BigInt& e) :
+ IF_Scheme_PublicKey(n, e)
+ {}
+
+ protected:
+ RSA_PublicKey() {}
+ };
+
+/**
+* RSA Private Key
+*/
+class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey,
+ public IF_Scheme_PrivateKey
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ RSA_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng) :
+ IF_Scheme_PrivateKey(rng, alg_id, key_bits) {}
+
+ /**
+ * Construct a private key from the specified parameters.
+ * @param rng a random number generator
+ * @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(RandomNumberGenerator& rng,
+ const BigInt& p, const BigInt& q,
+ const BigInt& e, const BigInt& d = 0,
+ const BigInt& n = 0) :
+ IF_Scheme_PrivateKey(rng, p, q, e, d, n) {}
+
+ /**
+ * 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);
+ };
+
+/**
+* RSA private (decrypt/sign) operation
+*/
+class BOTAN_DLL RSA_Private_Operation : public PK_Ops::Signature,
+ public PK_Ops::Decryption
+ {
+ public:
+ RSA_Private_Operation(const RSA_PrivateKey& rsa,
+ RandomNumberGenerator& rng);
+
+ size_t max_input_bits() const { return (n.bits() - 1); }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len);
+
+ private:
+ BigInt private_op(const BigInt& m) const;
+
+ const BigInt& n;
+ const BigInt& q;
+ const BigInt& c;
+ Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q;
+ Modular_Reducer mod_p;
+ Blinder blinder;
+ };
+
+/**
+* RSA public (encrypt/verify) operation
+*/
+class BOTAN_DLL RSA_Public_Operation : public PK_Ops::Verification,
+ public PK_Ops::Encryption
+ {
+ public:
+ RSA_Public_Operation(const RSA_PublicKey& rsa) :
+ n(rsa.get_n()), powermod_e_n(rsa.get_e(), rsa.get_n())
+ {}
+
+ size_t max_input_bits() const { return (n.bits() - 1); }
+ bool with_recovery() const { return true; }
+
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&)
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_1363(public_op(m), n.bytes());
+ }
+
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len)
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_locked(public_op(m));
+ }
+
+ private:
+ BigInt public_op(const BigInt& m) const
+ {
+ if(m >= n)
+ throw Invalid_Argument("RSA public op - input is too large");
+ return powermod_e_n(m);
+ }
+
+ const BigInt& n;
+ Fixed_Exponent_Power_Mod powermod_e_n;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/rw/info.txt b/src/lib/pubkey/rw/info.txt
new file mode 100644
index 000000000..486ede47f
--- /dev/null
+++ b/src/lib/pubkey/rw/info.txt
@@ -0,0 +1,8 @@
+define RW 20131128
+
+<requires>
+if_algo
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/src/lib/pubkey/rw/rw.cpp b/src/lib/pubkey/rw/rw.cpp
new file mode 100644
index 000000000..63e7977d8
--- /dev/null
+++ b/src/lib/pubkey/rw/rw.cpp
@@ -0,0 +1,130 @@
+/*
+* Rabin-Williams
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rw.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/parsing.h>
+#include <algorithm>
+#include <future>
+
+namespace Botan {
+
+/*
+* Create a Rabin-Williams private key
+*/
+RW_PrivateKey::RW_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 < 2 || exp % 2 == 1)
+ throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
+
+ e = exp;
+
+ do
+ {
+ p = random_prime(rng, (bits + 1) / 2, e / 2, 3, 4);
+ q = random_prime(rng, bits - p.bits(), e / 2, ((p % 8 == 3) ? 7 : 3), 8);
+ n = p * q;
+ } while(n.bits() != bits);
+
+ d = inverse_mod(e, lcm(p - 1, q - 1) >> 1);
+ d1 = d % (p - 1);
+ d2 = d % (q - 1);
+ c = inverse_mod(q, p);
+
+ gen_check(rng);
+ }
+
+/*
+* Check Private Rabin-Williams Parameters
+*/
+bool RW_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!IF_Scheme_PrivateKey::check_key(rng, strong))
+ return false;
+
+ if(!strong)
+ return true;
+
+ if((e * d) % (lcm(p - 1, q - 1) / 2) != 1)
+ return false;
+
+ return KeyPair::signature_consistency_check(rng, *this, "EMSA2(SHA-1)");
+ }
+
+RW_Signature_Operation::RW_Signature_Operation(const RW_PrivateKey& rw) :
+ n(rw.get_n()),
+ e(rw.get_e()),
+ q(rw.get_q()),
+ c(rw.get_c()),
+ powermod_d1_p(rw.get_d1(), rw.get_p()),
+ powermod_d2_q(rw.get_d2(), rw.get_q()),
+ mod_p(rw.get_p())
+ {
+ }
+
+secure_vector<byte>
+RW_Signature_Operation::sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ rng.add_entropy(msg, msg_len);
+
+ if(!blinder.initialized())
+ {
+ BigInt k(rng, std::min<size_t>(160, n.bits() - 1));
+ blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n);
+ }
+
+ BigInt i(msg, msg_len);
+
+ if(i >= n || i % 16 != 12)
+ throw Invalid_Argument("Rabin-Williams: invalid input");
+
+ if(jacobi(i, n) != 1)
+ i >>= 1;
+
+ i = blinder.blind(i);
+
+ auto future_j1 = std::async(std::launch::async, powermod_d1_p, i);
+ const BigInt j2 = powermod_d2_q(i);
+ BigInt j1 = future_j1.get();
+
+ j1 = mod_p.reduce(sub_mul(j1, j2, c));
+
+ const BigInt r = blinder.unblind(mul_add(j1, q, j2));
+
+ return BigInt::encode_1363(std::min(r, n - r), n.bytes());
+ }
+
+secure_vector<byte>
+RW_Verification_Operation::verify_mr(const byte msg[], size_t msg_len)
+ {
+ BigInt m(msg, msg_len);
+
+ if((m > (n >> 1)) || m.is_negative())
+ throw Invalid_Argument("RW signature verification: m > n / 2 || m < 0");
+
+ BigInt r = powermod_e_n(m);
+ if(r % 16 == 12)
+ return BigInt::encode_locked(r);
+ if(r % 8 == 6)
+ return BigInt::encode_locked(2*r);
+
+ r = n - r;
+ if(r % 16 == 12)
+ return BigInt::encode_locked(r);
+ if(r % 8 == 6)
+ return BigInt::encode_locked(2*r);
+
+ throw Invalid_Argument("RW signature verification: Invalid signature");
+ }
+
+}
diff --git a/src/lib/pubkey/rw/rw.h b/src/lib/pubkey/rw/rw.h
new file mode 100644
index 000000000..1e918e70c
--- /dev/null
+++ b/src/lib/pubkey/rw/rw.h
@@ -0,0 +1,107 @@
+/*
+* Rabin-Williams
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RW_H__
+#define BOTAN_RW_H__
+
+#include <botan/if_algo.h>
+#include <botan/pk_ops.h>
+#include <botan/reducer.h>
+#include <botan/blinding.h>
+
+namespace Botan {
+
+/**
+* Rabin-Williams Public Key
+*/
+class BOTAN_DLL RW_PublicKey : public virtual IF_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "RW"; }
+
+ RW_PublicKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits) :
+ IF_Scheme_PublicKey(alg_id, key_bits)
+ {}
+
+ RW_PublicKey(const BigInt& mod, const BigInt& exponent) :
+ IF_Scheme_PublicKey(mod, exponent)
+ {}
+
+ protected:
+ RW_PublicKey() {}
+ };
+
+/**
+* Rabin-Williams Private Key
+*/
+class BOTAN_DLL RW_PrivateKey : public RW_PublicKey,
+ public IF_Scheme_PrivateKey
+ {
+ public:
+ RW_PrivateKey(const AlgorithmIdentifier& alg_id,
+ const secure_vector<byte>& key_bits,
+ RandomNumberGenerator& rng) :
+ IF_Scheme_PrivateKey(rng, alg_id, key_bits) {}
+
+ RW_PrivateKey(RandomNumberGenerator& rng,
+ const BigInt& p, const BigInt& q,
+ const BigInt& e, const BigInt& d = 0,
+ const BigInt& n = 0) :
+ IF_Scheme_PrivateKey(rng, p, q, e, d, n) {}
+
+ RW_PrivateKey(RandomNumberGenerator& rng, size_t bits, size_t = 2);
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+ };
+
+/**
+* Rabin-Williams Signature Operation
+*/
+class BOTAN_DLL RW_Signature_Operation : public PK_Ops::Signature
+ {
+ public:
+ RW_Signature_Operation(const RW_PrivateKey& rw);
+
+ size_t max_input_bits() const { return (n.bits() - 1); }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+ private:
+ const BigInt& n;
+ const BigInt& e;
+ const BigInt& q;
+ const BigInt& c;
+
+ Fixed_Exponent_Power_Mod powermod_d1_p, powermod_d2_q;
+ Modular_Reducer mod_p;
+ Blinder blinder;
+ };
+
+/**
+* Rabin-Williams Verification Operation
+*/
+class BOTAN_DLL RW_Verification_Operation : public PK_Ops::Verification
+ {
+ public:
+ RW_Verification_Operation(const RW_PublicKey& rw) :
+ n(rw.get_n()), powermod_e_n(rw.get_e(), rw.get_n())
+ {}
+
+ size_t max_input_bits() const { return (n.bits() - 1); }
+ bool with_recovery() const { return true; }
+
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len);
+
+ private:
+ const BigInt& n;
+ Fixed_Exponent_Power_Mod powermod_e_n;
+ };
+
+}
+
+#endif
diff --git a/src/lib/pubkey/workfactor.cpp b/src/lib/pubkey/workfactor.cpp
new file mode 100644
index 000000000..b917ce52d
--- /dev/null
+++ b/src/lib/pubkey/workfactor.cpp
@@ -0,0 +1,50 @@
+/*
+* Public Key Work Factor Functions
+* (C) 1999-2007,2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/workfactor.h>
+#include <algorithm>
+#include <cmath>
+
+namespace Botan {
+
+size_t dl_work_factor(size_t bits)
+ {
+ /*
+ Based on GNFS work factors. Constant is 1.43 times the asymptotic
+ value; I'm not sure but I believe that came from a paper on 'real
+ world' runtimes, but I don't remember where now.
+
+ Sample return values:
+ |512| -> 64
+ |1024| -> 86
+ |1536| -> 102
+ |2048| -> 116
+ |3072| -> 138
+ |4096| -> 155
+ |8192| -> 206
+
+ For DL algos, we use an exponent of twice the size of the result;
+ the assumption is that 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.
+ */
+
+ const size_t MIN_WORKFACTOR = 64;
+
+ // approximates natural logarithm of p
+ const double log_p = bits / 1.4426;
+
+ const double strength =
+ 2.76 * std::pow(log_p, 1.0/3.0) * std::pow(std::log(log_p), 2.0/3.0);
+
+ return std::max(static_cast<size_t>(strength), MIN_WORKFACTOR);
+ }
+
+}
diff --git a/src/lib/pubkey/workfactor.h b/src/lib/pubkey/workfactor.h
new file mode 100644
index 000000000..179b580e7
--- /dev/null
+++ b/src/lib/pubkey/workfactor.h
@@ -0,0 +1,24 @@
+/*
+* Public Key Work Factor Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#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
+*/
+size_t dl_work_factor(size_t prime_group_size);
+
+}
+
+#endif
diff --git a/src/lib/pubkey/x509_key.cpp b/src/lib/pubkey/x509_key.cpp
new file mode 100644
index 000000000..10395837c
--- /dev/null
+++ b/src/lib/pubkey/x509_key.cpp
@@ -0,0 +1,111 @@
+/*
+* X.509 Public Key
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509_key.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pem.h>
+#include <botan/alg_id.h>
+#include <botan/internal/pk_algs.h>
+#include <memory>
+
+namespace Botan {
+
+namespace X509 {
+
+std::vector<byte> BER_encode(const Public_Key& key)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(key.algorithm_identifier())
+ .encode(key.x509_subject_public_key(), BIT_STRING)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+
+/*
+* PEM encode a X.509 public key
+*/
+std::string PEM_encode(const Public_Key& key)
+ {
+ return PEM_Code::encode(X509::BER_encode(key),
+ "PUBLIC KEY");
+ }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(DataSource& source)
+ {
+ try {
+ AlgorithmIdentifier alg_id;
+ secure_vector<byte> 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)
+ .verify_end()
+ .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)
+ .verify_end()
+ .end_cons();
+ }
+
+ if(key_bits.empty())
+ throw Decoding_Error("X.509 public key decoding failed");
+
+ return make_public_key(alg_id, key_bits);
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error("X.509 public key decoding failed");
+ }
+ }
+
+/*
+* 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);
+ }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(const std::vector<byte>& 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/lib/pubkey/x509_key.h b/src/lib/pubkey/x509_key.h
new file mode 100644
index 000000000..14e5c9699
--- /dev/null
+++ b/src/lib/pubkey/x509_key.h
@@ -0,0 +1,74 @@
+/*
+* X.509 Public Key
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_PUBLIC_KEY_H__
+#define BOTAN_X509_PUBLIC_KEY_H__
+
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+#include <botan/pipe.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* The two types of X509 encoding supported by Botan.
+*/
+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_DLL std::vector<byte> 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_DLL 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_DLL Public_Key* load_key(DataSource& source);
+
+/**
+* Create a public key from a file
+* @param filename pathname to the file to load
+* @return new public key object
+*/
+BOTAN_DLL Public_Key* load_key(const std::string& filename);
+
+/**
+* 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_DLL Public_Key* load_key(const std::vector<byte>& enc);
+
+/**
+* Copy a key.
+* @param key the public key to copy
+* @return new public key object
+*/
+BOTAN_DLL Public_Key* copy_key(const Public_Key& key);
+
+}
+
+}
+
+#endif