aboutsummaryrefslogtreecommitdiffstats
path: root/src/pk/pubkey
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-09-29 00:30:26 +0000
committerlloyd <[email protected]>2008-09-29 00:30:26 +0000
commitce1074c2ce8d37cddda35079dc279c7823766aca (patch)
treee9c8ef0c6706477666f8e1c3e82986785fc67e0b /src/pk/pubkey
parentd8034ff636a1b0d1d8d90058183b985f8b90e45f (diff)
Move parts of core into pk/pubkey which is at least somewhat relevant
Diffstat (limited to 'src/pk/pubkey')
-rw-r--r--src/pk/pubkey/dh_op.cpp41
-rw-r--r--src/pk/pubkey/dsa_op.cpp106
-rw-r--r--src/pk/pubkey/elg_op.cpp89
-rw-r--r--src/pk/pubkey/kdf.cpp70
-rw-r--r--src/pk/pubkey/nr_op.cpp104
-rw-r--r--src/pk/pubkey/pk_algs.cpp98
-rw-r--r--src/pk/pubkey/pk_algs.h22
-rw-r--r--src/pk/pubkey/pk_core.cpp300
-rw-r--r--src/pk/pubkey/pk_core.h128
-rw-r--r--src/pk/pubkey/pk_keys.cpp68
-rw-r--r--src/pk/pubkey/pk_keys.h127
-rw-r--r--src/pk/pubkey/pk_ops.h79
-rw-r--r--src/pk/pubkey/pk_util.cpp48
-rw-r--r--src/pk/pubkey/pk_util.h92
-rw-r--r--src/pk/pubkey/pkcs8.cpp307
-rw-r--r--src/pk/pubkey/pkcs8.h85
-rw-r--r--src/pk/pubkey/pubkey.cpp415
-rw-r--r--src/pk/pubkey/pubkey.h210
-rw-r--r--src/pk/pubkey/rsa_op.cpp83
-rw-r--r--src/pk/pubkey/x509_key.cpp174
-rw-r--r--src/pk/pubkey/x509_key.h58
21 files changed, 2704 insertions, 0 deletions
diff --git a/src/pk/pubkey/dh_op.cpp b/src/pk/pubkey/dh_op.cpp
new file mode 100644
index 000000000..0bcfd4ef8
--- /dev/null
+++ b/src/pk/pubkey/dh_op.cpp
@@ -0,0 +1,41 @@
+/*************************************************
+* DH Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default DH Operation *
+*************************************************/
+class Default_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const { return powermod_x_p(i); }
+ DH_Operation* clone() const { return new Default_DH_Op(*this); }
+
+ Default_DH_Op(const DL_Group& group, const BigInt& x) :
+ powermod_x_p(x, group.get_p()) {}
+ private:
+ const Fixed_Exponent_Power_Mod powermod_x_p;
+ };
+
+}
+
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* Default_Engine::dh_op(const DL_Group& group,
+ const BigInt& x) const
+ {
+ return new Default_DH_Op(group, x);
+ }
+
+}
diff --git a/src/pk/pubkey/dsa_op.cpp b/src/pk/pubkey/dsa_op.cpp
new file mode 100644
index 000000000..ee94cb256
--- /dev/null
+++ b/src/pk/pubkey/dsa_op.cpp
@@ -0,0 +1,106 @@
+/*************************************************
+* DSA Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default DSA Operation *
+*************************************************/
+class Default_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new Default_DSA_Op(*this); }
+
+ Default_DSA_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+/*************************************************
+* Default_DSA_Op Constructor *
+*************************************************/
+Default_DSA_Op::Default_DSA_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p());
+ powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p());
+ mod_p = Modular_Reducer(group.get_p());
+ mod_q = Modular_Reducer(group.get_q());
+ }
+
+/*************************************************
+* Default DSA Verify Operation *
+*************************************************/
+bool Default_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const BigInt& q = group.get_q();
+
+ 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);
+ s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)),
+ powermod_y_p(mod_q.multiply(s, r)));
+
+ return (mod_q.reduce(s) == r);
+ }
+
+/*************************************************
+* Default DSA Sign Operation *
+*************************************************/
+SecureVector<byte> Default_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ if(x == 0)
+ throw Internal_Error("Default_DSA_Op::sign: No private key");
+
+ const BigInt& q = group.get_q();
+ BigInt i(in, length);
+
+ BigInt r = mod_q.reduce(powermod_g_p(k));
+ BigInt s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i));
+
+ if(r.is_zero() || s.is_zero())
+ throw Internal_Error("Default_DSA_Op::sign: r or s was zero");
+
+ SecureVector<byte> output(2*q.bytes());
+ r.binary_encode(output + (output.size() / 2 - r.bytes()));
+ s.binary_encode(output + (output.size() - s.bytes()));
+ return output;
+ }
+
+}
+
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* Default_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_DSA_Op(group, y, x);
+ }
+
+}
diff --git a/src/pk/pubkey/elg_op.cpp b/src/pk/pubkey/elg_op.cpp
new file mode 100644
index 000000000..0d852d145
--- /dev/null
+++ b/src/pk/pubkey/elg_op.cpp
@@ -0,0 +1,89 @@
+/*************************************************
+* ElGamal Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default ElGamal Operation *
+*************************************************/
+class Default_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new Default_ELG_Op(*this); }
+
+ Default_ELG_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt p;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Fixed_Exponent_Power_Mod powermod_x_p;
+ Modular_Reducer mod_p;
+ };
+
+/*************************************************
+* Default_ELG_Op Constructor *
+*************************************************/
+Default_ELG_Op::Default_ELG_Op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) : p(group.get_p())
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), p);
+ powermod_y_p = Fixed_Base_Power_Mod(y, p);
+ mod_p = Modular_Reducer(p);
+
+ if(x != 0)
+ powermod_x_p = Fixed_Exponent_Power_Mod(x, p);
+ }
+
+/*************************************************
+* Default ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> Default_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ BigInt m(in, length);
+ if(m >= p)
+ throw Invalid_Argument("Default_ELG_Op::encrypt: Input is too large");
+
+ BigInt a = powermod_g_p(k);
+ BigInt b = mod_p.multiply(m, powermod_y_p(k));
+
+ SecureVector<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;
+ }
+
+/*************************************************
+* Default ElGamal Decrypt Operation *
+*************************************************/
+BigInt Default_ELG_Op::decrypt(const BigInt& a, const BigInt& b) const
+ {
+ if(a >= p || b >= p)
+ throw Invalid_Argument("Default_ELG_Op: Invalid message");
+
+ return mod_p.multiply(b, inverse_mod(powermod_x_p(a), p));
+ }
+
+}
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* Default_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_ELG_Op(group, y, x);
+ }
+
+}
diff --git a/src/pk/pubkey/kdf.cpp b/src/pk/pubkey/kdf.cpp
new file mode 100644
index 000000000..dca56e1a6
--- /dev/null
+++ b/src/pk/pubkey/kdf.cpp
@@ -0,0 +1,70 @@
+/*************************************************
+* KDF Base Class Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_util.h>
+#include <botan/lookup.h>
+#include <botan/loadstor.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const std::string& salt) const
+ {
+ return derive_key(key_len, secret, secret.size(),
+ reinterpret_cast<const byte*>(salt.data()),
+ salt.length());
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const byte salt[], u32bit salt_len) const
+ {
+ return derive_key(key_len, secret.begin(), secret.size(),
+ salt, salt_len);
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const MemoryRegion<byte>& salt) const
+ {
+ return derive_key(key_len, secret.begin(), secret.size(),
+ salt.begin(), salt.size());
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const std::string& salt) const
+ {
+ return derive_key(key_len, secret, secret_len,
+ reinterpret_cast<const byte*>(salt.data()),
+ salt.length());
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte salt[], u32bit salt_len) const
+ {
+ return derive(key_len, secret, secret_len, salt, salt_len);
+ }
+
+}
diff --git a/src/pk/pubkey/nr_op.cpp b/src/pk/pubkey/nr_op.cpp
new file mode 100644
index 000000000..01e96a822
--- /dev/null
+++ b/src/pk/pubkey/nr_op.cpp
@@ -0,0 +1,104 @@
+/*************************************************
+* NR Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default NR Operation *
+*************************************************/
+class Default_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new Default_NR_Op(*this); }
+
+ Default_NR_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+/*************************************************
+* Default_NR_Op Constructor *
+*************************************************/
+Default_NR_Op::Default_NR_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p());
+ powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p());
+ mod_p = Modular_Reducer(group.get_p());
+ mod_q = Modular_Reducer(group.get_q());
+ }
+
+/*************************************************
+* Default NR Verify Operation *
+*************************************************/
+SecureVector<byte> Default_NR_Op::verify(const byte in[], u32bit length) const
+ {
+ const BigInt& q = group.get_q();
+
+ if(length != 2*q.bytes())
+ return false;
+
+ BigInt c(in, q.bytes());
+ BigInt d(in + q.bytes(), q.bytes());
+
+ if(c.is_zero() || c >= q || d >= q)
+ throw Invalid_Argument("Default_NR_Op::verify: Invalid signature");
+
+ BigInt i = mod_p.multiply(powermod_g_p(d), powermod_y_p(c));
+ return BigInt::encode(mod_q.reduce(c - i));
+ }
+
+/*************************************************
+* Default NR Sign Operation *
+*************************************************/
+SecureVector<byte> Default_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ if(x == 0)
+ throw Internal_Error("Default_NR_Op::sign: No private key");
+
+ const BigInt& q = group.get_q();
+
+ BigInt f(in, length);
+
+ if(f >= q)
+ throw Invalid_Argument("Default_NR_Op::sign: Input is out of range");
+
+ BigInt c = mod_q.reduce(powermod_g_p(k) + f);
+ if(c.is_zero())
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+ BigInt d = mod_q.reduce(k - x * c);
+
+ SecureVector<byte> output(2*q.bytes());
+ c.binary_encode(output + (output.size() / 2 - c.bytes()));
+ d.binary_encode(output + (output.size() - d.bytes()));
+ return output;
+ }
+
+}
+
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* Default_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_NR_Op(group, y, x);
+ }
+
+}
diff --git a/src/pk/pubkey/pk_algs.cpp b/src/pk/pubkey/pk_algs.cpp
new file mode 100644
index 000000000..83ceb61c7
--- /dev/null
+++ b/src/pk/pubkey/pk_algs.cpp
@@ -0,0 +1,98 @@
+/*************************************************
+* PK Key Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_algs.h>
+
+#ifdef BOTAN_HAS_RSA
+ #include <botan/rsa.h>
+#endif
+
+#ifdef BOTAN_HAS_DSA
+ #include <botan/dsa.h>
+#endif
+
+#ifdef BOTAN_HAS_DH
+ #include <botan/dh.h>
+#endif
+
+#ifdef BOTAN_HAS_NR
+ #include <botan/nr.h>
+#endif
+
+#ifdef BOTAN_HAS_RW
+ #include <botan/rw.h>
+#endif
+
+#ifdef BOTAN_HAS_ELGAMAL
+ #include <botan/elgamal.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Get an PK public key object *
+*************************************************/
+Public_Key* get_public_key(const std::string& alg_name)
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA") return new RSA_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA") return new DSA_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_DH)
+ if(alg_name == "DH") return new DH_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_NR)
+ if(alg_name == "NR") return new NR_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(alg_name == "RW") return new RW_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_ELG)
+ if(alg_name == "ELG") return new ElGamal_PublicKey;
+#endif
+
+ return 0;
+ }
+
+/*************************************************
+* Get an PK private key object *
+*************************************************/
+Private_Key* get_private_key(const std::string& alg_name)
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA") return new RSA_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA") return new DSA_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_DH)
+ if(alg_name == "DH") return new DH_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_NR)
+ if(alg_name == "NR") return new NR_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(alg_name == "RW") return new RW_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_ELG)
+ if(alg_name == "ELG") return new ElGamal_PrivateKey;
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/src/pk/pubkey/pk_algs.h b/src/pk/pubkey/pk_algs.h
new file mode 100644
index 000000000..a8fa5f176
--- /dev/null
+++ b/src/pk/pubkey/pk_algs.h
@@ -0,0 +1,22 @@
+/*************************************************
+* PK Key Factory Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_KEY_FACTORY_H__
+#define BOTAN_PK_KEY_FACTORY_H__
+
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/*************************************************
+* Get an PK key object *
+*************************************************/
+BOTAN_DLL Public_Key* get_public_key(const std::string&);
+BOTAN_DLL Private_Key* get_private_key(const std::string&);
+
+}
+
+#endif
diff --git a/src/pk/pubkey/pk_core.cpp b/src/pk/pubkey/pk_core.cpp
new file mode 100644
index 000000000..82fe4c217
--- /dev/null
+++ b/src/pk/pubkey/pk_core.cpp
@@ -0,0 +1,300 @@
+/*************************************************
+* PK Algorithm Core Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_core.h>
+#include <botan/numthry.h>
+#include <botan/engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS;
+
+}
+
+/*************************************************
+* IF_Core Constructor *
+*************************************************/
+IF_Core::IF_Core(const BigInt& e, const BigInt& n)
+ {
+ op = Engine_Core::if_op(e, n, 0, 0, 0, 0, 0, 0);
+ }
+
+
+/*************************************************
+* IF_Core Constructor *
+*************************************************/
+IF_Core::IF_Core(RandomNumberGenerator& rng,
+ const BigInt& e, const BigInt& n, const BigInt& d,
+ const BigInt& p, const BigInt& q,
+ const BigInt& d1, const BigInt& d2, const BigInt& c)
+ {
+ op = Engine_Core::if_op(e, n, d, p, q, d1, d2, c);
+
+ if(BLINDING_BITS)
+ {
+ BigInt k(rng, std::min(n.bits()-1, BLINDING_BITS));
+ blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n);
+ }
+ }
+
+/*************************************************
+* IF_Core Copy Constructor *
+*************************************************/
+IF_Core::IF_Core(const IF_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ }
+
+/*************************************************
+* IF_Core Assignment Operator *
+*************************************************/
+IF_Core& IF_Core::operator=(const IF_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ return (*this);
+ }
+
+/*************************************************
+* IF Public Operation *
+*************************************************/
+BigInt IF_Core::public_op(const BigInt& i) const
+ {
+ return op->public_op(i);
+ }
+
+/*************************************************
+* IF Private Operation *
+*************************************************/
+BigInt IF_Core::private_op(const BigInt& i) const
+ {
+ return blinder.unblind(op->private_op(blinder.blind(i)));
+ }
+
+/*************************************************
+* DSA_Core Constructor *
+*************************************************/
+DSA_Core::DSA_Core(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::dsa_op(group, y, x);
+ }
+
+/*************************************************
+* DSA_Core Copy Constructor *
+*************************************************/
+DSA_Core::DSA_Core(const DSA_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ }
+
+/*************************************************
+* DSA_Core Assignment Operator *
+*************************************************/
+DSA_Core& DSA_Core::operator=(const DSA_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ return (*this);
+ }
+
+/*************************************************
+* DSA Verification Operation *
+*************************************************/
+bool DSA_Core::verify(const byte msg[], u32bit msg_length,
+ const byte sig[], u32bit sig_length) const
+ {
+ return op->verify(msg, msg_length, sig, sig_length);
+ }
+
+/*************************************************
+* DSA Signature Operation *
+*************************************************/
+SecureVector<byte> DSA_Core::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->sign(in, length, k);
+ }
+
+/*************************************************
+* NR_Core Constructor *
+*************************************************/
+NR_Core::NR_Core(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::nr_op(group, y, x);
+ }
+
+/*************************************************
+* NR_Core Copy Constructor *
+*************************************************/
+NR_Core::NR_Core(const NR_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ }
+
+/*************************************************
+* NR_Core Assignment Operator *
+*************************************************/
+NR_Core& NR_Core::operator=(const NR_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ return (*this);
+ }
+
+/*************************************************
+* NR Verification Operation *
+*************************************************/
+SecureVector<byte> NR_Core::verify(const byte in[], u32bit length) const
+ {
+ return op->verify(in, length);
+ }
+
+/*************************************************
+* NR Signature Operation *
+*************************************************/
+SecureVector<byte> NR_Core::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->sign(in, length, k);
+ }
+
+/*************************************************
+* ELG_Core Constructor *
+*************************************************/
+ELG_Core::ELG_Core(const DL_Group& group, const BigInt& y)
+ {
+ op = Engine_Core::elg_op(group, y, 0);
+ p_bytes = 0;
+ }
+
+/*************************************************
+* ELG_Core Constructor *
+*************************************************/
+ELG_Core::ELG_Core(RandomNumberGenerator& rng,
+ const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::elg_op(group, y, x);
+
+ const BigInt& p = group.get_p();
+ p_bytes = p.bytes();
+
+ if(BLINDING_BITS)
+ {
+ BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS));
+ blinder = Blinder(k, power_mod(k, x, p), p);
+ }
+ }
+
+/*************************************************
+* ELG_Core Copy Constructor *
+*************************************************/
+ELG_Core::ELG_Core(const ELG_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ p_bytes = core.p_bytes;
+ }
+
+/*************************************************
+* ELG_Core Assignment Operator *
+*************************************************/
+ELG_Core& ELG_Core::operator=(const ELG_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ p_bytes = core.p_bytes;
+ return (*this);
+ }
+
+/*************************************************
+* ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> ELG_Core::encrypt(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->encrypt(in, length, k);
+ }
+
+/*************************************************
+* ElGamal Decrypt Operation *
+*************************************************/
+SecureVector<byte> ELG_Core::decrypt(const byte in[], u32bit length) const
+ {
+ if(length != 2*p_bytes)
+ throw Invalid_Argument("ELG_Core::decrypt: Invalid message");
+
+ BigInt a(in, p_bytes);
+ BigInt b(in + p_bytes, p_bytes);
+
+ return BigInt::encode(blinder.unblind(op->decrypt(blinder.blind(a), b)));
+ }
+
+/*************************************************
+* DH_Core Constructor *
+*************************************************/
+DH_Core::DH_Core(RandomNumberGenerator& rng,
+ const DL_Group& group, const BigInt& x)
+ {
+ op = Engine_Core::dh_op(group, x);
+
+ const BigInt& p = group.get_p();
+
+ BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS));
+
+ if(k != 0)
+ blinder = Blinder(k, power_mod(inverse_mod(k, p), x, p), p);
+ }
+
+/*************************************************
+* DH_Core Copy Constructor *
+*************************************************/
+DH_Core::DH_Core(const DH_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ }
+
+/*************************************************
+* DH_Core Assignment Operator *
+*************************************************/
+DH_Core& DH_Core::operator=(const DH_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ return (*this);
+ }
+
+/*************************************************
+* DH Operation *
+*************************************************/
+BigInt DH_Core::agree(const BigInt& i) const
+ {
+ return blinder.unblind(op->agree(blinder.blind(i)));
+ }
+
+}
diff --git a/src/pk/pubkey/pk_core.h b/src/pk/pubkey/pk_core.h
new file mode 100644
index 000000000..585c12ee4
--- /dev/null
+++ b/src/pk/pubkey/pk_core.h
@@ -0,0 +1,128 @@
+/*************************************************
+* PK Algorithm Core Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_CORE_H__
+#define BOTAN_PK_CORE_H__
+
+#include <botan/bigint.h>
+#include <botan/dl_group.h>
+#include <botan/blinding.h>
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+/*************************************************
+* IF Core *
+*************************************************/
+class BOTAN_DLL IF_Core
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Core& operator=(const IF_Core&);
+
+ IF_Core() { op = 0; }
+ IF_Core(const IF_Core&);
+
+ IF_Core(const BigInt&, const BigInt&);
+
+ IF_Core(RandomNumberGenerator& rng,
+ const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&);
+
+ ~IF_Core() { delete op; }
+ private:
+ IF_Operation* op;
+ Blinder blinder;
+ };
+
+/*************************************************
+* DSA Core *
+*************************************************/
+class BOTAN_DLL DSA_Core
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+
+ DSA_Core& operator=(const DSA_Core&);
+
+ DSA_Core() { op = 0; }
+ DSA_Core(const DSA_Core&);
+ DSA_Core(const DL_Group&, const BigInt&, const BigInt& = 0);
+ ~DSA_Core() { delete op; }
+ private:
+ DSA_Operation* op;
+ };
+
+/*************************************************
+* NR Core *
+*************************************************/
+class BOTAN_DLL NR_Core
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ NR_Core& operator=(const NR_Core&);
+
+ NR_Core() { op = 0; }
+ NR_Core(const NR_Core&);
+ NR_Core(const DL_Group&, const BigInt&, const BigInt& = 0);
+ ~NR_Core() { delete op; }
+ private:
+ NR_Operation* op;
+ };
+
+/*************************************************
+* ElGamal Core *
+*************************************************/
+class BOTAN_DLL ELG_Core
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ ELG_Core& operator=(const ELG_Core&);
+
+ ELG_Core() { op = 0; }
+ ELG_Core(const ELG_Core&);
+
+ ELG_Core(const DL_Group&, const BigInt&);
+ ELG_Core(RandomNumberGenerator&, const DL_Group&,
+ const BigInt&, const BigInt&);
+
+ ~ELG_Core() { delete op; }
+ private:
+ ELG_Operation* op;
+ Blinder blinder;
+ u32bit p_bytes;
+ };
+
+/*************************************************
+* DH Core *
+*************************************************/
+class BOTAN_DLL DH_Core
+ {
+ public:
+ BigInt agree(const BigInt&) const;
+
+ DH_Core& operator=(const DH_Core&);
+
+ DH_Core() { op = 0; }
+ DH_Core(const DH_Core&);
+ DH_Core(RandomNumberGenerator& rng,
+ const DL_Group&, const BigInt&);
+ ~DH_Core() { delete op; }
+ private:
+ DH_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/src/pk/pubkey/pk_keys.cpp b/src/pk/pubkey/pk_keys.cpp
new file mode 100644
index 000000000..d991f3788
--- /dev/null
+++ b/src/pk/pubkey/pk_keys.cpp
@@ -0,0 +1,68 @@
+/*************************************************
+* PK Key Types Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_keys.h>
+#include <botan/libstate.h>
+#include <botan/oids.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Find out how much testing should be performed *
+*************************************************/
+bool key_check_level(const std::string& type)
+ {
+ const std::string setting = global_state().option("pk/test/" + type);
+ if(setting == "basic")
+ return false;
+ return true;
+ }
+
+}
+
+/*************************************************
+* 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, key_check_level("public")))
+ 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, key_check_level("private")))
+ 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, key_check_level("private_gen")))
+ throw Self_Test_Failure(algo_name() + " private key generation failed");
+ }
+
+}
diff --git a/src/pk/pubkey/pk_keys.h b/src/pk/pubkey/pk_keys.h
new file mode 100644
index 000000000..16109c634
--- /dev/null
+++ b/src/pk/pubkey/pk_keys.h
@@ -0,0 +1,127 @@
+/*************************************************
+* PK Key Types Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_KEYS_H__
+#define BOTAN_PK_KEYS_H__
+
+#include <botan/secmem.h>
+#include <botan/asn1_oid.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*************************************************
+* Public Key Base Class *
+*************************************************/
+class BOTAN_DLL Public_Key
+ {
+ public:
+ virtual std::string algo_name() const = 0;
+ virtual OID get_oid() const;
+
+ virtual bool check_key(RandomNumberGenerator&, bool) const
+ { return true; }
+
+ virtual u32bit message_parts() const { return 1; }
+ virtual u32bit message_part_size() const { return 0; }
+ virtual u32bit max_input_bits() const = 0;
+
+ virtual class X509_Encoder* x509_encoder() const = 0;
+ virtual class X509_Decoder* x509_decoder() = 0;
+
+ virtual ~Public_Key() {}
+ protected:
+ virtual void load_check(RandomNumberGenerator&) const;
+ };
+
+/*************************************************
+* Private Key Base Class *
+*************************************************/
+class BOTAN_DLL Private_Key : public virtual Public_Key
+ {
+ public:
+ virtual class PKCS8_Encoder* pkcs8_encoder() const
+ { return 0; }
+ virtual class PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&)
+ { return 0; }
+ protected:
+ void load_check(RandomNumberGenerator&) const;
+ void gen_check(RandomNumberGenerator&) const;
+ };
+
+/*************************************************
+* PK Encrypting Key *
+*************************************************/
+class BOTAN_DLL PK_Encrypting_Key : public virtual Public_Key
+ {
+ public:
+ virtual SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator&) const = 0;
+ virtual ~PK_Encrypting_Key() {}
+ };
+
+/*************************************************
+* PK Decrypting Key *
+*************************************************/
+class BOTAN_DLL PK_Decrypting_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> decrypt(const byte[], u32bit) const = 0;
+ virtual ~PK_Decrypting_Key() {}
+ };
+
+/*************************************************
+* PK Signing Key *
+*************************************************/
+class BOTAN_DLL PK_Signing_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const = 0;
+ virtual ~PK_Signing_Key() {}
+ };
+
+/*************************************************
+* PK Verifying Key, Message Recovery Version *
+*************************************************/
+class BOTAN_DLL PK_Verifying_with_MR_Key : public virtual Public_Key
+ {
+ public:
+ virtual SecureVector<byte> verify(const byte[], u32bit) const = 0;
+ virtual ~PK_Verifying_with_MR_Key() {}
+ };
+
+/*************************************************
+* PK Verifying Key, No Message Recovery Version *
+*************************************************/
+class BOTAN_DLL PK_Verifying_wo_MR_Key : public virtual Public_Key
+ {
+ public:
+ virtual bool verify(const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ virtual ~PK_Verifying_wo_MR_Key() {}
+ };
+
+/*************************************************
+* PK Secret Value Derivation Key *
+*************************************************/
+class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> derive_key(const byte[], u32bit) const = 0;
+ virtual MemoryVector<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/pk/pubkey/pk_ops.h b/src/pk/pubkey/pk_ops.h
new file mode 100644
index 000000000..fad87b573
--- /dev/null
+++ b/src/pk/pubkey/pk_ops.h
@@ -0,0 +1,79 @@
+/*************************************************
+* Public Key Operations Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_OPS_H__
+#define BOTAN_PK_OPS_H__
+
+#include <botan/bigint.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*************************************************
+* IF Operation *
+*************************************************/
+class BOTAN_DLL IF_Operation
+ {
+ public:
+ virtual BigInt public_op(const BigInt&) const = 0;
+ virtual BigInt private_op(const BigInt&) const = 0;
+ virtual IF_Operation* clone() const = 0;
+ virtual ~IF_Operation() {}
+ };
+
+/*************************************************
+* DSA Operation *
+*************************************************/
+class BOTAN_DLL DSA_Operation
+ {
+ public:
+ virtual bool verify(const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual DSA_Operation* clone() const = 0;
+ virtual ~DSA_Operation() {}
+ };
+
+/*************************************************
+* NR Operation *
+*************************************************/
+class BOTAN_DLL NR_Operation
+ {
+ public:
+ virtual SecureVector<byte> verify(const byte[], u32bit) const = 0;
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual NR_Operation* clone() const = 0;
+ virtual ~NR_Operation() {}
+ };
+
+/*************************************************
+* ElGamal Operation *
+*************************************************/
+class BOTAN_DLL ELG_Operation
+ {
+ public:
+ virtual SecureVector<byte> encrypt(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual BigInt decrypt(const BigInt&, const BigInt&) const = 0;
+ virtual ELG_Operation* clone() const = 0;
+ virtual ~ELG_Operation() {}
+ };
+
+/*************************************************
+* DH Operation *
+*************************************************/
+class BOTAN_DLL DH_Operation
+ {
+ public:
+ virtual BigInt agree(const BigInt&) const = 0;
+ virtual DH_Operation* clone() const = 0;
+ virtual ~DH_Operation() {}
+ };
+
+}
+
+#endif
diff --git a/src/pk/pubkey/pk_util.cpp b/src/pk/pubkey/pk_util.cpp
new file mode 100644
index 000000000..1976436ea
--- /dev/null
+++ b/src/pk/pubkey/pk_util.cpp
@@ -0,0 +1,48 @@
+/*************************************************
+* PK Utility Classes Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_util.h>
+
+namespace Botan {
+
+/*************************************************
+* Encode a message *
+*************************************************/
+SecureVector<byte> EME::encode(const byte msg[], u32bit msg_len,
+ u32bit key_bits,
+ RandomNumberGenerator& rng) const
+ {
+ return pad(msg, msg_len, key_bits, rng);
+ }
+
+/*************************************************
+* Encode a message *
+*************************************************/
+SecureVector<byte> EME::encode(const MemoryRegion<byte>& msg,
+ u32bit key_bits,
+ RandomNumberGenerator& rng) const
+ {
+ return pad(msg, msg.size(), key_bits, rng);
+ }
+
+/*************************************************
+* Decode a message *
+*************************************************/
+SecureVector<byte> EME::decode(const byte msg[], u32bit msg_len,
+ u32bit key_bits) const
+ {
+ return unpad(msg, msg_len, key_bits);
+ }
+
+/*************************************************
+* Decode a message *
+*************************************************/
+SecureVector<byte> EME::decode(const MemoryRegion<byte>& msg,
+ u32bit key_bits) const
+ {
+ return unpad(msg, msg.size(), key_bits);
+ }
+
+}
diff --git a/src/pk/pubkey/pk_util.h b/src/pk/pubkey/pk_util.h
new file mode 100644
index 000000000..aa7a71234
--- /dev/null
+++ b/src/pk/pubkey/pk_util.h
@@ -0,0 +1,92 @@
+/*************************************************
+* PK Utility Classes Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PUBKEY_UTIL_H__
+#define BOTAN_PUBKEY_UTIL_H__
+
+#include <botan/base.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*************************************************
+* Encoding Method for Encryption *
+*************************************************/
+class BOTAN_DLL EME
+ {
+ public:
+ virtual u32bit maximum_input_size(u32bit) const = 0;
+
+ SecureVector<byte> encode(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> encode(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator&) const;
+
+ SecureVector<byte> decode(const byte[], u32bit, u32bit) const;
+ SecureVector<byte> decode(const MemoryRegion<byte>&, u32bit) const;
+
+ virtual ~EME() {}
+ private:
+ virtual SecureVector<byte> pad(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const = 0;
+
+ virtual SecureVector<byte> unpad(const byte[], u32bit, u32bit) const = 0;
+ };
+
+/*************************************************
+* Encoding Method for Signatures, Appendix *
+*************************************************/
+class BOTAN_DLL EMSA
+ {
+ public:
+ virtual void update(const byte[], u32bit) = 0;
+ virtual SecureVector<byte> raw_data() = 0;
+
+ virtual SecureVector<byte> encoding_of(const MemoryRegion<byte>&,
+ u32bit,
+ RandomNumberGenerator& rng) = 0;
+
+ virtual bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw() = 0;
+ virtual ~EMSA() {}
+ };
+
+/*************************************************
+* Key Derivation Function *
+*************************************************/
+class BOTAN_DLL KDF
+ {
+ public:
+ SecureVector<byte> derive_key(u32bit, const MemoryRegion<byte>&,
+ const std::string& = "") const;
+ SecureVector<byte> derive_key(u32bit, const MemoryRegion<byte>&,
+ const MemoryRegion<byte>&) const;
+ SecureVector<byte> derive_key(u32bit, const MemoryRegion<byte>&,
+ const byte[], u32bit) const;
+
+ SecureVector<byte> derive_key(u32bit, const byte[], u32bit,
+ const std::string& = "") const;
+ SecureVector<byte> derive_key(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ virtual ~KDF() {}
+ private:
+ virtual SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ };
+
+/*************************************************
+* Mask Generation Function *
+*************************************************/
+class BOTAN_DLL MGF
+ {
+ public:
+ virtual void mask(const byte[], u32bit, byte[], u32bit) const = 0;
+ virtual ~MGF() {}
+ };
+
+}
+
+#endif
diff --git a/src/pk/pubkey/pkcs8.cpp b/src/pk/pubkey/pkcs8.cpp
new file mode 100644
index 000000000..2963c9d86
--- /dev/null
+++ b/src/pk/pubkey/pkcs8.cpp
@@ -0,0 +1,307 @@
+/*************************************************
+* PKCS #8 Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/pkcs8.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_obj.h>
+#include <botan/pk_algs.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/lookup.h>
+#include <memory>
+
+namespace Botan {
+
+namespace PKCS8 {
+
+namespace {
+
+/*************************************************
+* Get info from an EncryptedPrivateKeyInfo *
+*************************************************/
+SecureVector<byte> PKCS8_extract(DataSource& source,
+ AlgorithmIdentifier& pbe_alg_id)
+ {
+ SecureVector<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 *
+*************************************************/
+SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
+ AlgorithmIdentifier& pk_alg_id)
+ {
+ AlgorithmIdentifier pbe_alg_id;
+ SecureVector<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.is_empty())
+ throw PKCS8_Exception("No key data found");
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error("PKCS #8 private key decoding failed");
+ }
+
+ if(!is_encrypted)
+ key = key_data;
+
+ const u32bit MAX_TRIES = 3;
+
+ u32bit tries = 0;
+ while(true)
+ {
+ try {
+ if(MAX_TRIES && tries >= MAX_TRIES)
+ break;
+
+ if(is_encrypted)
+ {
+ DataSource_Memory params(pbe_alg_id.parameters);
+ PBE* pbe = get_pbe(pbe_alg_id.oid, params);
+
+ User_Interface::UI_Result result = User_Interface::OK;
+ const std::string passphrase =
+ ui.get_passphrase("PKCS #8 private key", source.id(), result);
+
+ if(result == User_Interface::CANCEL_ACTION)
+ break;
+
+ pbe->set_key(passphrase);
+ Pipe decryptor(pbe);
+ decryptor.process_msg(key_data, key_data.size());
+ key = decryptor.read_all();
+ }
+
+ u32bit version;
+
+ BER_Decoder(key)
+ .start_cons(SEQUENCE)
+ .decode(version)
+ .decode(pk_alg_id)
+ .decode(key, OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+
+ if(version != 0)
+ throw Decoding_Error("PKCS #8: Unknown version number");
+
+ break;
+ }
+ catch(Decoding_Error)
+ {
+ ++tries;
+ }
+ }
+
+ if(key.is_empty())
+ throw Decoding_Error("PKCS #8 private key decoding failed");
+ return key;
+ }
+
+}
+
+/*************************************************
+* DER or PEM encode a PKCS #8 private key *
+*************************************************/
+void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding)
+ {
+ std::auto_ptr<PKCS8_Encoder> encoder(key.pkcs8_encoder());
+ if(!encoder.get())
+ throw Encoding_Error("PKCS8::encode: Key does not support encoding");
+
+ const u32bit PKCS8_VERSION = 0;
+
+ SecureVector<byte> contents =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(encoder->alg_id())
+ .encode(encoder->key_bits(), OCTET_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(contents, "PRIVATE KEY"));
+ else
+ pipe.write(contents);
+ }
+
+/*************************************************
+* Encode and encrypt a PKCS #8 private key *
+*************************************************/
+void encrypt_key(const Private_Key& key,
+ Pipe& pipe,
+ RandomNumberGenerator& rng,
+ const std::string& pass, const std::string& pbe_algo,
+ X509_Encoding encoding)
+ {
+ const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,TripleDES/CBC)";
+
+ Pipe raw_key;
+ raw_key.start_msg();
+ encode(key, raw_key, RAW_BER);
+ raw_key.end_msg();
+
+ PBE* pbe = get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE));
+ pbe->new_params(rng);
+ pbe->set_key(pass);
+
+ Pipe key_encrytor(pbe);
+ key_encrytor.process_msg(raw_key);
+
+ SecureVector<byte> enc_key =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(AlgorithmIdentifier(pbe->get_oid(), pbe->encode_params()))
+ .encode(key_encrytor.read_all(), OCTET_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(enc_key, "ENCRYPTED PRIVATE KEY"));
+ else
+ pipe.write(enc_key);
+ }
+
+/*************************************************
+* PEM encode a PKCS #8 private key *
+*************************************************/
+std::string PEM_encode(const Private_Key& key)
+ {
+ Pipe pem;
+ pem.start_msg();
+ encode(key, pem, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*************************************************
+* Encrypt and PEM encode a PKCS #8 private key *
+*************************************************/
+std::string PEM_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ const std::string& pbe_algo)
+ {
+ if(pass == "")
+ return PEM_encode(key);
+
+ Pipe pem;
+ pem.start_msg();
+ encrypt_key(key, pem, rng, pass, pbe_algo, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*************************************************
+* Extract a private key and return it *
+*************************************************/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui)
+ {
+ AlgorithmIdentifier alg_id;
+ SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, 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());
+
+ std::auto_ptr<Private_Key> key(get_private_key(alg_name));
+
+ if(!key.get())
+ throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder(rng));
+
+ if(!decoder.get())
+ throw Decoding_Error("Key does not support PKCS #8 decoding");
+
+ decoder->alg_id(alg_id);
+ decoder->key_bits(pkcs8_key);
+
+ return key.release();
+ }
+
+/*************************************************
+* Extract a private key and return it *
+*************************************************/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui)
+ {
+ DataSource_Stream source(fsname, true);
+ return PKCS8::load_key(source, rng, ui);
+ }
+
+/*************************************************
+* 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, User_Interface(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, User_Interface(pass));
+ }
+
+/*************************************************
+* Make a copy of this private key *
+*************************************************/
+Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ Pipe bits;
+
+ bits.start_msg();
+ PKCS8::encode(key, bits);
+ bits.end_msg();
+
+ DataSource_Memory source(bits.read_all());
+ return PKCS8::load_key(source, rng);
+ }
+
+}
+
+}
diff --git a/src/pk/pubkey/pkcs8.h b/src/pk/pubkey/pkcs8.h
new file mode 100644
index 000000000..383b1604a
--- /dev/null
+++ b/src/pk/pubkey/pkcs8.h
@@ -0,0 +1,85 @@
+/*************************************************
+* PKCS #8 Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PKCS8_H__
+#define BOTAN_PKCS8_H__
+
+#include <botan/x509_key.h>
+#include <botan/ui.h>
+#include <botan/enums.h>
+
+namespace Botan {
+
+/*************************************************
+* PKCS #8 Private Key Encoder *
+*************************************************/
+class BOTAN_DLL PKCS8_Encoder
+ {
+ public:
+ virtual AlgorithmIdentifier alg_id() const = 0;
+ virtual MemoryVector<byte> key_bits() const = 0;
+ virtual ~PKCS8_Encoder() {}
+ };
+
+/*************************************************
+* PKCS #8 Private Key Decoder *
+*************************************************/
+class BOTAN_DLL PKCS8_Decoder
+ {
+ public:
+ virtual void alg_id(const AlgorithmIdentifier&) = 0;
+ virtual void key_bits(const MemoryRegion<byte>&) = 0;
+ virtual ~PKCS8_Decoder() {}
+ };
+
+/*************************************************
+* PKCS #8 General Exception *
+*************************************************/
+struct BOTAN_DLL PKCS8_Exception : public Decoding_Error
+ {
+ PKCS8_Exception(const std::string& error) :
+ Decoding_Error("PKCS #8: " + error) {}
+ };
+
+namespace PKCS8 {
+
+/*************************************************
+* PKCS #8 Private Key Encoding/Decoding *
+*************************************************/
+BOTAN_DLL void encode(const Private_Key&, Pipe&, X509_Encoding = PEM);
+BOTAN_DLL std::string PEM_encode(const Private_Key&);
+
+BOTAN_DLL void encrypt_key(const Private_Key&,
+ Pipe&,
+ RandomNumberGenerator&,
+ const std::string&,
+ const std::string& = "",
+ X509_Encoding = PEM);
+
+BOTAN_DLL std::string PEM_encode(const Private_Key&,
+ RandomNumberGenerator&,
+ const std::string&,
+ const std::string& = "");
+
+BOTAN_DLL Private_Key* load_key(DataSource&, RandomNumberGenerator&,
+ const User_Interface&);
+BOTAN_DLL Private_Key* load_key(DataSource&, RandomNumberGenerator&,
+ const std::string& = "");
+
+BOTAN_DLL Private_Key* load_key(const std::string&,
+ RandomNumberGenerator&,
+ const User_Interface&);
+BOTAN_DLL Private_Key* load_key(const std::string&,
+ RandomNumberGenerator&,
+ const std::string& = "");
+
+BOTAN_DLL Private_Key* copy_key(const Private_Key&,
+ RandomNumberGenerator& rng);
+
+}
+
+}
+
+#endif
diff --git a/src/pk/pubkey/pubkey.cpp b/src/pk/pubkey/pubkey.cpp
new file mode 100644
index 000000000..06bb44bca
--- /dev/null
+++ b/src/pk/pubkey/pubkey.cpp
@@ -0,0 +1,415 @@
+/*************************************************
+* Public Key Base Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pubkey.h>
+#include <botan/lookup.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/bigint.h>
+#include <botan/parsing.h>
+#include <botan/bit_ops.h>
+#include <memory>
+
+namespace Botan {
+
+/*************************************************
+* Encrypt a message *
+*************************************************/
+SecureVector<byte> PK_Encryptor::encrypt(const byte in[], u32bit len,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(in, len, rng);
+ }
+
+/*************************************************
+* Encrypt a message *
+*************************************************/
+SecureVector<byte> PK_Encryptor::encrypt(const MemoryRegion<byte>& in,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(in.begin(), in.size(), rng);
+ }
+
+/*************************************************
+* Decrypt a message *
+*************************************************/
+SecureVector<byte> PK_Decryptor::decrypt(const byte in[], u32bit len) const
+ {
+ return dec(in, len);
+ }
+
+/*************************************************
+* Decrypt a message *
+*************************************************/
+SecureVector<byte> PK_Decryptor::decrypt(const MemoryRegion<byte>& in) const
+ {
+ return dec(in.begin(), in.size());
+ }
+
+/*************************************************
+* PK_Encryptor_MR_with_EME Constructor *
+*************************************************/
+PK_Encryptor_MR_with_EME::PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& k,
+ const std::string& eme) :
+ key(k), encoder((eme == "Raw") ? 0 : get_eme(eme))
+ {
+ }
+
+/*************************************************
+* Encrypt a message *
+*************************************************/
+SecureVector<byte>
+PK_Encryptor_MR_with_EME::enc(const byte msg[],
+ u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ SecureVector<byte> message;
+ if(encoder)
+ message = encoder->encode(msg, length, key.max_input_bits(), rng);
+ else
+ message.set(msg, length);
+
+ if(8*(message.size() - 1) + high_bit(message[0]) > key.max_input_bits())
+ throw Exception("PK_Encryptor_MR_with_EME: Input is too large");
+
+ return key.encrypt(message, message.size(), rng);
+ }
+
+/*************************************************
+* Return the max size, in bytes, of a message *
+*************************************************/
+u32bit PK_Encryptor_MR_with_EME::maximum_input_size() const
+ {
+ if(!encoder)
+ return (key.max_input_bits() / 8);
+ else
+ return encoder->maximum_input_size(key.max_input_bits());
+ }
+
+/*************************************************
+* PK_Decryptor_MR_with_EME Constructor *
+*************************************************/
+PK_Decryptor_MR_with_EME::PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& k,
+ const std::string& eme) :
+ key(k), encoder((eme == "Raw") ? 0 : get_eme(eme))
+ {
+ }
+
+/*************************************************
+* Decrypt a message *
+*************************************************/
+SecureVector<byte> PK_Decryptor_MR_with_EME::dec(const byte msg[],
+ u32bit length) const
+ {
+ try {
+ SecureVector<byte> decrypted = key.decrypt(msg, length);
+ if(encoder)
+ return encoder->decode(decrypted, key.max_input_bits());
+ else
+ return decrypted;
+ }
+ catch(Invalid_Argument)
+ {
+ throw Exception("PK_Decryptor_MR_with_EME: Input is invalid");
+ }
+ catch(Decoding_Error)
+ {
+ throw Exception("PK_Decryptor_MR_with_EME: Input is invalid");
+ }
+ }
+
+/*************************************************
+* PK_Signer Constructor *
+*************************************************/
+PK_Signer::PK_Signer(const PK_Signing_Key& k, const std::string& emsa_name) :
+ key(k), emsa(get_emsa(emsa_name))
+ {
+ sig_format = IEEE_1363;
+ }
+
+/*************************************************
+* Set the signature format *
+*************************************************/
+void PK_Signer::set_output_format(Signature_Format format)
+ {
+ if(key.message_parts() == 1 && format != IEEE_1363)
+ throw Invalid_State("PK_Signer: Cannot set the output format for " +
+ key.algo_name() + " keys");
+ sig_format = format;
+ }
+
+/*************************************************
+* Sign a message *
+*************************************************/
+SecureVector<byte> PK_Signer::sign_message(const byte msg[], u32bit length,
+ RandomNumberGenerator& rng)
+ {
+ update(msg, length);
+ return signature(rng);
+ }
+
+/*************************************************
+* Sign a message *
+*************************************************/
+SecureVector<byte> PK_Signer::sign_message(const MemoryRegion<byte>& msg,
+ RandomNumberGenerator& rng)
+ {
+ return sign_message(msg, msg.size(), rng);
+ }
+
+/*************************************************
+* Add more to the message to be signed *
+*************************************************/
+void PK_Signer::update(const byte in[], u32bit length)
+ {
+ emsa->update(in, length);
+ }
+
+/*************************************************
+* Add more to the message to be signed *
+*************************************************/
+void PK_Signer::update(byte in)
+ {
+ update(&in, 1);
+ }
+
+/*************************************************
+* Add more to the message to be signed *
+*************************************************/
+void PK_Signer::update(const MemoryRegion<byte>& in)
+ {
+ update(in, in.size());
+ }
+
+/*************************************************
+* Create a signature *
+*************************************************/
+SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
+ {
+ SecureVector<byte> encoded = emsa->encoding_of(emsa->raw_data(),
+ key.max_input_bits(),
+ rng);
+
+ SecureVector<byte> plain_sig = key.sign(encoded, encoded.size(), rng);
+
+ if(key.message_parts() == 1 || sig_format == IEEE_1363)
+ return plain_sig;
+
+ if(sig_format == DER_SEQUENCE)
+ {
+ if(plain_sig.size() % key.message_parts())
+ throw Encoding_Error("PK_Signer: strange signature size found");
+ const u32bit SIZE_OF_PART = plain_sig.size() / key.message_parts();
+
+ std::vector<BigInt> sig_parts(key.message_parts());
+ for(u32bit 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();
+ }
+ else
+ throw Encoding_Error("PK_Signer: Unknown signature format " +
+ to_string(sig_format));
+ }
+
+/*************************************************
+* PK_Verifier Constructor *
+*************************************************/
+PK_Verifier::PK_Verifier(const std::string& emsa_name)
+ {
+ emsa = get_emsa(emsa_name);
+ sig_format = IEEE_1363;
+ }
+
+/*************************************************
+* PK_Verifier Destructor *
+*************************************************/
+PK_Verifier::~PK_Verifier()
+ {
+ delete emsa;
+ }
+
+/*************************************************
+* Set the signature format *
+*************************************************/
+void PK_Verifier::set_input_format(Signature_Format format)
+ {
+ if(key_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 MemoryRegion<byte>& msg,
+ const MemoryRegion<byte>& sig)
+ {
+ return verify_message(msg, msg.size(), sig, sig.size());
+ }
+
+/*************************************************
+* Verify a message *
+*************************************************/
+bool PK_Verifier::verify_message(const byte msg[], u32bit msg_length,
+ const byte sig[], u32bit sig_length)
+ {
+ update(msg, msg_length);
+ return check_signature(sig, sig_length);
+ }
+
+/*************************************************
+* Append to the message *
+*************************************************/
+void PK_Verifier::update(const byte in[], u32bit length)
+ {
+ emsa->update(in, length);
+ }
+
+/*************************************************
+* Append to the message *
+*************************************************/
+void PK_Verifier::update(byte in)
+ {
+ update(&in, 1);
+ }
+
+/*************************************************
+* Append to the message *
+*************************************************/
+void PK_Verifier::update(const MemoryRegion<byte>& in)
+ {
+ update(in, in.size());
+ }
+
+/*************************************************
+* Check a signature *
+*************************************************/
+bool PK_Verifier::check_signature(const MemoryRegion<byte>& sig)
+ {
+ return check_signature(sig, sig.size());
+ }
+
+/*************************************************
+* Check a signature *
+*************************************************/
+bool PK_Verifier::check_signature(const byte sig[], u32bit 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);
+
+ u32bit count = 0;
+ SecureVector<byte> real_sig;
+ while(ber_sig.more_items())
+ {
+ BigInt sig_part;
+ ber_sig.decode(sig_part);
+ real_sig.append(BigInt::encode_1363(sig_part,
+ key_message_part_size()));
+ ++count;
+ }
+ if(count != key_message_parts())
+ throw Decoding_Error("PK_Verifier: signature size invalid");
+
+ return validate_signature(emsa->raw_data(),
+ real_sig, real_sig.size());
+ }
+ else
+ throw Decoding_Error("PK_Verifier: Unknown signature format " +
+ to_string(sig_format));
+ }
+ catch(Invalid_Argument) { return false; }
+ catch(Decoding_Error) { return false; }
+ }
+
+/*************************************************
+* PK_Verifier_with_MR Constructor *
+*************************************************/
+PK_Verifier_with_MR::PK_Verifier_with_MR(const PK_Verifying_with_MR_Key& k,
+ const std::string& emsa_name) :
+ PK_Verifier(emsa_name), key(k)
+ {
+ }
+
+/*************************************************
+* Verify a signature *
+*************************************************/
+bool PK_Verifier_with_MR::validate_signature(const MemoryRegion<byte>& msg,
+ const byte sig[], u32bit sig_len)
+ {
+ SecureVector<byte> output_of_key = key.verify(sig, sig_len);
+ return emsa->verify(output_of_key, msg, key.max_input_bits());
+ }
+
+/*************************************************
+* PK_Verifier_wo_MR Constructor *
+*************************************************/
+PK_Verifier_wo_MR::PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key& k,
+ const std::string& emsa_name) :
+ PK_Verifier(emsa_name), key(k)
+ {
+ }
+
+/*************************************************
+* Verify a signature *
+*************************************************/
+bool PK_Verifier_wo_MR::validate_signature(const MemoryRegion<byte>& msg,
+ const byte sig[], u32bit sig_len)
+ {
+ Null_RNG rng;
+
+ SecureVector<byte> encoded =
+ emsa->encoding_of(msg, key.max_input_bits(), rng);
+
+ return key.verify(encoded, encoded.size(), sig, sig_len);
+ }
+
+/*************************************************
+* PK_Key_Agreement Constructor *
+*************************************************/
+PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& k,
+ const std::string& k_name) :
+ key(k), kdf_name(k_name)
+ {
+ }
+
+/*************************************************
+* Perform Key Agreement Operation *
+*************************************************/
+SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len,
+ const byte in[], u32bit 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 *
+*************************************************/
+SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len, const byte in[],
+ u32bit in_len, const byte params[],
+ u32bit params_len) const
+ {
+ std::auto_ptr<KDF> kdf((kdf_name == "Raw") ? 0 : get_kdf(kdf_name));
+ OctetString z = key.derive_key(in, in_len);
+
+ if(kdf.get())
+ z = kdf->derive_key(key_len, z.bits_of(), params, params_len);
+
+ return z;
+ }
+
+}
diff --git a/src/pk/pubkey/pubkey.h b/src/pk/pubkey/pubkey.h
new file mode 100644
index 000000000..0c9abf18f
--- /dev/null
+++ b/src/pk/pubkey/pubkey.h
@@ -0,0 +1,210 @@
+/*************************************************
+* Public Key Interface Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PUBKEY_H__
+#define BOTAN_PUBKEY_H__
+
+#include <botan/base.h>
+#include <botan/pk_keys.h>
+#include <botan/pk_util.h>
+
+namespace Botan {
+
+enum Signature_Format { IEEE_1363, DER_SEQUENCE };
+
+/*************************************************
+* Public Key Encryptor *
+*************************************************/
+class BOTAN_DLL PK_Encryptor
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> encrypt(const MemoryRegion<byte>&,
+ RandomNumberGenerator&) const;
+
+ virtual u32bit maximum_input_size() const = 0;
+ virtual ~PK_Encryptor() {}
+ private:
+ virtual SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator&) const = 0;
+ };
+
+/*************************************************
+* Public Key Decryptor *
+*************************************************/
+class BOTAN_DLL PK_Decryptor
+ {
+ public:
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+ SecureVector<byte> decrypt(const MemoryRegion<byte>&) const;
+ virtual ~PK_Decryptor() {}
+ private:
+ virtual SecureVector<byte> dec(const byte[], u32bit) const = 0;
+ };
+
+/*************************************************
+* Public Key Signer *
+*************************************************/
+class BOTAN_DLL PK_Signer
+ {
+ public:
+ SecureVector<byte> sign_message(const byte[], u32bit,
+ RandomNumberGenerator&);
+ SecureVector<byte> sign_message(const MemoryRegion<byte>&,
+ RandomNumberGenerator&);
+
+ void update(byte);
+ void update(const byte[], u32bit);
+ void update(const MemoryRegion<byte>&);
+
+ SecureVector<byte> signature(RandomNumberGenerator&);
+
+ void set_output_format(Signature_Format);
+
+ PK_Signer(const PK_Signing_Key&, const std::string&);
+ ~PK_Signer() { delete emsa; }
+ private:
+ PK_Signer(const PK_Signer&);
+ PK_Signer& operator=(const PK_Signer&);
+
+ const PK_Signing_Key& key;
+ Signature_Format sig_format;
+ EMSA* emsa;
+ };
+
+/*************************************************
+* Public Key Verifier *
+*************************************************/
+class BOTAN_DLL PK_Verifier
+ {
+ public:
+ bool verify_message(const byte[], u32bit, const byte[], u32bit);
+ bool verify_message(const MemoryRegion<byte>&,
+ const MemoryRegion<byte>&);
+
+ void update(byte);
+ void update(const byte[], u32bit);
+ void update(const MemoryRegion<byte>&);
+
+ bool check_signature(const byte[], u32bit);
+ bool check_signature(const MemoryRegion<byte>&);
+
+ void set_input_format(Signature_Format);
+
+ PK_Verifier(const std::string&);
+ virtual ~PK_Verifier();
+ protected:
+ virtual bool validate_signature(const MemoryRegion<byte>&,
+ const byte[], u32bit) = 0;
+ virtual u32bit key_message_parts() const = 0;
+ virtual u32bit key_message_part_size() const = 0;
+
+ Signature_Format sig_format;
+ EMSA* emsa;
+ private:
+ PK_Verifier(const PK_Verifier&);
+ PK_Verifier& operator=(const PK_Verifier&);
+ };
+
+/*************************************************
+* Key Agreement *
+*************************************************/
+class BOTAN_DLL PK_Key_Agreement
+ {
+ public:
+ SymmetricKey derive_key(u32bit, const byte[], u32bit,
+ const std::string& = "") const;
+ SymmetricKey derive_key(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ PK_Key_Agreement(const PK_Key_Agreement_Key&, const std::string&);
+ private:
+ PK_Key_Agreement(const PK_Key_Agreement_Key&);
+ PK_Key_Agreement& operator=(const PK_Key_Agreement&);
+
+ const PK_Key_Agreement_Key& key;
+ const std::string kdf_name;
+ };
+
+/*************************************************
+* Encryption with an MR algorithm and an EME *
+*************************************************/
+class BOTAN_DLL PK_Encryptor_MR_with_EME : public PK_Encryptor
+ {
+ public:
+ u32bit maximum_input_size() const;
+
+ PK_Encryptor_MR_with_EME(const PK_Encrypting_Key&, const std::string&);
+ ~PK_Encryptor_MR_with_EME() { delete encoder; }
+
+ private:
+ PK_Encryptor_MR_with_EME(const PK_Encryptor_MR_with_EME&);
+ PK_Encryptor_MR_with_EME& operator=(const PK_Encryptor_MR_with_EME&);
+
+ SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ const PK_Encrypting_Key& key;
+ const EME* encoder;
+ };
+
+/*************************************************
+* Decryption with an MR algorithm and an EME *
+*************************************************/
+class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor
+ {
+ public:
+ PK_Decryptor_MR_with_EME(const PK_Decrypting_Key&, const std::string&);
+ ~PK_Decryptor_MR_with_EME() { delete encoder; }
+ private:
+ PK_Decryptor_MR_with_EME(const PK_Decryptor_MR_with_EME&);
+ PK_Decryptor_MR_with_EME& operator=(const PK_Decryptor_MR_with_EME&);
+
+ SecureVector<byte> dec(const byte[], u32bit) const;
+
+ const PK_Decrypting_Key& key;
+ const EME* encoder;
+ };
+
+/*************************************************
+* Public Key Verifier with Message Recovery *
+*************************************************/
+class BOTAN_DLL PK_Verifier_with_MR : public PK_Verifier
+ {
+ public:
+ PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&, const std::string&);
+ private:
+ PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&);
+ PK_Verifier_with_MR& operator=(const PK_Verifier_with_MR&);
+
+ bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit);
+ u32bit key_message_parts() const { return key.message_parts(); }
+ u32bit key_message_part_size() const { return key.message_part_size(); }
+
+ const PK_Verifying_with_MR_Key& key;
+ };
+
+/*************************************************
+* Public Key Verifier without Message Recovery *
+*************************************************/
+class BOTAN_DLL PK_Verifier_wo_MR : public PK_Verifier
+ {
+ public:
+ PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&, const std::string&);
+ private:
+ PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&);
+ PK_Verifier_wo_MR& operator=(const PK_Verifier_wo_MR&);
+
+ bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit);
+ u32bit key_message_parts() const { return key.message_parts(); }
+ u32bit key_message_part_size() const { return key.message_part_size(); }
+
+ const PK_Verifying_wo_MR_Key& key;
+ };
+
+}
+
+#endif
diff --git a/src/pk/pubkey/rsa_op.cpp b/src/pk/pubkey/rsa_op.cpp
new file mode 100644
index 000000000..0b151bf3b
--- /dev/null
+++ b/src/pk/pubkey/rsa_op.cpp
@@ -0,0 +1,83 @@
+/*************************************************
+* IF (RSA/RW) Operation Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default IF Operation *
+*************************************************/
+class Default_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt& i) const
+ { return powermod_e_n(i); }
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new Default_IF_Op(*this); }
+
+ Default_IF_Op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+ private:
+ Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q;
+ Modular_Reducer reducer;
+ BigInt c, q;
+ };
+
+/*************************************************
+* Default_IF_Op Constructor *
+*************************************************/
+Default_IF_Op::Default_IF_Op(const BigInt& e, const BigInt& n, const BigInt&,
+ const BigInt& p, const BigInt& q,
+ const BigInt& d1, const BigInt& d2,
+ const BigInt& c)
+ {
+ powermod_e_n = Fixed_Exponent_Power_Mod(e, n);
+
+ if(d1 != 0 && d2 != 0 && p != 0 && q != 0)
+ {
+ powermod_d1_p = Fixed_Exponent_Power_Mod(d1, p);
+ powermod_d2_q = Fixed_Exponent_Power_Mod(d2, q);
+ reducer = Modular_Reducer(p);
+ this->c = c;
+ this->q = q;
+ }
+ }
+
+/*************************************************
+* Default IF Private Operation *
+*************************************************/
+BigInt Default_IF_Op::private_op(const BigInt& i) const
+ {
+ if(q == 0)
+ throw Internal_Error("Default_IF_Op::private_op: No private key");
+
+ BigInt j1 = powermod_d1_p(i);
+ BigInt j2 = powermod_d2_q(i);
+ j1 = reducer.reduce(sub_mul(j1, j2, c));
+ return mul_add(j1, q, j2);
+ }
+
+}
+
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* Default_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new Default_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+
+}
diff --git a/src/pk/pubkey/x509_key.cpp b/src/pk/pubkey/x509_key.cpp
new file mode 100644
index 000000000..26ce16a72
--- /dev/null
+++ b/src/pk/pubkey/x509_key.cpp
@@ -0,0 +1,174 @@
+/*************************************************
+* X.509 Public Key Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/x509_key.h>
+#include <botan/filters.h>
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pk_algs.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <memory>
+
+namespace Botan {
+
+namespace X509 {
+
+/*************************************************
+* DER or PEM encode a X.509 public key *
+*************************************************/
+void encode(const Public_Key& key, Pipe& pipe, X509_Encoding encoding)
+ {
+ std::auto_ptr<X509_Encoder> encoder(key.x509_encoder());
+ if(!encoder.get())
+ throw Encoding_Error("X509::encode: Key does not support encoding");
+
+ MemoryVector<byte> der =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(encoder->alg_id())
+ .encode(encoder->key_bits(), BIT_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(der, "PUBLIC KEY"));
+ else
+ pipe.write(der);
+ }
+
+/*************************************************
+* PEM encode a X.509 public key *
+*************************************************/
+std::string PEM_encode(const Public_Key& key)
+ {
+ Pipe pem;
+ pem.start_msg();
+ encode(key, pem, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*************************************************
+* Extract a public key and return it *
+*************************************************/
+Public_Key* load_key(DataSource& source)
+ {
+ try {
+ AlgorithmIdentifier alg_id;
+ MemoryVector<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.is_empty())
+ throw Decoding_Error("X.509 public key decoding failed");
+
+ const std::string alg_name = OIDS::lookup(alg_id.oid);
+ if(alg_name == "")
+ throw Decoding_Error("Unknown algorithm OID: " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<Public_Key> key_obj(get_public_key(alg_name));
+ if(!key_obj.get())
+ throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<X509_Decoder> decoder(key_obj->x509_decoder());
+
+ if(!decoder.get())
+ throw Decoding_Error("Key does not support X.509 decoding");
+
+ decoder->alg_id(alg_id);
+ decoder->key_bits(key_bits);
+
+ return key_obj.release();
+ }
+ 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 MemoryRegion<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)
+ {
+ Pipe bits;
+ bits.start_msg();
+ X509::encode(key, bits, RAW_BER);
+ bits.end_msg();
+ DataSource_Memory source(bits.read_all());
+ return X509::load_key(source);
+ }
+
+/*************************************************
+* Find the allowable key constraints *
+*************************************************/
+Key_Constraints find_constraints(const Public_Key& pub_key,
+ Key_Constraints limits)
+ {
+ const Public_Key* key = &pub_key;
+ u32bit constraints = 0;
+
+ if(dynamic_cast<const PK_Encrypting_Key*>(key))
+ constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
+
+ if(dynamic_cast<const PK_Key_Agreement_Key*>(key))
+ constraints |= KEY_AGREEMENT;
+
+ if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) ||
+ dynamic_cast<const PK_Verifying_with_MR_Key*>(key))
+ constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;
+
+ if(limits)
+ constraints &= limits;
+
+ return Key_Constraints(constraints);
+ }
+
+}
+
+}
diff --git a/src/pk/pubkey/x509_key.h b/src/pk/pubkey/x509_key.h
new file mode 100644
index 000000000..abaeaaced
--- /dev/null
+++ b/src/pk/pubkey/x509_key.h
@@ -0,0 +1,58 @@
+/*************************************************
+* X.509 Public Key Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_X509_PUBLIC_KEY_H__
+#define BOTAN_X509_PUBLIC_KEY_H__
+
+#include <botan/pipe.h>
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+#include <botan/enums.h>
+
+namespace Botan {
+
+/*************************************************
+* X.509 Public Key Encoder *
+*************************************************/
+class BOTAN_DLL X509_Encoder
+ {
+ public:
+ virtual AlgorithmIdentifier alg_id() const = 0;
+ virtual MemoryVector<byte> key_bits() const = 0;
+ virtual ~X509_Encoder() {}
+ };
+
+/*************************************************
+* X.509 Public Key Decoder *
+*************************************************/
+class BOTAN_DLL X509_Decoder
+ {
+ public:
+ virtual void alg_id(const AlgorithmIdentifier&) = 0;
+ virtual void key_bits(const MemoryRegion<byte>&) = 0;
+ virtual ~X509_Decoder() {}
+ };
+
+namespace X509 {
+
+/*************************************************
+* X.509 Public Key Encoding/Decoding *
+*************************************************/
+BOTAN_DLL void encode(const Public_Key&, Pipe&, X509_Encoding = PEM);
+BOTAN_DLL std::string PEM_encode(const Public_Key&);
+
+BOTAN_DLL Public_Key* load_key(DataSource&);
+BOTAN_DLL Public_Key* load_key(const std::string&);
+BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>&);
+
+BOTAN_DLL Public_Key* copy_key(const Public_Key&);
+
+BOTAN_DLL Key_Constraints find_constraints(const Public_Key&, Key_Constraints);
+
+}
+
+}
+
+#endif