aboutsummaryrefslogtreecommitdiffstats
path: root/src/pubkey
diff options
context:
space:
mode:
Diffstat (limited to 'src/pubkey')
-rw-r--r--src/pubkey/dh/dh.cpp117
-rw-r--r--src/pubkey/dh/dh.h57
-rw-r--r--src/pubkey/dh/dh_core.cpp67
-rw-r--r--src/pubkey/dh/dh_core.h38
-rw-r--r--src/pubkey/dh/info.txt20
-rw-r--r--src/pubkey/dl_algo/dl_algo.cpp165
-rw-r--r--src/pubkey/dl_algo/dl_algo.h61
-rw-r--r--src/pubkey/dl_algo/info.txt16
-rw-r--r--src/pubkey/dl_group/dl_group.cpp327
-rw-r--r--src/pubkey/dl_group/dl_group.h64
-rw-r--r--src/pubkey/dl_group/info.txt15
-rw-r--r--src/pubkey/dlies/dlies.cpp129
-rw-r--r--src/pubkey/dlies/dlies.h53
-rw-r--r--src/pubkey/dlies/info.txt16
-rw-r--r--src/pubkey/dsa/dsa.cpp131
-rw-r--r--src/pubkey/dsa/dsa.h60
-rw-r--r--src/pubkey/dsa/dsa_core.cpp67
-rw-r--r--src/pubkey/dsa/dsa_core.h36
-rw-r--r--src/pubkey/dsa/info.txt21
-rw-r--r--src/pubkey/ec_dompar/ec_dompar.cpp289
-rw-r--r--src/pubkey/ec_dompar/ec_dompar.h115
-rw-r--r--src/pubkey/ec_dompar/info.txt17
-rw-r--r--src/pubkey/ecdsa/ec.cpp554
-rw-r--r--src/pubkey/ecdsa/ec.h380
-rw-r--r--src/pubkey/ecdsa/ecc_core.cpp92
-rw-r--r--src/pubkey/ecdsa/ecc_core.h69
-rw-r--r--src/pubkey/ecdsa/ecdsa.cpp72
-rw-r--r--src/pubkey/ecdsa/ecdsa.h100
-rw-r--r--src/pubkey/ecdsa/info.txt23
-rw-r--r--src/pubkey/elgamal/elg_core.cpp95
-rw-r--r--src/pubkey/elgamal/elg_core.h43
-rw-r--r--src/pubkey/elgamal/elgamal.cpp121
-rw-r--r--src/pubkey/elgamal/elgamal.h57
-rw-r--r--src/pubkey/elgamal/info.txt22
-rw-r--r--src/pubkey/if_algo/if_algo.cpp213
-rw-r--r--src/pubkey/if_algo/if_algo.h58
-rw-r--r--src/pubkey/if_algo/if_core.cpp85
-rw-r--r--src/pubkey/if_algo/if_core.h44
-rw-r--r--src/pubkey/if_algo/info.txt18
-rw-r--r--src/pubkey/keypair/info.txt14
-rw-r--r--src/pubkey/keypair/keypair.cpp71
-rw-r--r--src/pubkey/keypair/keypair.h25
-rw-r--r--src/pubkey/nr/info.txt21
-rw-r--r--src/pubkey/nr/nr.cpp131
-rw-r--r--src/pubkey/nr/nr.h61
-rw-r--r--src/pubkey/nr/nr_core.cpp60
-rw-r--r--src/pubkey/nr/nr_core.h36
-rw-r--r--src/pubkey/pubkey/dh_op.cpp41
-rw-r--r--src/pubkey/pubkey/dsa_op.cpp106
-rw-r--r--src/pubkey/pubkey/elg_op.cpp89
-rw-r--r--src/pubkey/pubkey/info.txt30
-rw-r--r--src/pubkey/pubkey/nr_op.cpp104
-rw-r--r--src/pubkey/pubkey/pk_algs.cpp110
-rw-r--r--src/pubkey/pubkey/pk_algs.h22
-rw-r--r--src/pubkey/pubkey/pk_keys.cpp68
-rw-r--r--src/pubkey/pubkey/pk_keys.h127
-rw-r--r--src/pubkey/pubkey/pk_ops.h113
-rw-r--r--src/pubkey/pubkey/pkcs8.cpp307
-rw-r--r--src/pubkey/pubkey/pkcs8.h85
-rw-r--r--src/pubkey/pubkey/pubkey.cpp415
-rw-r--r--src/pubkey/pubkey/pubkey.h210
-rw-r--r--src/pubkey/pubkey/rsa_op.cpp83
-rw-r--r--src/pubkey/pubkey/x509_key.cpp174
-rw-r--r--src/pubkey/pubkey/x509_key.h58
-rw-r--r--src/pubkey/rsa/info.txt19
-rw-r--r--src/pubkey/rsa/rsa.cpp161
-rw-r--r--src/pubkey/rsa/rsa.h63
-rw-r--r--src/pubkey/rw/info.txt19
-rw-r--r--src/pubkey/rw/rw.cpp145
-rw-r--r--src/pubkey/rw/rw.h54
70 files changed, 6949 insertions, 0 deletions
diff --git a/src/pubkey/dh/dh.cpp b/src/pubkey/dh/dh.cpp
new file mode 100644
index 000000000..8d2059936
--- /dev/null
+++ b/src/pubkey/dh/dh.cpp
@@ -0,0 +1,117 @@
+/*************************************************
+* Diffie-Hellman Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/dh.h>
+#include <botan/numthry.h>
+#include <botan/util.h>
+
+namespace Botan {
+
+/*************************************************
+* DH_PublicKey Constructor *
+*************************************************/
+DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ X509_load_hook();
+ }
+
+/*************************************************
+* Algorithm Specific X.509 Initialization Code *
+*************************************************/
+void DH_PublicKey::X509_load_hook()
+ {
+ }
+
+/*************************************************
+* Return the maximum input size in bits *
+*************************************************/
+u32bit DH_PublicKey::max_input_bits() const
+ {
+ return group_p().bits();
+ }
+
+/*************************************************
+* Return the public value for key agreement *
+*************************************************/
+MemoryVector<byte> DH_PublicKey::public_value() const
+ {
+ return 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()));
+ PKCS8_load_hook(rng, true);
+ }
+ else
+ PKCS8_load_hook(rng, false);
+ }
+
+/*************************************************
+* Algorithm Specific PKCS #8 Initialization Code *
+*************************************************/
+void DH_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ if(y == 0)
+ y = power_mod(group_g(), x, group_p());
+ core = DH_Core(rng, group, x);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*************************************************
+* Return the public value for key agreement *
+*************************************************/
+MemoryVector<byte> DH_PrivateKey::public_value() const
+ {
+ return DH_PublicKey::public_value();
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> DH_PrivateKey::derive_key(const byte w[],
+ u32bit w_len) const
+ {
+ return derive_key(BigInt::decode(w, w_len));
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> DH_PrivateKey::derive_key(const DH_PublicKey& key) const
+ {
+ return derive_key(key.get_y());
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> DH_PrivateKey::derive_key(const BigInt& w) const
+ {
+ const BigInt& p = group_p();
+ if(w <= 1 || w >= p-1)
+ throw Invalid_Argument(algo_name() + "::derive_key: Invalid key input");
+ return BigInt::encode_1363(core.agree(w), p.bytes());
+ }
+
+}
diff --git a/src/pubkey/dh/dh.h b/src/pubkey/dh/dh.h
new file mode 100644
index 000000000..2a567fb70
--- /dev/null
+++ b/src/pubkey/dh/dh.h
@@ -0,0 +1,57 @@
+/*************************************************
+* Diffie-Hellman Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DIFFIE_HELLMAN_H__
+#define BOTAN_DIFFIE_HELLMAN_H__
+
+#include <botan/dl_algo.h>
+#include <botan/dh_core.h>
+
+namespace Botan {
+
+/*************************************************
+* Diffie-Hellman Public Key *
+*************************************************/
+class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "DH"; }
+
+ MemoryVector<byte> public_value() const;
+ u32bit max_input_bits() const;
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
+
+ DH_PublicKey() {}
+ DH_PublicKey(const DL_Group&, const BigInt&);
+ private:
+ void X509_load_hook();
+ };
+
+/*************************************************
+* Diffie-Hellman Private Key *
+*************************************************/
+class BOTAN_DLL DH_PrivateKey : public DH_PublicKey,
+ public PK_Key_Agreement_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> derive_key(const byte[], u32bit) const;
+ SecureVector<byte> derive_key(const DH_PublicKey&) const;
+ SecureVector<byte> derive_key(const BigInt&) const;
+
+ MemoryVector<byte> public_value() const;
+
+ DH_PrivateKey() {}
+ DH_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ DH_Core core;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/dh/dh_core.cpp b/src/pubkey/dh/dh_core.cpp
new file mode 100644
index 000000000..a0586c444
--- /dev/null
+++ b/src/pubkey/dh/dh_core.cpp
@@ -0,0 +1,67 @@
+/*************************************************
+* PK Algorithm Core Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/dh_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;
+
+}
+
+/*************************************************
+* 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/pubkey/dh/dh_core.h b/src/pubkey/dh/dh_core.h
new file mode 100644
index 000000000..3735f31e1
--- /dev/null
+++ b/src/pubkey/dh/dh_core.h
@@ -0,0 +1,38 @@
+/*************************************************
+* DH Core Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DH_CORE_H__
+#define BOTAN_DH_CORE_H__
+
+#include <botan/bigint.h>
+#include <botan/blinding.h>
+#include <botan/pk_ops.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*************************************************
+* 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/pubkey/dh/info.txt b/src/pubkey/dh/info.txt
new file mode 100644
index 000000000..3765644c8
--- /dev/null
+++ b/src/pubkey/dh/info.txt
@@ -0,0 +1,20 @@
+realname "DH"
+
+define DH
+
+load_on auto
+
+<add>
+dh.cpp
+dh.h
+dh_core.cpp
+dh_core.h
+</add>
+
+<requires>
+asn1
+bigint
+dl_algo
+numbertheory
+pubkey
+</requires>
diff --git a/src/pubkey/dl_algo/dl_algo.cpp b/src/pubkey/dl_algo/dl_algo.cpp
new file mode 100644
index 000000000..2b59a334e
--- /dev/null
+++ b/src/pubkey/dl_algo/dl_algo.cpp
@@ -0,0 +1,165 @@
+/*************************************************
+* DL Scheme Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/dl_algo.h>
+#include <botan/numthry.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+/*************************************************
+* Return the X.509 public key encoder *
+*************************************************/
+X509_Encoder* DL_Scheme_PublicKey::x509_encoder() const
+ {
+ class DL_Scheme_Encoder : public X509_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ MemoryVector<byte> group =
+ key->group.DER_encode(key->group_format());
+
+ return AlgorithmIdentifier(key->get_oid(), group);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ return DER_Encoder().encode(key->y).get_contents();
+ }
+
+ DL_Scheme_Encoder(const DL_Scheme_PublicKey* k) : key(k) {}
+ private:
+ const DL_Scheme_PublicKey* key;
+ };
+
+ return new DL_Scheme_Encoder(this);
+ }
+
+/*************************************************
+* Return the X.509 public key decoder *
+*************************************************/
+X509_Decoder* DL_Scheme_PublicKey::x509_decoder()
+ {
+ class DL_Scheme_Decoder : public X509_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier& alg_id)
+ {
+ DataSource_Memory source(alg_id.parameters);
+ key->group.BER_decode(source, key->group_format());
+ }
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits).decode(key->y);
+ key->X509_load_hook();
+ }
+
+ DL_Scheme_Decoder(DL_Scheme_PublicKey* k) : key(k) {}
+ private:
+ DL_Scheme_PublicKey* key;
+ };
+
+ return new DL_Scheme_Decoder(this);
+ }
+
+/*************************************************
+* Return the PKCS #8 private key encoder *
+*************************************************/
+PKCS8_Encoder* DL_Scheme_PrivateKey::pkcs8_encoder() const
+ {
+ class DL_Scheme_Encoder : public PKCS8_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ MemoryVector<byte> group =
+ key->group.DER_encode(key->group_format());
+
+ return AlgorithmIdentifier(key->get_oid(), group);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ return DER_Encoder().encode(key->x).get_contents();
+ }
+
+ DL_Scheme_Encoder(const DL_Scheme_PrivateKey* k) : key(k) {}
+ private:
+ const DL_Scheme_PrivateKey* key;
+ };
+
+ return new DL_Scheme_Encoder(this);
+ }
+
+/*************************************************
+* Return the PKCS #8 private key decoder *
+*************************************************/
+PKCS8_Decoder* DL_Scheme_PrivateKey::pkcs8_decoder(RandomNumberGenerator& rng)
+ {
+ class DL_Scheme_Decoder : public PKCS8_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier& alg_id)
+ {
+ DataSource_Memory source(alg_id.parameters);
+ key->group.BER_decode(source, key->group_format());
+ }
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits).decode(key->x);
+ key->PKCS8_load_hook(rng);
+ }
+
+ DL_Scheme_Decoder(DL_Scheme_PrivateKey* k, RandomNumberGenerator& r) :
+ key(k), rng(r) {}
+ private:
+ DL_Scheme_PrivateKey* key;
+ RandomNumberGenerator& rng;
+ };
+
+ return new DL_Scheme_Decoder(this, rng);
+ }
+
+/*************************************************
+* 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/pubkey/dl_algo/dl_algo.h b/src/pubkey/dl_algo/dl_algo.h
new file mode 100644
index 000000000..a8d8d1d51
--- /dev/null
+++ b/src/pubkey/dl_algo/dl_algo.h
@@ -0,0 +1,61 @@
+/*************************************************
+* DL Scheme Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DL_ALGO_H__
+#define BOTAN_DL_ALGO_H__
+
+#include <botan/dl_group.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*************************************************
+* DL Public Key *
+*************************************************/
+class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ const DL_Group& get_domain() const { return group; }
+ const BigInt& get_y() const { return y; }
+ const BigInt& group_p() const { return group.get_p(); }
+ const BigInt& group_q() const { return group.get_q(); }
+ const BigInt& group_g() const { return group.get_g(); }
+ virtual DL_Group::Format group_format() const = 0;
+
+ X509_Encoder* x509_encoder() const;
+ X509_Decoder* x509_decoder();
+ protected:
+ BigInt y;
+ DL_Group group;
+ private:
+ virtual void X509_load_hook() {}
+ };
+
+/*************************************************
+* DL Private Key *
+*************************************************/
+class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ const BigInt& get_x() const { return x; }
+
+ PKCS8_Encoder* pkcs8_encoder() const;
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&);
+ protected:
+ BigInt x;
+ private:
+ virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false) {}
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/dl_algo/info.txt b/src/pubkey/dl_algo/info.txt
new file mode 100644
index 000000000..d3368765a
--- /dev/null
+++ b/src/pubkey/dl_algo/info.txt
@@ -0,0 +1,16 @@
+realname "Discrete Logarithm PK Algorithms"
+
+define DL_PUBLIC_KEY_FAMILY
+
+load_on auto
+
+<add>
+dl_algo.cpp
+dl_algo.h
+</add>
+
+<requires>
+asn1
+bigint
+dl_group
+</requires>
diff --git a/src/pubkey/dl_group/dl_group.cpp b/src/pubkey/dl_group/dl_group.cpp
new file mode 100644
index 000000000..b37bc238c
--- /dev/null
+++ b/src/pubkey/dl_group/dl_group.cpp
@@ -0,0 +1,327 @@
+/*************************************************
+* Discrete Logarithm Parameters Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#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/util.h>
+#include <botan/pem.h>
+
+namespace Botan {
+
+/*************************************************
+* DL_Group Constructor *
+*************************************************/
+DL_Group::DL_Group()
+ {
+ initialized = false;
+ }
+
+/*************************************************
+* DL_Group Constructor *
+*************************************************/
+DL_Group::DL_Group(const std::string& type)
+ {
+ std::string grp_contents = global_state().get("dl", type);
+
+ if(grp_contents == "")
+ throw Invalid_Argument("DL_Group: Unknown group " + type);
+
+ DataSource_Memory pem(grp_contents);
+ PEM_decode(pem);
+ }
+
+/*************************************************
+* DL_Group Constructor *
+*************************************************/
+DL_Group::DL_Group(RandomNumberGenerator& rng,
+ PrimeType type, u32bit pbits, u32bit qbits)
+ {
+ if(pbits < 512)
+ throw Invalid_Argument("DL_Group: prime size " + 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 || type == DSA_Kosherizer)
+ {
+ if(type == Prime_Subgroup)
+ {
+ if(!qbits)
+ qbits = 2 * dl_work_factor(pbits);
+
+ q = random_prime(rng, qbits);
+ BigInt X;
+ while(p.bits() != pbits || !is_prime(p, rng))
+ {
+ X.randomize(rng, pbits);
+ p = X - (X % (2*q) - 1);
+ }
+ }
+ else
+ {
+ qbits = qbits ? qbits : ((pbits == 1024) ? 160 : 256);
+ generate_dsa_primes(rng, p, q, pbits, qbits);
+ }
+
+ g = make_dsa_generator(p, q);
+ }
+
+ initialized = true;
+ }
+
+/*************************************************
+* DL_Group Constructor *
+*************************************************/
+DL_Group::DL_Group(RandomNumberGenerator& rng,
+ const MemoryRegion<byte>& seed, u32bit pbits, u32bit qbits)
+ {
+ if(!generate_dsa_primes(rng, 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 Format_Error("DLP group has no q prime specified");
+ return q;
+ }
+
+/*************************************************
+* DER encode the parameters *
+*************************************************/
+SecureVector<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();
+ }
+ else if(format == ANSI_X9_42)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(p)
+ .encode(g)
+ .encode(q)
+ .end_cons()
+ .get_contents();
+ }
+ else if(format == PKCS_3)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(p)
+ .encode(g)
+ .end_cons()
+ .get_contents();
+ }
+
+ throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
+ }
+
+/*************************************************
+* PEM encode the parameters *
+*************************************************/
+std::string DL_Group::PEM_encode(Format format) const
+ {
+ SecureVector<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 " + to_string(format));
+ }
+
+/*************************************************
+* Decode BER encoded parameters *
+*************************************************/
+void DL_Group::BER_decode(DataSource& source, Format format)
+ {
+ BigInt new_p, new_q, new_g;
+
+ BER_Decoder decoder(source);
+ 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 " + to_string(format));
+
+ initialize(new_p, new_q, new_g);
+ }
+
+/*************************************************
+* Decode PEM encoded parameters *
+*************************************************/
+void DL_Group::PEM_decode(DataSource& source)
+ {
+ std::string label;
+ DataSource_Memory ber(PEM_Code::decode(source, 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 a random DSA-style generator *
+*************************************************/
+BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q)
+ {
+ BigInt g, e = (p - 1) / q;
+
+ for(u32bit j = 0; j != PRIME_TABLE_SIZE; ++j)
+ {
+ g = power_mod(PRIMES[j], e, p);
+ if(g != 1)
+ break;
+ }
+
+ if(g == 1)
+ throw Exception("DL_Group: Couldn't create a suitable generator");
+
+ return g;
+ }
+
+}
diff --git a/src/pubkey/dl_group/dl_group.h b/src/pubkey/dl_group/dl_group.h
new file mode 100644
index 000000000..7d631433e
--- /dev/null
+++ b/src/pubkey/dl_group/dl_group.h
@@ -0,0 +1,64 @@
+/*************************************************
+* Discrete Logarithm Group Header File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DL_PARAM_H__
+#define BOTAN_DL_PARAM_H__
+
+#include <botan/bigint.h>
+#include <botan/data_src.h>
+
+namespace Botan {
+
+/*************************************************
+* Discrete Logarithm Group *
+*************************************************/
+class BOTAN_DLL DL_Group
+ {
+ public:
+ const BigInt& get_p() const;
+ const BigInt& get_q() const;
+ const BigInt& get_g() const;
+
+ 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
+ };
+
+ enum PrimeType { Strong, Prime_Subgroup, DSA_Kosherizer };
+
+ bool verify_group(RandomNumberGenerator& rng, bool) const;
+
+ std::string PEM_encode(Format) const;
+ SecureVector<byte> DER_encode(Format) const;
+ void BER_decode(DataSource&, Format);
+ void PEM_decode(DataSource&);
+
+ DL_Group();
+ DL_Group(const std::string&);
+
+ DL_Group(RandomNumberGenerator& rng, PrimeType, u32bit, u32bit = 0);
+ DL_Group(RandomNumberGenerator& rng, const MemoryRegion<byte>&,
+ u32bit = 1024, u32bit = 0);
+
+ DL_Group(const BigInt& p, const BigInt& g);
+ DL_Group(const BigInt& p, const BigInt& g, const BigInt& q);
+ 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/pubkey/dl_group/info.txt b/src/pubkey/dl_group/info.txt
new file mode 100644
index 000000000..62446091f
--- /dev/null
+++ b/src/pubkey/dl_group/info.txt
@@ -0,0 +1,15 @@
+realname "DL Group"
+
+load_on auto
+
+define DL_GROUP
+
+<add>
+dl_group.cpp
+dl_group.h
+</add>
+
+<requires>
+asn1
+bigint
+</requires>
diff --git a/src/pubkey/dlies/dlies.cpp b/src/pubkey/dlies/dlies.cpp
new file mode 100644
index 000000000..2a2f33925
--- /dev/null
+++ b/src/pubkey/dlies/dlies.cpp
@@ -0,0 +1,129 @@
+/*************************************************
+* DLIES Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/dlies.h>
+#include <botan/lookup.h>
+#include <botan/look_pk.h>
+#include <botan/xor_buf.h>
+#include <memory>
+
+namespace Botan {
+
+/*************************************************
+* DLIES_Encryptor Constructor *
+*************************************************/
+DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& k,
+ const std::string& kdf,
+ const std::string& mac, u32bit mk_len) :
+ key(k), kdf_algo(kdf), mac_algo(mac), MAC_KEYLEN(mk_len)
+ {
+ }
+
+/*************************************************
+* DLIES Encryption *
+*************************************************/
+SecureVector<byte> DLIES_Encryptor::enc(const byte in[], u32bit length,
+ RandomNumberGenerator&) const
+ {
+ if(length > maximum_input_size())
+ throw Invalid_Argument("DLIES: Plaintext too large");
+ if(other_key.is_empty())
+ throw Invalid_State("DLIES: The other key was never set");
+
+ std::auto_ptr<KDF> kdf(get_kdf(kdf_algo));
+ std::auto_ptr<MessageAuthenticationCode> mac(get_mac(mac_algo));
+
+ MemoryVector<byte> v = key.public_value();
+
+ SecureVector<byte> out(v.size() + length + mac->OUTPUT_LENGTH);
+ out.copy(v, v.size());
+ out.copy(v.size(), in, length);
+
+ SecureVector<byte> vz(v, key.derive_key(other_key, other_key.size()));
+
+ const u32bit K_LENGTH = length + MAC_KEYLEN;
+ OctetString K = kdf->derive_key(K_LENGTH, vz, vz.size());
+ if(K.length() != K_LENGTH)
+ throw Encoding_Error("DLIES: KDF did not provide sufficient output");
+ byte* C = out + v.size();
+
+ xor_buf(C, K.begin() + MAC_KEYLEN, length);
+ mac->set_key(K.begin(), MAC_KEYLEN);
+
+ mac->update(C, length);
+ for(u32bit j = 0; j != 8; ++j)
+ mac->update(0);
+
+ mac->final(C + length);
+
+ return out;
+ }
+
+/*************************************************
+* Set the other parties public key *
+*************************************************/
+void DLIES_Encryptor::set_other_key(const MemoryRegion<byte>& ok)
+ {
+ other_key = ok;
+ }
+
+/*************************************************
+* Return the max size, in bytes, of a message *
+*************************************************/
+u32bit DLIES_Encryptor::maximum_input_size() const
+ {
+ return 32;
+ }
+
+/*************************************************
+* DLIES_Decryptor Constructor *
+*************************************************/
+DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& k,
+ const std::string& kdf,
+ const std::string& mac, u32bit mk_len) :
+ key(k), kdf_algo(kdf), mac_algo(mac),
+ MAC_KEYLEN(mk_len), PUBLIC_LEN(key.public_value().size())
+ {
+ }
+
+/*************************************************
+* DLIES Decryption *
+*************************************************/
+SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], u32bit length) const
+ {
+ std::auto_ptr<MessageAuthenticationCode> mac(get_mac(mac_algo));
+
+ if(length < PUBLIC_LEN + mac->OUTPUT_LENGTH)
+ throw Decoding_Error("DLIES decryption: ciphertext is too short");
+
+ std::auto_ptr<KDF> kdf(get_kdf(kdf_algo));
+
+ const u32bit CIPHER_LEN = length - PUBLIC_LEN - mac->OUTPUT_LENGTH;
+
+ SecureVector<byte> v(msg, PUBLIC_LEN);
+ SecureVector<byte> C(msg + PUBLIC_LEN, CIPHER_LEN);
+ SecureVector<byte> T(msg + PUBLIC_LEN + CIPHER_LEN, mac->OUTPUT_LENGTH);
+
+ SecureVector<byte> vz(v, key.derive_key(v, v.size()));
+
+ const u32bit K_LENGTH = C.size() + MAC_KEYLEN;
+ OctetString K = kdf->derive_key(K_LENGTH, vz, vz.size());
+ 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(u32bit j = 0; j != 8; ++j)
+ mac->update(0);
+ SecureVector<byte> T2 = mac->final();
+ if(T != T2)
+ throw Integrity_Failure("DLIES: message authentication failed");
+
+ xor_buf(C, K.begin() + MAC_KEYLEN, C.size());
+
+ return C;
+ }
+
+}
diff --git a/src/pubkey/dlies/dlies.h b/src/pubkey/dlies/dlies.h
new file mode 100644
index 000000000..ef0f4d493
--- /dev/null
+++ b/src/pubkey/dlies/dlies.h
@@ -0,0 +1,53 @@
+/*************************************************
+* DLIES Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DLIES_H__
+#define BOTAN_DLIES_H__
+
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+/*************************************************
+* DLIES Encryption *
+*************************************************/
+class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor
+ {
+ public:
+ DLIES_Encryptor(const PK_Key_Agreement_Key&,
+ const std::string& = "KDF2(SHA-160)",
+ const std::string& = "HMAC(SHA-160)", u32bit = 20);
+ void set_other_key(const MemoryRegion<byte>&);
+ private:
+ SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator&) const;
+ u32bit maximum_input_size() const;
+ const PK_Key_Agreement_Key& key;
+ SecureVector<byte> other_key;
+ const std::string kdf_algo;
+ const std::string mac_algo;
+ const u32bit MAC_KEYLEN;
+ };
+
+/*************************************************
+* DLIES Decryption *
+*************************************************/
+class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor
+ {
+ public:
+ DLIES_Decryptor(const PK_Key_Agreement_Key&,
+ const std::string& = "KDF2(SHA-160)",
+ const std::string& = "HMAC(SHA-160)", u32bit = 20);
+ private:
+ SecureVector<byte> dec(const byte[], u32bit) const;
+ const PK_Key_Agreement_Key& key;
+ const std::string kdf_algo;
+ const std::string mac_algo;
+ const u32bit MAC_KEYLEN, PUBLIC_LEN;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/dlies/info.txt b/src/pubkey/dlies/info.txt
new file mode 100644
index 000000000..1a09dcbc5
--- /dev/null
+++ b/src/pubkey/dlies/info.txt
@@ -0,0 +1,16 @@
+realname "DLIES"
+
+define DLIES
+
+load_on auto
+
+<add>
+dlies.cpp
+dlies.h
+</add>
+
+<requires>
+dh
+kdf2
+pubkey
+</requires>
diff --git a/src/pubkey/dsa/dsa.cpp b/src/pubkey/dsa/dsa.cpp
new file mode 100644
index 000000000..ef69a1ee5
--- /dev/null
+++ b/src/pubkey/dsa/dsa.cpp
@@ -0,0 +1,131 @@
+/*************************************************
+* DSA Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/dsa.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+
+namespace Botan {
+
+/*************************************************
+* DSA_PublicKey Constructor *
+*************************************************/
+DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ X509_load_hook();
+ }
+
+/*************************************************
+* Algorithm Specific X.509 Initialization Code *
+*************************************************/
+void DSA_PublicKey::X509_load_hook()
+ {
+ core = DSA_Core(group, y);
+ }
+
+/*************************************************
+* DSA Verification Function *
+*************************************************/
+bool DSA_PublicKey::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ return core.verify(msg, msg_len, sig, sig_len);
+ }
+
+/*************************************************
+* Return the maximum input size in bits *
+*************************************************/
+u32bit DSA_PublicKey::max_input_bits() const
+ {
+ return group_q().bits();
+ }
+
+/*************************************************
+* Return the size of each portion of the sig *
+*************************************************/
+u32bit DSA_PublicKey::message_part_size() const
+ {
+ return group_q().bytes();
+ }
+
+/*************************************************
+* 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);
+ PKCS8_load_hook(rng, true);
+ }
+ else
+ PKCS8_load_hook(rng, false);
+ }
+
+/*************************************************
+* Algorithm Specific PKCS #8 Initialization Code *
+*************************************************/
+void DSA_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ y = power_mod(group_g(), x, group_p());
+ core = DSA_Core(group, y, x);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*************************************************
+* DSA Signature Operation *
+*************************************************/
+SecureVector<byte> DSA_PrivateKey::sign(const byte in[], u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ const BigInt& q = group_q();
+
+ BigInt k;
+ do
+ k.randomize(rng, q.bits());
+ while(k >= q);
+
+ return core.sign(in, length, k);
+ }
+
+/*************************************************
+* 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;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_signer(*this, "EMSA1(SHA-1)"),
+ get_pk_verifier(*this, "EMSA1(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/pubkey/dsa/dsa.h b/src/pubkey/dsa/dsa.h
new file mode 100644
index 000000000..4175c19ad
--- /dev/null
+++ b/src/pubkey/dsa/dsa.h
@@ -0,0 +1,60 @@
+/*************************************************
+* DSA Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DSA_H__
+#define BOTAN_DSA_H__
+
+#include <botan/dl_algo.h>
+#include <botan/dsa_core.h>
+
+namespace Botan {
+
+/*************************************************
+* DSA Public Key *
+*************************************************/
+class BOTAN_DLL DSA_PublicKey : public PK_Verifying_wo_MR_Key,
+ 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; }
+ u32bit message_parts() const { return 2; }
+ u32bit message_part_size() const;
+
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ u32bit max_input_bits() const;
+
+ DSA_PublicKey() {}
+ DSA_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ DSA_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*************************************************
+* DSA Private Key *
+*************************************************/
+class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey,
+ public PK_Signing_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ DSA_PrivateKey() {}
+ DSA_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false);
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/dsa/dsa_core.cpp b/src/pubkey/dsa/dsa_core.cpp
new file mode 100644
index 000000000..aba1e61fb
--- /dev/null
+++ b/src/pubkey/dsa/dsa_core.cpp
@@ -0,0 +1,67 @@
+/*************************************************
+* DSA Core Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/dsa_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;
+
+}
+
+/*************************************************
+* 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);
+ }
+
+}
diff --git a/src/pubkey/dsa/dsa_core.h b/src/pubkey/dsa/dsa_core.h
new file mode 100644
index 000000000..467f3c23f
--- /dev/null
+++ b/src/pubkey/dsa/dsa_core.h
@@ -0,0 +1,36 @@
+/*************************************************
+* DSA Core Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DSA_CORE_H__
+#define BOTAN_DSA_CORE_H__
+
+#include <botan/bigint.h>
+#include <botan/pk_ops.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*************************************************
+* 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;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/dsa/info.txt b/src/pubkey/dsa/info.txt
new file mode 100644
index 000000000..e98f33ca9
--- /dev/null
+++ b/src/pubkey/dsa/info.txt
@@ -0,0 +1,21 @@
+realname "DSA"
+
+define DSA
+
+load_on auto
+
+<add>
+dsa.cpp
+dsa.h
+dsa_core.cpp
+dsa_core.h
+</add>
+
+<requires>
+asn1
+bigint
+dl_algo
+keypair
+numbertheory
+pubkey
+</requires>
diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_dompar/ec_dompar.cpp
new file mode 100644
index 000000000..97f71a6b3
--- /dev/null
+++ b/src/pubkey/ec_dompar/ec_dompar.cpp
@@ -0,0 +1,289 @@
+
+#include <botan/ec_dompar.h>
+#include <botan/enums.h>
+#include <botan/parsing.h>
+#include <botan/libstate.h>
+#include <botan/hex.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+namespace {
+
+std::vector<std::string> get_standard_domain_parameter(const std::string& oid)
+ {
+ /*
+ GEC 2: Test Vectors for SEC 1
+ Certicom Research
+ Working Draft
+ September, 1999
+ Version 0.3;
+ section 2.1.2
+ */
+ if(oid == "1.3.132.8") // InSiTo had '08'
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xffffffffffffffffffffffffffffffff7fffffff"); //p
+ dom_par.push_back("0xffffffffffffffffffffffffffffffff7ffffffc"); // a
+ dom_par.push_back("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); // b
+ dom_par.push_back("024a96b5688ef573284664698968c38bb913cbfc82"); // G
+ dom_par.push_back("0x0100000000000000000001f4c8f927aed3ca752257"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ if(oid == "1.2.840.10045.3.1.1") // prime192v1 Flexiprovider
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffeffffffffffffffff"); //p
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffefffffffffffffffc"); // a
+ dom_par.push_back("0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"); // b
+ dom_par.push_back("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"); // G
+ dom_par.push_back("0xffffffffffffffffffffffff99def836146bc9b1b4d22831"); // order
+ dom_par.push_back("1"); // cofactor
+ }
+
+ /* prime192v2; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.2")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffeffffffffffffffff"); //p
+ dom_par.push_back("0xffffffffffffffffffffffffffffffFeffffffffffffffFC"); // a
+ dom_par.push_back("0xcc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953"); // b
+ dom_par.push_back("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a"); // G
+ dom_par.push_back("0xfffffffffffffffffffffffe5fb1a724dc80418648d8dd31"); // order
+ dom_par.push_back("1"); // cofactor
+ }
+
+ /* prime192v3; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.3")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffeffffffffffffffff"); //p
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffefffffffffffffffc"); // a
+ dom_par.push_back("0x22123dc2395a05caa7423daeccc94760a7d462256bd56916"); // b
+ dom_par.push_back("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896"); // G
+ dom_par.push_back("0xffffffffffffffffffffffff7a62d031c83f4294f640ec13"); // order
+ dom_par.push_back("1"); // cofactor
+ }
+
+ /* prime239v1; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.4")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); //p
+ dom_par.push_back("0x7ffFffffffffffffffffffff7fffffffffff8000000000007ffffffffffc"); // a
+ dom_par.push_back("0x6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A"); // b
+ dom_par.push_back("020ffA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF"); // G
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b"); // order
+ dom_par.push_back("1"); // cofactor
+ }
+
+ /* prime239v2; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.5")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); //p
+ dom_par.push_back("0x7ffFffffffffffffffffffff7ffFffffffff8000000000007ffFffffffFC"); // a
+ dom_par.push_back("0x617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C"); // b
+ dom_par.push_back("0238AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7"); // G
+ dom_par.push_back("0x7fffffffffffffffffffffff800000CFA7E8594377D414C03821BC582063"); // order
+ dom_par.push_back("1"); // cofactor
+ }
+
+ /* prime239v3; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.6")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); //p
+ dom_par.push_back("0x7ffFffffffffffffffffffff7ffFffffffff8000000000007ffFffffffFC"); // a
+ dom_par.push_back("0x255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E"); // b
+ dom_par.push_back("036768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A"); // G
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffff975DEB41B3A6057C3C432146526551"); // order
+ dom_par.push_back("1"); // cofactor
+ }
+
+ /* prime256v1; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.7")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"); //p
+ dom_par.push_back("0xffffffff00000001000000000000000000000000ffffffffffffffffffffffFC"); // a
+ dom_par.push_back("0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); // b
+ dom_par.push_back("036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"); // G
+ dom_par.push_back("0xffffffff00000000ffffffffffffffffBCE6FAADA7179E84F3B9CAC2FC632551"); // order
+ dom_par.push_back("1"); // cofactor
+ }
+
+ throw Invalid_Argument("No such ECC curve " + oid);
+
+ // Todo, add SEC2, Brainpool, NIST curves
+ }
+
+EC_Domain_Params get_ec_dompar(const std::string& oid)
+ {
+ std::vector<std::string> dom_par = get_standard_domain_parameter(oid);
+
+ BigInt p(dom_par[0]); // give as 0x...
+ GFpElement a(p, BigInt(dom_par[1]));
+ GFpElement b(p, BigInt(dom_par[2]));
+
+ Pipe pipe(new Hex_Decoder);
+ pipe.process_msg(dom_par[3]);
+ SecureVector<byte> sv_g = pipe.read_all();
+
+ CurveGFp curve(a, b, p);
+ PointGFp G = OS2ECP ( sv_g, curve );
+ G.check_invariants();
+ BigInt order(dom_par[4]);
+ BigInt cofactor(dom_par[5]);
+ EC_Domain_Params result(curve, G, order, cofactor);
+ return result;
+ }
+
+}
+
+EC_Domain_Params get_EC_Dom_Pars_by_oid(std::string oid)
+ {
+ EC_Domain_Params result = get_ec_dompar(oid);
+ result.m_oid = oid;
+ return result;
+ }
+
+EC_Domain_Params::EC_Domain_Params(const CurveGFp& curve, const PointGFp& base_point,
+ const BigInt& order, const BigInt& cofactor)
+ : m_curve(curve),
+ m_base_point(base_point),
+ m_order(order),
+ m_cofactor(cofactor),
+ m_oid("")
+ { }
+
+namespace {
+
+SecureVector<byte> encode_der_ec_dompar_explicit(EC_Domain_Params const& dom_pars)
+ {
+ u32bit ecpVers1 = 1;
+ OID curve_type_oid("1.2.840.10045.1.1");
+
+ DER_Encoder der;
+
+ der.start_cons(SEQUENCE)
+ .encode(ecpVers1)
+ .start_cons(SEQUENCE)
+ .encode(curve_type_oid)
+ .encode(dom_pars.get_curve().get_p())
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .encode(FE2OSP ( dom_pars.get_curve().get_a() ), OCTET_STRING)
+ .encode(FE2OSP ( dom_pars.get_curve().get_b() ), OCTET_STRING)
+ .end_cons()
+ .encode(EC2OSP ( dom_pars.get_base_point(), PointGFp::UNCOMPRESSED), OCTET_STRING)
+ .encode(dom_pars.get_order())
+ .encode(dom_pars.get_cofactor())
+ .end_cons();
+
+ return der.get_contents();
+ }
+
+EC_Domain_Params decode_ber_ec_dompar_explicit(SecureVector<byte> const& encoded)
+ {
+ BigInt ecpVers1(1);
+ OID curve_type_oid;
+ SecureVector<byte> sv_a;
+ SecureVector<byte> sv_b;
+ BigInt p;
+ SecureVector<byte> sv_base_point;
+ BigInt order;
+ BigInt cofactor;
+ BER_Decoder dec(encoded);
+ dec
+ .start_cons(SEQUENCE)
+ .decode(ecpVers1)
+ .start_cons(SEQUENCE)
+ .decode(curve_type_oid)
+ .decode(p)
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .decode(sv_a, OCTET_STRING)
+ .decode(sv_b, OCTET_STRING)
+ .end_cons()
+ .decode(sv_base_point, OCTET_STRING)
+ .decode(order)
+ .decode(cofactor)
+ .verify_end()
+ .end_cons();
+ if(ecpVers1 != 1)
+ {
+ throw Decoding_Error("wrong ecpVers");
+ }
+ // Set the domain parameters
+ if(curve_type_oid.as_string() != "1.2.840.10045.1.1") // NOTE: hardcoded: prime field type
+ {
+ throw Decoding_Error("wrong curve type oid where prime field was expected");
+ }
+ GFpElement a(p,BigInt::decode(sv_a, sv_a.size()));
+ GFpElement b(p,BigInt::decode(sv_b, sv_b.size()));
+ CurveGFp curve(a,b,p);
+ PointGFp G = OS2ECP ( sv_base_point, curve );
+ G.check_invariants();
+ return EC_Domain_Params(curve, G, order, cofactor);
+ }
+
+} // end anonymous namespace
+
+SecureVector<byte> encode_der_ec_dompar(EC_Domain_Params const& dom_pars, EC_dompar_enc enc_type)
+ {
+ SecureVector<byte> result;
+
+ if(enc_type == ENC_EXPLICIT)
+ {
+ result = encode_der_ec_dompar_explicit(dom_pars);
+ }
+ else if(enc_type == ENC_OID)
+ {
+ OID dom_par_oid(dom_pars.get_oid());
+ result = DER_Encoder().encode(dom_par_oid).get_contents();
+ }
+ else if(enc_type == ENC_IMPLICITCA)
+ {
+ result = DER_Encoder().encode_null().get_contents();
+ }
+ else
+ {
+ throw Internal_Error("encountered illegal value for ec parameter encoding type");
+ }
+ return result;
+ }
+
+EC_Domain_Params decode_ber_ec_dompar(SecureVector<byte> const& encoded)
+ {
+ BER_Decoder dec(encoded);
+ BER_Object obj = dec.get_next_object();
+ ASN1_Tag tag = obj.type_tag;
+ std::auto_ptr<EC_Domain_Params> p_result;
+
+ if(tag == OBJECT_ID)
+ {
+ OID dom_par_oid;
+ BER_Decoder(encoded).decode(dom_par_oid);
+ return EC_Domain_Params(get_ec_dompar(dom_par_oid.as_string()));
+ }
+ else if(tag == SEQUENCE)
+ return EC_Domain_Params(decode_ber_ec_dompar_explicit(encoded));
+ else if(tag == NULL_TAG)
+ throw Decoding_Error("cannot decode ECDSA parameters that are ImplicitCA");
+
+ throw Decoding_Error("encountered unexpected when trying to decode domain parameters");
+ }
+
+bool operator==(EC_Domain_Params const& lhs, EC_Domain_Params const& rhs)
+ {
+ return ((lhs.get_curve() == rhs.get_curve()) &&
+ (lhs.get_base_point() == rhs.get_base_point()) &&
+ (lhs.get_order() == rhs.get_order()) &&
+ (lhs.get_cofactor() == rhs.get_cofactor()));
+ }
+
+}
+
diff --git a/src/pubkey/ec_dompar/ec_dompar.h b/src/pubkey/ec_dompar/ec_dompar.h
new file mode 100644
index 000000000..8f9cc77d9
--- /dev/null
+++ b/src/pubkey/ec_dompar/ec_dompar.h
@@ -0,0 +1,115 @@
+/*************************************************
+* ECDSA Domain Parameters Header File *
+* (C) 2007 Falko Strenzke, FlexSecure GmbH *
+*************************************************/
+
+#ifndef EC_DOMPAR_H__
+#define EC_DOMPAR_H__
+
+#include <botan/point_gfp.h>
+#include <botan/gfp_element.h>
+#include <botan/curve_gfp.h>
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/alg_id.h>
+#include <botan/enums.h>
+
+namespace Botan {
+
+/**
+* This class represents elliptic curce domain parameters
+*/
+class EC_Domain_Params
+ {
+ 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_Domain_Params(CurveGFp const& curve, PointGFp const& base_point,
+ const BigInt& order, const BigInt& cofactor);
+
+ /**
+ * Return domain parameter curve
+ * @result domain parameter curve
+ */
+ const CurveGFp& get_curve() const
+ {
+ return m_curve;
+ }
+
+ /**
+ * Return domain parameter curve
+ * @result domain parameter curve
+ */
+ const PointGFp& get_base_point() const
+ {
+ return m_base_point;
+ }
+
+ /**
+ * Return the order of the base point
+ * @result order of the base point
+ */
+ const BigInt& get_order() const
+ {
+ return m_order;
+ }
+
+ /**
+ * Return the cofactor
+ * @result the cofactor
+ */
+ const BigInt& get_cofactor() const
+ {
+ return m_cofactor;
+ }
+
+ /**
+ * Return the OID of these domain parameters
+ * @result the OID
+ */
+ std::string get_oid() const { return m_oid; }
+
+ private:
+ friend EC_Domain_Params get_EC_Dom_Pars_by_oid(std::string oid);
+
+ CurveGFp m_curve;
+ PointGFp m_base_point;
+ BigInt m_order;
+ BigInt m_cofactor;
+ std::string m_oid;
+ };
+
+bool operator==(EC_Domain_Params const& lhs, EC_Domain_Params const& rhs);
+
+inline bool operator!=(const EC_Domain_Params& lhs,
+ const EC_Domain_Params& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+enum EC_dompar_enc { ENC_EXPLICIT = 0, ENC_IMPLICITCA = 1, ENC_OID = 2 };
+
+SecureVector<byte> encode_der_ec_dompar(EC_Domain_Params const& dom_pars,
+ EC_dompar_enc enc_type);
+
+EC_Domain_Params decode_ber_ec_dompar(SecureVector<byte> const& encoded);
+
+/**
+* Factory function, the only way to obtain EC domain parameters with an OID.
+* The demanded OID has to be registered in the InSiTo configuration. Consult the file
+* policy.cpp for the default configuration.
+* @param the oid of the demanded EC domain parameters
+* @result the EC domain parameters associated with the OID
+*/
+EC_Domain_Params get_EC_Dom_Pars_by_oid(std::string oid);
+
+}
+
+#endif
diff --git a/src/pubkey/ec_dompar/info.txt b/src/pubkey/ec_dompar/info.txt
new file mode 100644
index 000000000..59032ce90
--- /dev/null
+++ b/src/pubkey/ec_dompar/info.txt
@@ -0,0 +1,17 @@
+realname "ECC Domain Parameters"
+
+define ECC_DOMAIN_PARAMATERS
+
+load_on auto
+
+<add>
+ec_dompar.cpp
+ec_dompar.h
+</add>
+
+<requires>
+asn1
+bigint
+numbertheory
+gfpmath
+</requires>
diff --git a/src/pubkey/ecdsa/ec.cpp b/src/pubkey/ecdsa/ec.cpp
new file mode 100644
index 000000000..1ab871e25
--- /dev/null
+++ b/src/pubkey/ecdsa/ec.cpp
@@ -0,0 +1,554 @@
+/*************************************************
+* ECC Key implemenation *
+* (C) 2007 Manuel Hartl / FlexSecure GmbH *
+* *
+* Falko Strenzke *
+*************************************************/
+
+#include <botan/ec.h>
+#include <botan/ecdsa.h>
+#include <botan/numthry.h>
+#include <botan/util.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/secmem.h>
+#include <botan/point_gfp.h>
+
+namespace Botan {
+
+/*************************************************
+* EC_PublicKey *
+*************************************************/
+void EC_PublicKey::affirm_init() const // virtual
+ {
+ if ((mp_dom_pars.get() == 0) || (mp_public_point.get() == 0))
+ {
+ throw Invalid_State("cannot use uninitialized EC_Key");
+ }
+ }
+EC_Domain_Params const EC_PublicKey::get_domain_parameters() const
+ {
+ if(!mp_dom_pars.get())
+ {
+ throw Invalid_State("EC_PublicKey::get_domain_parameters(): ec domain parameters are not yet set");
+ }
+ return *mp_dom_pars;
+ }
+bool EC_PublicKey::domain_parameters_set()
+ {
+ if (mp_dom_pars.get())
+ {
+ return true;
+ }
+ return false;
+ }
+void EC_PublicKey::X509_load_hook()
+ {
+ try
+ {
+ // the base point is checked to be on curve already when decoding it
+ affirm_init();
+ mp_public_point->check_invariants();
+ }
+ catch ( Illegal_Point exc )
+ {
+ throw Decoding_Error ( "decoded public point was found not to lie on curve" );
+ }
+ }
+
+
+X509_Encoder* EC_PublicKey::x509_encoder() const
+ {
+ class EC_Key_Encoder : public X509_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ key->affirm_init();
+ SecureVector<byte> params = encode_der_ec_dompar ( * ( key->mp_dom_pars ), key->m_param_enc );
+ return AlgorithmIdentifier ( key->get_oid(),
+ params );
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ key->affirm_init();
+ return EC2OSP ( * ( key->mp_public_point ), PointGFp::COMPRESSED );
+
+ }
+
+ EC_Key_Encoder ( const EC_PublicKey* k ) : key ( k )
+ {}
+ private:
+ const EC_PublicKey* key;
+ };
+
+ return new EC_Key_Encoder(this);
+ }
+
+X509_Decoder* EC_PublicKey::x509_decoder()
+ {
+ class EC_Key_Decoder : public X509_Decoder
+ {
+ public:
+ void alg_id ( const AlgorithmIdentifier& alg_id )
+ {
+ key->mp_dom_pars.reset ( new EC_Domain_Params ( decode_ber_ec_dompar ( alg_id.parameters ) ) );
+ }
+
+ void key_bits ( const MemoryRegion<byte>& bits )
+ {
+ key->mp_public_point.reset ( new PointGFp ( OS2ECP ( bits, key->mp_dom_pars->get_curve() ) ) );
+ key->X509_load_hook();
+ }
+
+ EC_Key_Decoder ( EC_PublicKey* k ) : key ( k )
+ {}
+ private:
+ EC_PublicKey* key;
+ };
+
+ return new EC_Key_Decoder(this);
+ }
+
+void EC_PublicKey::set_parameter_encoding ( EC_dompar_enc type )
+ {
+ if ( ( type != ENC_EXPLICIT ) && ( type != ENC_IMPLICITCA ) && ( type != ENC_OID ) )
+ {
+ throw Invalid_Argument ( "invalid encoding type for EC-key object specified" );
+ }
+ affirm_init();
+ if ( ( mp_dom_pars->get_oid() == "" ) && ( type == ENC_OID ) )
+ {
+ throw Invalid_Argument ( "invalid encoding type ENC_OID specified for EC-key object whose corresponding domain parameters are without oid" );
+ }
+ m_param_enc = type;
+ }
+
+/********************************
+* EC_PrivateKey *
+********************************/
+void EC_PrivateKey::affirm_init() const // virtual
+ {
+ EC_PublicKey::affirm_init();
+ if (m_private_value == 0)
+ {
+ throw Invalid_State("cannot use EC_PrivateKey when private key is uninitialized");
+ }
+ }
+
+ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Domain_Params& dom_pars)
+ {
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params>(new EC_Domain_Params(dom_pars));
+ generate_private_key(rng);
+
+ try
+ {
+ mp_public_point->check_invariants();
+ }
+ catch(Illegal_Point& e)
+ {
+ throw Invalid_State("ECDSA key generation failed");
+ }
+
+ m_ecdsa_core = ECDSA_Core(*mp_dom_pars, m_private_value, *mp_public_point);
+ }
+
+/**
+* EC_PrivateKey generator
+**/
+void EC_PrivateKey::generate_private_key(RandomNumberGenerator& rng)
+ {
+ if (mp_dom_pars.get() == 0)
+ {
+ throw Invalid_State("cannot generate private key when domain parameters are not set");
+ }
+ BigInt tmp_private_value(0);
+ tmp_private_value = BigInt::random_integer(rng, 1, mp_dom_pars->get_order() );
+ mp_public_point = std::auto_ptr<PointGFp>( new PointGFp (mp_dom_pars->get_base_point()));
+ mp_public_point->mult_this_secure(tmp_private_value, mp_dom_pars->get_order(), mp_dom_pars->get_order()-1);
+
+ //assert(mp_public_point.get() != 0);
+ tmp_private_value.swap(m_private_value);
+ }
+
+/**
+* Return the PKCS #8 public key encoder
+**/
+PKCS8_Encoder* EC_PrivateKey::pkcs8_encoder() const
+ {
+ class EC_Key_Encoder : public PKCS8_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ key->affirm_init();
+ SecureVector<byte> params = encode_der_ec_dompar ( * ( key->mp_dom_pars ), ENC_EXPLICIT );
+ return AlgorithmIdentifier ( key->get_oid(),
+ params );
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ key->affirm_init();
+ SecureVector<byte> octstr_secret = BigInt::encode_1363 ( key->m_private_value, key->m_private_value.bytes() );
+
+ return DER_Encoder()
+ .start_cons ( SEQUENCE )
+ .encode ( BigInt ( 1 ) )
+ .encode ( octstr_secret, OCTET_STRING )
+ .end_cons()
+ .get_contents();
+ }
+
+ EC_Key_Encoder ( const EC_PrivateKey* k ) : key ( k )
+ {}
+ private:
+ const EC_PrivateKey* key;
+ };
+
+ return new EC_Key_Encoder(this);
+ }
+
+/**
+* Return the PKCS #8 public key decoder
+*/
+PKCS8_Decoder* EC_PrivateKey::pkcs8_decoder(RandomNumberGenerator&)
+ {
+ class EC_Key_Decoder : public PKCS8_Decoder
+ {
+ public:
+ void alg_id ( const AlgorithmIdentifier& alg_id )
+ {
+ key->mp_dom_pars.reset ( new EC_Domain_Params ( decode_ber_ec_dompar ( alg_id.parameters ) ) );
+ }
+
+ void key_bits ( const MemoryRegion<byte>& bits )
+ {
+ u32bit version;
+ SecureVector<byte> octstr_secret;
+ BER_Decoder ( bits )
+ .start_cons ( SEQUENCE )
+ .decode ( version )
+ .decode ( octstr_secret, OCTET_STRING )
+ .verify_end()
+ .end_cons();
+ key->m_private_value = BigInt::decode ( octstr_secret, octstr_secret.size() );
+ if ( version != 1 )
+ throw Decoding_Error ( "Wrong PKCS #1 key format version for EC key" );
+ key->PKCS8_load_hook();
+ }
+
+ EC_Key_Decoder ( EC_PrivateKey* k ) : key ( k )
+ {}
+ private:
+ EC_PrivateKey* key;
+ };
+
+ return new EC_Key_Decoder(this);
+ }
+
+
+void EC_PrivateKey::PKCS8_load_hook ( bool )
+ {
+ // we cannot use affirm_init() here because mp_public_point might still be null
+ if (mp_dom_pars.get() == 0 )
+ {
+ throw Invalid_State("attempt to set public point for an uninitialized key");
+ }
+ mp_public_point.reset ( new PointGFp ( m_private_value * mp_dom_pars->get_base_point() ) );
+ mp_public_point->check_invariants();
+
+ }
+
+
+
+
+/*************************************************
+* ECDSA_PublicKey *
+*************************************************/
+void ECDSA_PublicKey::affirm_init() const // virtual
+ {
+ EC_PublicKey::affirm_init();
+ }
+
+void ECDSA_PublicKey::set_domain_parameters(EC_Domain_Params const& dom_pars)
+ {
+ if (mp_dom_pars.get())
+ {
+ // they are already set, we must ensure that they are equal to the arg
+ if (dom_pars != *mp_dom_pars.get())
+ {
+ throw Invalid_Argument("EC_PublicKey::set_domain_parameters(): domain parameters are already set, and they are different from the argument");
+ }
+ else
+ {
+ // they are equal, so nothing to do
+ return;
+ }
+ }
+ // set them ...
+ if (m_enc_public_point.size() == 0)
+ {
+ throw Invalid_State("EC_PublicKey::set_domain_parameters(): encoded public point isn´t set");
+ }
+
+ // now try to decode the public key ...
+ PointGFp tmp_pp(OS2ECP(m_enc_public_point, dom_pars.get_curve()));
+ try
+ {
+ tmp_pp.check_invariants();
+ }
+ catch(Illegal_Point e)
+ {
+ throw Invalid_State("EC_PublicKey::set_domain_parameters(): point does not lie on provided curve");
+ }
+ std::auto_ptr<EC_Domain_Params> p_tmp_pars(new EC_Domain_Params(dom_pars));
+ ECDSA_Core tmp_ecdsa_core( *p_tmp_pars, BigInt ( 0 ), tmp_pp );
+ mp_public_point.reset(new PointGFp(tmp_pp));
+ m_ecdsa_core = tmp_ecdsa_core;
+ mp_dom_pars = p_tmp_pars;
+ }
+
+void ECDSA_PublicKey::set_all_values ( ECDSA_PublicKey const& other )
+ {
+ m_param_enc = other.m_param_enc;
+ m_ecdsa_core = other.m_ecdsa_core;
+ m_enc_public_point = other.m_enc_public_point;
+ if ( other.mp_dom_pars.get() )
+ {
+ mp_dom_pars.reset ( new EC_Domain_Params ( * ( other.mp_dom_pars ) ) );
+ }
+ if ( other.mp_public_point.get() )
+ {
+ mp_public_point.reset ( new PointGFp ( * ( other.mp_public_point ) ) );
+ }
+ }
+ECDSA_PublicKey::ECDSA_PublicKey ( ECDSA_PublicKey const& other )
+ : Public_Key(),
+ EC_PublicKey(),
+ PK_Verifying_wo_MR_Key()
+ {
+ set_all_values ( other );
+ }
+ECDSA_PublicKey const& ECDSA_PublicKey::operator= ( ECDSA_PublicKey const& rhs )
+ {
+ set_all_values ( rhs );
+ return *this;
+ }
+bool ECDSA_PublicKey::verify ( const byte message[], u32bit mess_len, const byte signature [], u32bit sig_len ) const
+ {
+ affirm_init();
+ ECDSA_Signature sig;
+ std::auto_ptr<ECDSA_Signature_Decoder> dec(sig.x509_decoder());
+ SecureVector<byte> sv_sig;
+ sv_sig.set ( signature, sig_len );
+ dec->signature_bits ( sv_sig );
+ SecureVector<byte> sv_plain_sig = sig.get_concatenation();
+ return m_ecdsa_core.verify ( sv_plain_sig, sv_plain_sig.size(), message, mess_len );
+ }
+ECDSA_PublicKey::ECDSA_PublicKey ( EC_Domain_Params const& dom_par, PointGFp const& public_point )
+ {
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params> ( new EC_Domain_Params ( dom_par ) );
+ mp_public_point = std::auto_ptr<PointGFp> ( new PointGFp ( public_point ) );
+ m_param_enc = ENC_EXPLICIT;
+ m_ecdsa_core = ECDSA_Core ( *mp_dom_pars, BigInt ( 0 ), *mp_public_point );
+ }
+void ECDSA_PublicKey::X509_load_hook()
+ {
+ EC_PublicKey::X509_load_hook();
+ EC_PublicKey::affirm_init();
+ m_ecdsa_core = ECDSA_Core ( *mp_dom_pars, BigInt ( 0 ), *mp_public_point );
+ }
+u32bit ECDSA_PublicKey::max_input_bits() const
+ {
+ if(!mp_dom_pars.get())
+ {
+ throw Invalid_State("ECDSA_PublicKey::max_input_bits(): domain parameters not set");
+ }
+ return mp_dom_pars->get_order().bits();
+ }
+
+
+/*************************
+* ECDSA_PrivateKey *
+*************************/
+
+void ECDSA_PrivateKey::affirm_init() const // virtual
+ {
+ EC_PrivateKey::affirm_init();
+ }
+
+void ECDSA_PrivateKey::PKCS8_load_hook ( bool generated )
+ {
+ EC_PrivateKey::PKCS8_load_hook ( generated );
+ EC_PrivateKey::affirm_init();
+ m_ecdsa_core = ECDSA_Core ( *mp_dom_pars, m_private_value, *mp_public_point );
+ }
+
+
+void ECDSA_PrivateKey::set_all_values ( ECDSA_PrivateKey const& other )
+ {
+ m_private_value = other.m_private_value;
+ m_param_enc = other.m_param_enc;
+ m_ecdsa_core = other.m_ecdsa_core;
+ m_enc_public_point = other.m_enc_public_point;
+ if ( other.mp_dom_pars.get() )
+ {
+ mp_dom_pars.reset ( new EC_Domain_Params ( * ( other.mp_dom_pars ) ) );
+ }
+ if ( other.mp_public_point.get() )
+ {
+ mp_public_point.reset ( new PointGFp ( * ( other.mp_public_point ) ) );
+ }
+ }
+
+ECDSA_PrivateKey::ECDSA_PrivateKey(ECDSA_PrivateKey const& other)
+ : Public_Key(),
+ EC_PublicKey(),
+ Private_Key(),
+ ECDSA_PublicKey(),
+ EC_PrivateKey(),
+ PK_Signing_Key()
+ {
+ set_all_values(other);
+ }
+ECDSA_PrivateKey const& ECDSA_PrivateKey::operator= (ECDSA_PrivateKey const& rhs)
+ {
+ set_all_values(rhs);
+ return *this;
+ }
+
+SecureVector<byte> ECDSA_PrivateKey::sign ( const byte message [], u32bit mess_len, RandomNumberGenerator&) const
+ {
+ affirm_init();
+ SecureVector<byte> sv_sig = m_ecdsa_core.sign ( message, mess_len );
+ //code which der encodes the signature returned
+ ECDSA_Signature sig = decode_concatenation( sv_sig );
+ std::auto_ptr<ECDSA_Signature_Encoder> enc(sig.x509_encoder());
+ return enc->signature_bits();
+
+ }
+
+
+
+/*********************************
+* ECKAEG_PublicKey *
+*********************************/
+
+void ECKAEG_PublicKey::affirm_init() const // virtual
+ {
+ EC_PublicKey::affirm_init();
+ }
+
+void ECKAEG_PublicKey::set_all_values ( ECKAEG_PublicKey const& other )
+ {
+ m_param_enc = other.m_param_enc;
+ m_eckaeg_core = other.m_eckaeg_core;
+ m_enc_public_point = other.m_enc_public_point;
+ if ( other.mp_dom_pars.get() )
+ {
+ mp_dom_pars.reset ( new EC_Domain_Params ( * ( other.mp_dom_pars ) ) );
+ }
+ if ( other.mp_public_point.get() )
+ {
+ mp_public_point.reset ( new PointGFp ( * ( other.mp_public_point ) ) );
+ }
+ }
+ECKAEG_PublicKey::ECKAEG_PublicKey ( ECKAEG_PublicKey const& other )
+ : Public_Key(),
+ EC_PublicKey()
+ {
+ set_all_values ( other );
+ }
+ECKAEG_PublicKey const& ECKAEG_PublicKey::operator= ( ECKAEG_PublicKey const& rhs )
+ {
+ set_all_values ( rhs );
+ return *this;
+ }
+
+void ECKAEG_PublicKey::X509_load_hook()
+ {
+ EC_PublicKey::X509_load_hook();
+ EC_PublicKey::affirm_init();
+ m_eckaeg_core = ECKAEG_Core ( *mp_dom_pars, BigInt ( 0 ), *mp_public_point );
+ }
+ECKAEG_PublicKey::ECKAEG_PublicKey ( EC_Domain_Params const& dom_par, PointGFp const& public_point )
+ {
+
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params> ( new EC_Domain_Params ( dom_par ) );
+ mp_public_point = std::auto_ptr<PointGFp> ( new PointGFp ( public_point ) );
+ if(mp_public_point->get_curve() != mp_dom_pars->get_curve())
+ {
+ throw Invalid_Argument("ECKAEG_PublicKey(): curve of arg. point and curve of arg. domain parameters are different");
+ }
+ EC_PublicKey::affirm_init();
+ m_eckaeg_core = ECKAEG_Core ( *mp_dom_pars, BigInt ( 0 ), *mp_public_point );
+ }
+
+
+/*********************************
+* ECKAEG_PrivateKey *
+*********************************/
+void ECKAEG_PrivateKey::affirm_init() const // virtual
+ {
+ EC_PrivateKey::affirm_init();
+ }
+void ECKAEG_PrivateKey::PKCS8_load_hook ( bool generated )
+ {
+ EC_PrivateKey::PKCS8_load_hook ( generated );
+ EC_PrivateKey::affirm_init();
+ m_eckaeg_core = ECKAEG_Core ( *mp_dom_pars, m_private_value, *mp_public_point );
+ }
+void ECKAEG_PrivateKey::set_all_values ( ECKAEG_PrivateKey const& other )
+ {
+ m_private_value = other.m_private_value;
+ m_param_enc = other.m_param_enc;
+ m_eckaeg_core = other.m_eckaeg_core;
+ m_enc_public_point = other.m_enc_public_point;
+ if ( other.mp_dom_pars.get() )
+ {
+ mp_dom_pars.reset ( new EC_Domain_Params ( * ( other.mp_dom_pars ) ) );
+ }
+ if ( other.mp_public_point.get() )
+ {
+ mp_public_point.reset ( new PointGFp ( * ( other.mp_public_point ) ) );
+ }
+ }
+
+ECKAEG_PrivateKey::ECKAEG_PrivateKey(ECKAEG_PrivateKey const& other)
+ : Public_Key(),
+ EC_PublicKey(),
+ Private_Key(),
+ ECKAEG_PublicKey(),
+ EC_PrivateKey(),
+ PK_Key_Agreement_Key()
+
+ {
+ set_all_values(other);
+ }
+ECKAEG_PrivateKey const& ECKAEG_PrivateKey::operator= (ECKAEG_PrivateKey const& rhs)
+ {
+ set_all_values(rhs);
+ return *this;
+ }
+
+/**
+* Derive a key
+*/
+SecureVector<byte> ECKAEG_PrivateKey::derive_key(const Public_Key& key) const
+ {
+ affirm_init();
+
+ const EC_PublicKey * p_ec_pk = dynamic_cast<const EC_PublicKey*>(&key);
+ if(!p_ec_pk)
+ {
+ throw Invalid_Argument("ECKAEG_PrivateKey::derive_key(): argument must be an EC_PublicKey");
+ }
+ p_ec_pk->affirm_init();
+ return m_eckaeg_core.agree ( p_ec_pk->get_public_point() );
+ }
+
+}
diff --git a/src/pubkey/ecdsa/ec.h b/src/pubkey/ecdsa/ec.h
new file mode 100644
index 000000000..7a0b3cbba
--- /dev/null
+++ b/src/pubkey/ecdsa/ec.h
@@ -0,0 +1,380 @@
+/*************************************************
+* ECDSA Header File *
+* (C) 2007 Falko Strenzke, FlexSecure GmbH *
+* Manuel hartl, FlexSecure GmbH *
+*************************************************/
+
+#ifndef BOTAN_EC_H__
+#define BOTAN_EC_H__
+
+#include <botan/if_algo.h>
+#include <botan/bigint.h>
+#include <botan/curve_gfp.h>
+#include <botan/pk_keys.h>
+#include <botan/ec_dompar.h>
+#include <botan/ecc_core.h>
+
+namespace Botan {
+
+/**
+* This class represents abstract EC 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 EC_PublicKey : public virtual Public_Key
+ {
+ public:
+
+ /**
+ * Tells whether this key knows his own domain parameters.
+ * @result true if the domain parameters are set, false otherwise
+ */
+ bool domain_parameters_set();
+
+ /**
+ * 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
+ */
+ inline Botan::PointGFp get_public_point() const
+ {
+ if (!mp_public_point.get())
+ {
+ throw Invalid_State("EC_PublicKey::get_public_point(): public point not set because ec domain parameters are not yet set");
+ }
+ return *mp_public_point;
+ }
+ /**
+ * 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
+ */
+ EC_Domain_Params const get_domain_parameters() const;
+ /**
+ * Set the domain parameter encoding to be used when encoding this key.
+ * @param enc the encoding to use
+ */
+ void set_parameter_encoding(EC_dompar_enc enc);
+
+ /**
+ * Get the domain parameter encoding to be used when encoding this key.
+ * @result the encoding to use
+ */
+ inline int get_parameter_encoding() const
+ {
+ return m_param_enc;
+ }
+ //ctors
+
+ EC_PublicKey()
+ : m_param_enc(ENC_EXPLICIT)
+ {
+ //assert(mp_dom_pars.get() == 0);
+ //assert(mp_public_point.get() == 0);
+ }
+
+ /**
+ * Get an x509_encoder that can be used to encode this key.
+ * @result an x509_encoder for this key
+ */
+ X509_Encoder* x509_encoder() const;
+
+ /**
+ * Get an x509_decoder that can be used to decode a stored key into
+ * this key.
+ * @result an x509_decoder for this key
+ */
+ X509_Decoder* x509_decoder();
+
+ /**
+ * Make sure that the public point and domain parameters of this key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+
+ virtual ~EC_PublicKey() {}
+ protected:
+ virtual void X509_load_hook();
+
+ SecureVector<byte> m_enc_public_point; // stores the public point
+
+ std::auto_ptr<EC_Domain_Params> mp_dom_pars;
+ std::auto_ptr<Botan::PointGFp> mp_public_point;
+ EC_dompar_enc m_param_enc;
+ };
+
+/**
+* This abstract class represents general EC Private Keys
+*/
+class EC_PrivateKey : public virtual EC_PublicKey, public virtual Private_Key
+ {
+ public:
+
+ /**
+ * Get an PKCS#8 encoder that can be used to encoded this key.
+ * @result an PKCS#8 encoder for this key
+ */
+ PKCS8_Encoder* pkcs8_encoder() const;
+ /**
+ * Get an PKCS#8 decoder that can be used to decoded a stored key into
+ * this key.
+ * @result an PKCS#8 decoder for this key
+ */
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&);
+ /**
+ * Get the private key value of this key object.
+ * @result the private key value of this key object
+ */
+ inline BigInt const get_value() const
+ {
+ return m_private_value;
+ }
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+ virtual ~EC_PrivateKey()
+ {}
+ protected:
+ virtual void PKCS8_load_hook(bool = false);
+ void generate_private_key(RandomNumberGenerator&);
+ BigInt m_private_value;
+ };
+
+/**
+* This class represents ECDSA Public Keys.
+*/
+class ECDSA_PublicKey : public virtual EC_PublicKey, public PK_Verifying_wo_MR_Key
+ {
+ public:
+
+ /**
+ * 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
+ */
+ u32bit max_input_bits() const;
+
+ /**
+ * Verify a message with this key.
+ * @param message the byte array containing the message
+ * @param mess_len the number of bytes in the message byte array
+ * @param signature the byte array containing the signature
+ * @param sig_len the number of bytes in the signature byte array
+ */
+ bool verify(const byte message[], u32bit mess_len,
+ const byte signature [], u32bit sig_len) const;
+
+ /**
+ * Default constructor. Use this one if you want to later fill this object with data
+ * from an encoded key.
+ */
+ ECDSA_PublicKey() {}
+
+ /**
+ * 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(EC_Domain_Params const& dom_par, Botan::PointGFp const& public_point); // sets core
+
+
+ ECDSA_PublicKey const& operator= (ECDSA_PublicKey const& rhs);
+
+ ECDSA_PublicKey(ECDSA_PublicKey const& other);
+
+ /**
+ * Set the domain parameters of this key. This function has to be
+ * used when a key encoded without domain parameters was decoded into
+ * this key. Otherwise it will not be able to verify a signature.
+ * @param dom_pars the domain_parameters associated with this key
+ * @throw Invalid_Argument if the point was found not to be satisfying the
+ * curve equation of the provided domain parameters
+ * or if this key already has domain parameters set
+ * and these are differing from those given as the parameter
+ */
+ void set_domain_parameters(EC_Domain_Params const& dom_pars);
+
+ /**
+ * Make sure that the public point and domain parameters of this key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ void X509_load_hook();
+ virtual void set_all_values(ECDSA_PublicKey const& other);
+
+ ECDSA_Core m_ecdsa_core;
+ };
+/**
+* This class represents ECDSA Public Keys.
+*/
+class ECDSA_PrivateKey : public ECDSA_PublicKey, public EC_PrivateKey, public PK_Signing_Key
+ {
+ public:
+ //ctors
+ /**
+ * Default constructor. Use this one if you want to later fill this object with data
+ * from an encoded key.
+ */
+ ECDSA_PrivateKey()
+ {}
+ /**
+ * Generate a new private key
+ * @param the domain parameters to used for this key
+ */
+ ECDSA_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Domain_Params& domain);
+
+ ECDSA_PrivateKey(ECDSA_PrivateKey const& other);
+ ECDSA_PrivateKey const& operator= (ECDSA_PrivateKey const& rhs);
+
+ /**
+ * Sign a message with this key.
+ * @param message the byte array representing the message to be signed
+ * @param mess_len the length of the message byte array
+ * @result the signature
+ */
+ SecureVector<byte> sign(const byte message[], u32bit mess_len, RandomNumberGenerator& rng) const;
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+ protected:
+ virtual void set_all_values ( ECDSA_PrivateKey const& other );
+ private:
+ void PKCS8_load_hook(bool = false);
+ };
+
+/**
+* This class represents ECKAEG Public Keys.
+*/
+class ECKAEG_PublicKey : public virtual EC_PublicKey
+ {
+ public:
+ /**
+ * Default constructor. Use this one if you want to later fill this object with data
+ * from an encoded key.
+ */
+ ECKAEG_PublicKey()
+ {};
+ /**
+ * 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
+ */
+ ECKAEG_PublicKey(EC_Domain_Params const& dom_par, Botan::PointGFp const& public_point);
+
+ /**
+ * Get this keys algorithm name.
+ * @result this keys algorithm name
+ */
+ std::string algo_name() const
+ {
+ return "ECKAEG";
+ }
+ /**
+ * 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
+ */
+ u32bit max_input_bits() const
+ {
+ if (!mp_dom_pars.get())
+ {
+ throw Invalid_State("ECKAEG_PublicKey::max_input_bits(): domain parameters not set");
+ }
+ return mp_dom_pars->get_order().bits();
+ }
+ ECKAEG_PublicKey(ECKAEG_PublicKey const& other);
+ ECKAEG_PublicKey const& operator= (ECKAEG_PublicKey const& rhs);
+
+
+ /**
+ * Make sure that the public point and domain parameters of this key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+ protected:
+ void X509_load_hook();
+ virtual void set_all_values ( ECKAEG_PublicKey const& other );
+
+ ECKAEG_Core m_eckaeg_core;
+ };
+
+/**
+* This class represents ECKAEG Private Keys.
+*/
+class ECKAEG_PrivateKey : public ECKAEG_PublicKey, public EC_PrivateKey, public PK_Key_Agreement_Key
+ {
+ public:
+ /**
+ * Generate a new private key
+ * @param the domain parameters to used for this key
+ */
+ ECKAEG_PrivateKey(RandomNumberGenerator& rng,
+ EC_Domain_Params const& dom_pars)
+ {
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params>(new EC_Domain_Params(dom_pars));
+ generate_private_key(rng);
+ mp_public_point->check_invariants();
+ m_eckaeg_core = ECKAEG_Core(*mp_dom_pars, m_private_value, *mp_public_point);
+ }
+ /**
+ * Default constructor. Use this one if you want to later fill this object with data
+ * from an encoded key.
+ */
+ ECKAEG_PrivateKey()
+ {}
+ ECKAEG_PrivateKey(ECKAEG_PrivateKey const& other);
+ ECKAEG_PrivateKey const& operator= (ECKAEG_PrivateKey const& rhs);
+
+ void PKCS8_load_hook(bool = false);
+
+ /**
+ * Derive a shared key with the other partys public key.
+ * @param pub_key the other partys public key
+ */
+ SecureVector<byte> derive_key(const Public_Key& pub_key) const;
+
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ virtual void set_all_values ( ECKAEG_PrivateKey const& other );
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/ecdsa/ecc_core.cpp b/src/pubkey/ecdsa/ecc_core.cpp
new file mode 100644
index 000000000..f644e231c
--- /dev/null
+++ b/src/pubkey/ecdsa/ecc_core.cpp
@@ -0,0 +1,92 @@
+/*************************************************
+* ECDSA/ECKAEG Core Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/ecc_core.h>
+#include <botan/numthry.h>
+#include <botan/engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*************************************************
+* ECKAEG_Core Constructor *
+*************************************************/
+ECKAEG_Core::ECKAEG_Core(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key)
+ {
+ op = Engine_Core::eckaeg_op(dom_pars, priv_key, pub_key);
+ }
+
+/*************************************************
+* ECKAEG_Core Copy Constructor *
+*************************************************/
+ECKAEG_Core::ECKAEG_Core(const ECKAEG_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ }
+
+/*************************************************
+* ECKAEG_Core Assignment Operator *
+*************************************************/
+ECKAEG_Core& ECKAEG_Core::operator=(const ECKAEG_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ return (*this);
+ }
+
+/*************************************************
+* ECKAEG Operation *
+*************************************************/
+SecureVector<byte> ECKAEG_Core::agree(const PointGFp& otherKey) const
+ {
+ //assert(op.get());
+ return op->agree(otherKey);
+ }
+
+/*************************************************
+* ECDSA Operation *
+*************************************************/
+bool ECDSA_Core::verify(const byte signature[], u32bit sig_len,
+ const byte message[], u32bit mess_len) const
+ {
+ //assert(op.get());
+ return op->verify(signature, sig_len, message, mess_len);
+ }
+
+SecureVector<byte> ECDSA_Core::sign(const byte message[], u32bit mess_len) const
+ {
+ //assert(op.get());
+ return op->sign(message, mess_len);
+ }
+
+ECDSA_Core& ECDSA_Core::operator=(const ECDSA_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ return (*this);
+ }
+
+ECDSA_Core::ECDSA_Core(const ECDSA_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ }
+
+ECDSA_Core::ECDSA_Core(EC_Domain_Params const& dom_pars, const BigInt& priv_key, PointGFp const& pub_key)
+ {
+ op = Engine_Core::ecdsa_op(dom_pars, priv_key, pub_key);
+ }
+
+}
diff --git a/src/pubkey/ecdsa/ecc_core.h b/src/pubkey/ecdsa/ecc_core.h
new file mode 100644
index 000000000..4f840bf06
--- /dev/null
+++ b/src/pubkey/ecdsa/ecc_core.h
@@ -0,0 +1,69 @@
+/*************************************************
+* ECC Core Header File *
+* (C) 1999-2007 Jack Lloyd *
+* (C) 2007 FlexSecure GmbH *
+*************************************************/
+
+#ifndef BOTAN_ECC_CORE_H__
+#define BOTAN_ECC_CORE_H__
+
+#include <botan/bigint.h>
+#include <botan/blinding.h>
+#include <botan/pk_ops.h>
+#include <botan/ec_dompar.h>
+
+namespace Botan {
+
+/*************************************************
+* ECDSA Core *
+*************************************************/
+class ECDSA_Core
+ {
+ public:
+ bool verify(const byte signature[], u32bit sig_len,
+ const byte message[], u32bit mess_len) const;
+
+ SecureVector<byte> sign(const byte message[], u32bit mess_len) const;
+
+ ECDSA_Core& operator=(const ECDSA_Core&);
+
+ ECDSA_Core() { op = 0; }
+
+ ECDSA_Core(const ECDSA_Core&);
+
+ ECDSA_Core(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+
+ ~ECDSA_Core() { delete op; }
+ private:
+ ECDSA_Operation* op;
+ };
+
+/*************************************************
+* ECKAEG Core *
+*************************************************/
+class ECKAEG_Core
+ {
+ public:
+ SecureVector<byte> agree(const PointGFp&) const;
+
+ ECKAEG_Core& operator=(const ECKAEG_Core&);
+
+ ECKAEG_Core() { op = 0; }
+
+ ECKAEG_Core(const ECKAEG_Core&);
+
+ ECKAEG_Core(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ PointGFp const& pub_key);
+
+ ~ECKAEG_Core() { delete op; }
+ private:
+ ECKAEG_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp
new file mode 100644
index 000000000..04dc1e529
--- /dev/null
+++ b/src/pubkey/ecdsa/ecdsa.cpp
@@ -0,0 +1,72 @@
+#include <botan/bigint.h>
+#include <botan/ecdsa.h>
+#include <memory>
+
+namespace Botan {
+
+ECDSA_Signature::ECDSA_Signature(const BigInt& r, const BigInt& s)
+ : m_r(r),
+ m_s(s)
+ {}
+
+ECDSA_Signature::ECDSA_Signature(ECDSA_Signature const& other)
+ : m_r(other.m_r),
+ m_s(other.m_s)
+ {}
+
+ECDSA_Signature const& ECDSA_Signature::operator=(ECDSA_Signature const& other)
+ {
+ m_r = other.m_r;
+ m_s = other.m_s;
+ return *this;
+ }
+
+bool operator== ( ECDSA_Signature const& lhs, ECDSA_Signature const& rhs )
+ {
+ return (lhs.get_r() == rhs.get_r() && lhs.get_s() == rhs.get_s());
+ }
+
+ECDSA_Signature_Decoder* ECDSA_Signature::x509_decoder()
+ {
+ return new ECDSA_Signature_Decoder(this);
+ }
+
+ECDSA_Signature_Encoder* ECDSA_Signature::x509_encoder() const
+ {
+ return new ECDSA_Signature_Encoder(this);
+ }
+SecureVector<byte> const ECDSA_Signature::get_concatenation() const
+ {
+ u32bit enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes(); // use the larger
+ SecureVector<byte> sv_r = BigInt::encode_1363 ( m_r, enc_len );
+ SecureVector<byte> sv_s = BigInt::encode_1363 ( m_s, enc_len );
+ SecureVector<byte> result(sv_r);
+ result.append(sv_s);
+ return result;
+ }
+
+ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq)
+ {
+ ECDSA_Signature sig;
+ std::auto_ptr<ECDSA_Signature_Decoder> dec(sig.x509_decoder());
+ dec->signature_bits(seq);
+ return sig;
+ }
+
+ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concatenation)
+ {
+ if(concatenation.size() % 2 != 0)
+ {
+ throw Invalid_Argument("Erroneous length of signature");
+ }
+ u32bit rs_len = concatenation.size()/2;
+ SecureVector<byte> sv_r;
+ SecureVector<byte> sv_s;
+ sv_r.set(concatenation.begin(), rs_len);
+ sv_s.set(&concatenation[rs_len], rs_len);
+ BigInt r = BigInt::decode ( sv_r, sv_r.size());
+ BigInt s = BigInt::decode (sv_s, sv_s.size());
+ return ECDSA_Signature(r, s);
+ }
+
+}
diff --git a/src/pubkey/ecdsa/ecdsa.h b/src/pubkey/ecdsa/ecdsa.h
new file mode 100644
index 000000000..2f8392a3f
--- /dev/null
+++ b/src/pubkey/ecdsa/ecdsa.h
@@ -0,0 +1,100 @@
+/*************************************************
+* ECDSA Header File *
+* (C) 2007 Falko Strenzke, FlexSecure GmbH *
+* Defines classes ECDSA_Signature and *
+* ECDSA_Signature_De/Encoder, *
+*************************************************/
+
+#ifndef BOTAN_ECDSA_H__
+#define BOTAN_ECDSA_H__
+
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+class ECDSA_Signature_Decoder;
+class ECDSA_Signature_Encoder;
+
+class ECDSA_Signature
+ {
+ friend class ECDSA_Signature_Decoder;
+ friend class ECDSA_Signature_Encoder;
+ public:
+ ECDSA_Signature(const BigInt& r, const BigInt& s);
+ ECDSA_Signature()
+ {}
+ ;
+ ECDSA_Signature(ECDSA_Signature const& other);
+ ECDSA_Signature const& operator=(ECDSA_Signature const& other);
+
+ BigInt const get_r() const
+ {
+ return m_r;
+ }
+ BigInt const get_s() const
+ {
+ return m_s;
+ }
+ /**
+ * return the r||s
+ */
+ SecureVector<byte> const get_concatenation() const;
+
+
+ ECDSA_Signature_Encoder* x509_encoder() const;
+ ECDSA_Signature_Decoder* x509_decoder();
+ private:
+ BigInt m_r;
+ BigInt m_s;
+ };
+
+bool operator== ( ECDSA_Signature const& lhs, ECDSA_Signature const& rhs );
+inline bool operator!= ( ECDSA_Signature const& lhs, ECDSA_Signature const& rhs )
+ {
+ return !operator== ( lhs, rhs );
+ }
+
+class ECDSA_Signature_Decoder
+ {
+ public:
+ void signature_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits)
+ .start_cons(SEQUENCE)
+ .decode(m_signature->m_r)
+ .decode(m_signature->m_s)
+ .verify_end()
+ .end_cons();
+ }
+ ECDSA_Signature_Decoder(ECDSA_Signature* signature) : m_signature(signature)
+ {}
+ private:
+ ECDSA_Signature* m_signature;
+ };
+
+class ECDSA_Signature_Encoder
+ {
+ public:
+ MemoryVector<byte> signature_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(m_signature->m_r)
+ .encode(m_signature->m_s)
+ .end_cons()
+ .get_contents();
+ }
+ ECDSA_Signature_Encoder(const ECDSA_Signature* signature) : m_signature(signature)
+ {}
+ private:
+ const ECDSA_Signature* m_signature;
+ };
+
+ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq);
+ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concatenation);
+
+}
+
+#endif
diff --git a/src/pubkey/ecdsa/info.txt b/src/pubkey/ecdsa/info.txt
new file mode 100644
index 000000000..699c62214
--- /dev/null
+++ b/src/pubkey/ecdsa/info.txt
@@ -0,0 +1,23 @@
+realname "ECDSA/ECKAEG"
+
+define ECDSA
+
+load_on auto
+
+<add>
+ec.cpp
+ec.h
+ecc_core.cpp
+ecc_core.h
+ecdsa.cpp
+ecdsa.h
+</add>
+
+<requires>
+asn1
+bigint
+ec_dompar
+numbertheory
+gfpmath
+pubkey
+</requires>
diff --git a/src/pubkey/elgamal/elg_core.cpp b/src/pubkey/elgamal/elg_core.cpp
new file mode 100644
index 000000000..1181e7534
--- /dev/null
+++ b/src/pubkey/elgamal/elg_core.cpp
@@ -0,0 +1,95 @@
+/*************************************************
+* ElGamal Core Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/elg_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;
+
+}
+
+/*************************************************
+* 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)));
+ }
+
+}
diff --git a/src/pubkey/elgamal/elg_core.h b/src/pubkey/elgamal/elg_core.h
new file mode 100644
index 000000000..67966a452
--- /dev/null
+++ b/src/pubkey/elgamal/elg_core.h
@@ -0,0 +1,43 @@
+/*************************************************
+* ElGamal Core Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_ELGAMAL_CORE_H__
+#define BOTAN_ELGAMAL_CORE_H__
+
+#include <botan/pk_ops.h>
+#include <botan/bigint.h>
+#include <botan/blinding.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*************************************************
+* 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;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/elgamal/elgamal.cpp b/src/pubkey/elgamal/elgamal.cpp
new file mode 100644
index 000000000..ea0d581b0
--- /dev/null
+++ b/src/pubkey/elgamal/elgamal.cpp
@@ -0,0 +1,121 @@
+/*************************************************
+* ElGamal Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/elgamal.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/util.h>
+
+namespace Botan {
+
+/*************************************************
+* ElGamal_PublicKey Constructor *
+*************************************************/
+ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ X509_load_hook();
+ }
+
+/*************************************************
+* Algorithm Specific X.509 Initialization Code *
+*************************************************/
+void ElGamal_PublicKey::X509_load_hook()
+ {
+ core = ELG_Core(group, y);
+ }
+
+/*************************************************
+* ElGamal Encryption Function *
+*************************************************/
+SecureVector<byte>
+ElGamal_PublicKey::encrypt(const byte in[], u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ BigInt k(rng, 2 * dl_work_factor(group_p().bits()));
+ return core.encrypt(in, length, k);
+ }
+
+/*************************************************
+* Return the maximum input size in bits *
+*************************************************/
+u32bit ElGamal_PublicKey::max_input_bits() const
+ {
+ return (group_p().bits() - 1);
+ }
+
+/*************************************************
+* 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()));
+ PKCS8_load_hook(rng, true);
+ }
+ else
+ PKCS8_load_hook(rng, false);
+ }
+
+/*************************************************
+* Algorithm Specific PKCS #8 Initialization Code *
+*************************************************/
+void ElGamal_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ if(y == 0)
+ y = power_mod(group_g(), x, group_p());
+ core = ELG_Core(rng, group, y, x);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*************************************************
+* ElGamal Decryption Function *
+*************************************************/
+SecureVector<byte> ElGamal_PrivateKey::decrypt(const byte in[],
+ u32bit length) const
+ {
+ return core.decrypt(in, length);
+ }
+
+/*************************************************
+* 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;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_encryptor(*this, "EME1(SHA-1)"),
+ get_pk_decryptor(*this, "EME1(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/pubkey/elgamal/elgamal.h b/src/pubkey/elgamal/elgamal.h
new file mode 100644
index 000000000..064bdd504
--- /dev/null
+++ b/src/pubkey/elgamal/elgamal.h
@@ -0,0 +1,57 @@
+/*************************************************
+* ElGamal Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_ELGAMAL_H__
+#define BOTAN_ELGAMAL_H__
+
+#include <botan/dl_algo.h>
+#include <botan/elg_core.h>
+
+namespace Botan {
+
+/*************************************************
+* ElGamal Public Key *
+*************************************************/
+class BOTAN_DLL ElGamal_PublicKey : public PK_Encrypting_Key,
+ 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; }
+
+ SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+ u32bit max_input_bits() const;
+
+ ElGamal_PublicKey() {}
+ ElGamal_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ ELG_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*************************************************
+* ElGamal Private Key *
+*************************************************/
+class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey,
+ public PK_Decrypting_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ ElGamal_PrivateKey() {}
+ ElGamal_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/elgamal/info.txt b/src/pubkey/elgamal/info.txt
new file mode 100644
index 000000000..96586480b
--- /dev/null
+++ b/src/pubkey/elgamal/info.txt
@@ -0,0 +1,22 @@
+realname "ElGamal"
+
+define ELGAMAL
+
+load_on auto
+
+<add>
+elgamal.cpp
+elgamal.h
+elg_core.cpp
+elg_core.h
+</add>
+
+<requires>
+asn1
+bigint
+bigint
+dl_algo
+keypair
+numbertheory
+pubkey
+</requires>
diff --git a/src/pubkey/if_algo/if_algo.cpp b/src/pubkey/if_algo/if_algo.cpp
new file mode 100644
index 000000000..929f488fd
--- /dev/null
+++ b/src/pubkey/if_algo/if_algo.cpp
@@ -0,0 +1,213 @@
+/*************************************************
+* IF Scheme Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/if_algo.h>
+#include <botan/numthry.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+/*************************************************
+* Return the X.509 public key encoder *
+*************************************************/
+X509_Encoder* IF_Scheme_PublicKey::x509_encoder() const
+ {
+ class IF_Scheme_Encoder : public X509_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ return AlgorithmIdentifier(key->get_oid(),
+ AlgorithmIdentifier::USE_NULL_PARAM);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(key->n)
+ .encode(key->e)
+ .end_cons()
+ .get_contents();
+ }
+
+ IF_Scheme_Encoder(const IF_Scheme_PublicKey* k) : key(k) {}
+ private:
+ const IF_Scheme_PublicKey* key;
+ };
+
+ return new IF_Scheme_Encoder(this);
+ }
+
+/*************************************************
+* Return the X.509 public key decoder *
+*************************************************/
+X509_Decoder* IF_Scheme_PublicKey::x509_decoder()
+ {
+ class IF_Scheme_Decoder : public X509_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier&) {}
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits)
+ .start_cons(SEQUENCE)
+ .decode(key->n)
+ .decode(key->e)
+ .verify_end()
+ .end_cons();
+
+ key->X509_load_hook();
+ }
+
+ IF_Scheme_Decoder(IF_Scheme_PublicKey* k) : key(k) {}
+ private:
+ IF_Scheme_PublicKey* key;
+ };
+
+ return new IF_Scheme_Decoder(this);
+ }
+
+/*************************************************
+* Return the PKCS #8 public key encoder *
+*************************************************/
+PKCS8_Encoder* IF_Scheme_PrivateKey::pkcs8_encoder() const
+ {
+ class IF_Scheme_Encoder : public PKCS8_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ return AlgorithmIdentifier(key->get_oid(),
+ AlgorithmIdentifier::USE_NULL_PARAM);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(static_cast<u32bit>(0))
+ .encode(key->n)
+ .encode(key->e)
+ .encode(key->d)
+ .encode(key->p)
+ .encode(key->q)
+ .encode(key->d1)
+ .encode(key->d2)
+ .encode(key->c)
+ .end_cons()
+ .get_contents();
+ }
+
+ IF_Scheme_Encoder(const IF_Scheme_PrivateKey* k) : key(k) {}
+ private:
+ const IF_Scheme_PrivateKey* key;
+ };
+
+ return new IF_Scheme_Encoder(this);
+ }
+
+/*************************************************
+* Return the PKCS #8 public key decoder *
+*************************************************/
+PKCS8_Decoder* IF_Scheme_PrivateKey::pkcs8_decoder(RandomNumberGenerator& rng)
+ {
+ class IF_Scheme_Decoder : public PKCS8_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier&) {}
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ u32bit version;
+
+ BER_Decoder(bits)
+ .start_cons(SEQUENCE)
+ .decode(version)
+ .decode(key->n)
+ .decode(key->e)
+ .decode(key->d)
+ .decode(key->p)
+ .decode(key->q)
+ .decode(key->d1)
+ .decode(key->d2)
+ .decode(key->c)
+ .end_cons();
+
+ if(version != 0)
+ throw Decoding_Error("Unknown PKCS #1 key format version");
+
+ key->PKCS8_load_hook(rng);
+ }
+
+ IF_Scheme_Decoder(IF_Scheme_PrivateKey* k, RandomNumberGenerator& r) :
+ key(k), rng(r) {}
+ private:
+ IF_Scheme_PrivateKey* key;
+ RandomNumberGenerator& rng;
+ };
+
+ return new IF_Scheme_Decoder(this, rng);
+ }
+
+/*************************************************
+* Algorithm Specific X.509 Initialization Code *
+*************************************************/
+void IF_Scheme_PublicKey::X509_load_hook()
+ {
+ core = IF_Core(e, n);
+ }
+
+/*************************************************
+* Algorithm Specific PKCS #8 Initialization Code *
+*************************************************/
+void IF_Scheme_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ if(n == 0) n = p * q;
+ if(d1 == 0) d1 = d % (p - 1);
+ if(d2 == 0) d2 = d % (q - 1);
+ if(c == 0) c = inverse_mod(q, p);
+
+ core = IF_Core(rng, e, n, d, p, q, d1, d2, c);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*************************************************
+* 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;
+ }
+
+/*************************************************
+* 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/pubkey/if_algo/if_algo.h b/src/pubkey/if_algo/if_algo.h
new file mode 100644
index 000000000..c58b2cb8f
--- /dev/null
+++ b/src/pubkey/if_algo/if_algo.h
@@ -0,0 +1,58 @@
+/*************************************************
+* IF Scheme Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_IF_ALGO_H__
+#define BOTAN_IF_ALGO_H__
+
+#include <botan/if_core.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/*************************************************
+* IF Public Key *
+*************************************************/
+class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ const BigInt& get_n() const { return n; }
+ const BigInt& get_e() const { return e; }
+
+ u32bit max_input_bits() const { return (n.bits() - 1); }
+
+ X509_Encoder* x509_encoder() const;
+ X509_Decoder* x509_decoder();
+ protected:
+ virtual void X509_load_hook();
+ BigInt n, e;
+ IF_Core core;
+ };
+
+/*************************************************
+* IF Private Key *
+*************************************************/
+class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ const BigInt& get_p() const { return p; }
+ const BigInt& get_q() const { return q; }
+ const BigInt& get_d() const { return d; }
+
+ PKCS8_Encoder* pkcs8_encoder() const;
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&);
+ protected:
+ virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ BigInt d, p, q, d1, d2, c;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/if_algo/if_core.cpp b/src/pubkey/if_algo/if_core.cpp
new file mode 100644
index 000000000..97cacf9d8
--- /dev/null
+++ b/src/pubkey/if_algo/if_core.cpp
@@ -0,0 +1,85 @@
+/*************************************************
+* IF Algorithm Core Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/if_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)));
+ }
+
+}
diff --git a/src/pubkey/if_algo/if_core.h b/src/pubkey/if_algo/if_core.h
new file mode 100644
index 000000000..b6afad950
--- /dev/null
+++ b/src/pubkey/if_algo/if_core.h
@@ -0,0 +1,44 @@
+/*************************************************
+* IF Algorithm Core Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_IF_CORE_H__
+#define BOTAN_IF_CORE_H__
+
+#include <botan/bigint.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;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/if_algo/info.txt b/src/pubkey/if_algo/info.txt
new file mode 100644
index 000000000..af1726414
--- /dev/null
+++ b/src/pubkey/if_algo/info.txt
@@ -0,0 +1,18 @@
+realname "Integer Factorization Algorithms"
+
+define IF_PUBLIC_KEY_FAMILY
+
+load_on required
+
+<add>
+if_algo.cpp
+if_algo.h
+if_core.cpp
+if_core.h
+</add>
+
+<requires>
+asn1
+bigint
+filters
+</requires>
diff --git a/src/pubkey/keypair/info.txt b/src/pubkey/keypair/info.txt
new file mode 100644
index 000000000..c6fa4af5d
--- /dev/null
+++ b/src/pubkey/keypair/info.txt
@@ -0,0 +1,14 @@
+realname "Keypair Testing"
+
+define KEYPAIR_TESTING
+
+load_on auto
+
+<add>
+keypair.cpp
+keypair.h
+</add>
+
+<requires>
+pubkey
+</requires>
diff --git a/src/pubkey/keypair/keypair.cpp b/src/pubkey/keypair/keypair.cpp
new file mode 100644
index 000000000..940f0c028
--- /dev/null
+++ b/src/pubkey/keypair/keypair.cpp
@@ -0,0 +1,71 @@
+/*************************************************
+* Keypair Checks Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/keypair.h>
+#include <botan/look_pk.h>
+#include <memory>
+
+namespace Botan {
+
+namespace KeyPair {
+
+/*************************************************
+* Check an encryption key pair for consistency *
+*************************************************/
+void check_key(RandomNumberGenerator& rng,
+ PK_Encryptor* encryptor, PK_Decryptor* decryptor)
+ {
+ if(encryptor->maximum_input_size() == 0)
+ return;
+
+ std::auto_ptr<PK_Encryptor> enc(encryptor);
+ std::auto_ptr<PK_Decryptor> dec(decryptor);
+
+ SecureVector<byte> message(enc->maximum_input_size() - 1);
+ rng.randomize(message, message.size());
+
+ SecureVector<byte> ciphertext = enc->encrypt(message, rng);
+ if(ciphertext == message)
+ throw Self_Test_Failure("Encryption key pair consistency failure");
+
+ SecureVector<byte> message2 = dec->decrypt(ciphertext);
+ if(message != message2)
+ throw Self_Test_Failure("Encryption key pair consistency failure");
+ }
+
+/*************************************************
+* Check a signature key pair for consistency *
+*************************************************/
+void check_key(RandomNumberGenerator& rng,
+ PK_Signer* signer, PK_Verifier* verifier)
+ {
+ std::auto_ptr<PK_Signer> sig(signer);
+ std::auto_ptr<PK_Verifier> ver(verifier);
+
+ SecureVector<byte> message(16);
+ rng.randomize(message, message.size());
+
+ SecureVector<byte> signature;
+
+ try
+ {
+ signature = sig->sign_message(message, rng);
+ }
+ catch(Encoding_Error)
+ {
+ return;
+ }
+
+ if(!ver->verify_message(message, signature))
+ throw Self_Test_Failure("Signature key pair consistency failure");
+
+ ++message[0];
+ if(ver->verify_message(message, signature))
+ throw Self_Test_Failure("Signature key pair consistency failure");
+ }
+
+}
+
+}
diff --git a/src/pubkey/keypair/keypair.h b/src/pubkey/keypair/keypair.h
new file mode 100644
index 000000000..da322c075
--- /dev/null
+++ b/src/pubkey/keypair/keypair.h
@@ -0,0 +1,25 @@
+/*************************************************
+* Keypair Checks Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_KEYPAIR_H__
+#define BOTAN_KEYPAIR_H__
+
+#include <botan/look_pk.h>
+
+namespace Botan {
+
+namespace KeyPair {
+
+/*************************************************
+* Check key pair consistency *
+*************************************************/
+BOTAN_DLL void check_key(RandomNumberGenerator&, PK_Encryptor*, PK_Decryptor*);
+BOTAN_DLL void check_key(RandomNumberGenerator&, PK_Signer*, PK_Verifier*);
+
+}
+
+}
+
+#endif
diff --git a/src/pubkey/nr/info.txt b/src/pubkey/nr/info.txt
new file mode 100644
index 000000000..f7325d984
--- /dev/null
+++ b/src/pubkey/nr/info.txt
@@ -0,0 +1,21 @@
+realname "Nyberg-Rueppel"
+
+define NR
+
+load_on auto
+
+<add>
+nr.cpp
+nr.h
+nr_core.cpp
+nr_core.h
+</add>
+
+<requires>
+asn1
+bigint
+dl_algo
+keypair
+numbertheory
+pubkey
+</requires>
diff --git a/src/pubkey/nr/nr.cpp b/src/pubkey/nr/nr.cpp
new file mode 100644
index 000000000..99eff9726
--- /dev/null
+++ b/src/pubkey/nr/nr.cpp
@@ -0,0 +1,131 @@
+/*************************************************
+* Nyberg-Rueppel Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/nr.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+
+namespace Botan {
+
+/*************************************************
+* NR_PublicKey Constructor *
+*************************************************/
+NR_PublicKey::NR_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ X509_load_hook();
+ }
+
+/*************************************************
+* Algorithm Specific X.509 Initialization Code *
+*************************************************/
+void NR_PublicKey::X509_load_hook()
+ {
+ core = NR_Core(group, y);
+ }
+
+/*************************************************
+* Nyberg-Rueppel Verification Function *
+*************************************************/
+SecureVector<byte> NR_PublicKey::verify(const byte sig[], u32bit sig_len) const
+ {
+ return core.verify(sig, sig_len);
+ }
+
+/*************************************************
+* Return the maximum input size in bits *
+*************************************************/
+u32bit NR_PublicKey::max_input_bits() const
+ {
+ return (group_q().bits() - 1);
+ }
+
+/*************************************************
+* Return the size of each portion of the sig *
+*************************************************/
+u32bit NR_PublicKey::message_part_size() const
+ {
+ return group_q().bytes();
+ }
+
+/*************************************************
+* 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);
+ PKCS8_load_hook(rng, true);
+ }
+ else
+ PKCS8_load_hook(rng, false);
+ }
+
+/*************************************************
+* Algorithm Specific PKCS #8 Initialization Code *
+*************************************************/
+void NR_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ if(y == 0)
+ y = power_mod(group_g(), x, group_p());
+ core = NR_Core(group, y, x);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*************************************************
+* Nyberg-Rueppel Signature Operation *
+*************************************************/
+SecureVector<byte> NR_PrivateKey::sign(const byte in[], u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ const BigInt& q = group_q();
+
+ BigInt k;
+ do
+ k.randomize(rng, q.bits());
+ while(k >= q);
+
+ return core.sign(in, length, k);
+ }
+
+/*************************************************
+* 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;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_signer(*this, "EMSA1(SHA-1)"),
+ get_pk_verifier(*this, "EMSA1(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/pubkey/nr/nr.h b/src/pubkey/nr/nr.h
new file mode 100644
index 000000000..21415bc25
--- /dev/null
+++ b/src/pubkey/nr/nr.h
@@ -0,0 +1,61 @@
+/*************************************************
+* Nyberg-Rueppel Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_NYBERG_RUEPPEL_H__
+#define BOTAN_NYBERG_RUEPPEL_H__
+
+#include <botan/dl_algo.h>
+#include <botan/nr_core.h>
+
+namespace Botan {
+
+/*************************************************
+* Nyberg-Rueppel Public Key *
+*************************************************/
+class BOTAN_DLL NR_PublicKey : public PK_Verifying_with_MR_Key,
+ public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "NR"; }
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ u32bit max_input_bits() const;
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
+ u32bit message_parts() const { return 2; }
+ u32bit message_part_size() const;
+
+ NR_PublicKey() {}
+ NR_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ NR_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*************************************************
+* Nyberg-Rueppel Private Key *
+*************************************************/
+class BOTAN_DLL NR_PrivateKey : public NR_PublicKey,
+ public PK_Signing_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ NR_PrivateKey() {}
+
+ NR_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/nr/nr_core.cpp b/src/pubkey/nr/nr_core.cpp
new file mode 100644
index 000000000..f9dfa4024
--- /dev/null
+++ b/src/pubkey/nr/nr_core.cpp
@@ -0,0 +1,60 @@
+/*************************************************
+* NR Core Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/nr_core.h>
+#include <botan/numthry.h>
+#include <botan/engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*************************************************
+* 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);
+ }
+
+}
diff --git a/src/pubkey/nr/nr_core.h b/src/pubkey/nr/nr_core.h
new file mode 100644
index 000000000..416e31619
--- /dev/null
+++ b/src/pubkey/nr/nr_core.h
@@ -0,0 +1,36 @@
+/*************************************************
+* NR Core Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_NR_CORE_H__
+#define BOTAN_NR_CORE_H__
+
+#include <botan/bigint.h>
+#include <botan/pk_ops.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*************************************************
+* 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;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/pubkey/dh_op.cpp b/src/pubkey/pubkey/dh_op.cpp
new file mode 100644
index 000000000..0bcfd4ef8
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/dsa_op.cpp b/src/pubkey/pubkey/dsa_op.cpp
new file mode 100644
index 000000000..ee94cb256
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/elg_op.cpp b/src/pubkey/pubkey/elg_op.cpp
new file mode 100644
index 000000000..0d852d145
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/info.txt b/src/pubkey/pubkey/info.txt
new file mode 100644
index 000000000..8c97aa744
--- /dev/null
+++ b/src/pubkey/pubkey/info.txt
@@ -0,0 +1,30 @@
+realname "Public Key Base"
+
+define PUBKEY_BASE
+
+load_on dep
+
+<requires>
+bigint
+numbertheory
+asn1
+</requires>
+
+<add>
+dh_op.cpp
+dsa_op.cpp
+elg_op.cpp
+nr_op.cpp
+pk_algs.cpp
+pk_algs.h
+pk_keys.cpp
+pk_keys.h
+pk_ops.h
+pkcs8.cpp
+pkcs8.h
+pubkey.cpp
+pubkey.h
+rsa_op.cpp
+x509_key.cpp
+x509_key.h
+</add>
diff --git a/src/pubkey/pubkey/nr_op.cpp b/src/pubkey/pubkey/nr_op.cpp
new file mode 100644
index 000000000..01e96a822
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/pk_algs.cpp b/src/pubkey/pubkey/pk_algs.cpp
new file mode 100644
index 000000000..3c1b81ba9
--- /dev/null
+++ b/src/pubkey/pubkey/pk_algs.cpp
@@ -0,0 +1,110 @@
+/*************************************************
+* 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_ECDSA
+ #include <botan/ec.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
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA") return new ECDSA_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
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA") return new ECDSA_PrivateKey;
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/src/pubkey/pubkey/pk_algs.h b/src/pubkey/pubkey/pk_algs.h
new file mode 100644
index 000000000..a8fa5f176
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/pk_keys.cpp b/src/pubkey/pubkey/pk_keys.cpp
new file mode 100644
index 000000000..d991f3788
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/pk_keys.h b/src/pubkey/pubkey/pk_keys.h
new file mode 100644
index 000000000..16109c634
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/pk_ops.h b/src/pubkey/pubkey/pk_ops.h
new file mode 100644
index 000000000..5413fc7cd
--- /dev/null
+++ b/src/pubkey/pubkey/pk_ops.h
@@ -0,0 +1,113 @@
+/*************************************************
+* Public Key Operations Header File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_OPS_H__
+#define BOTAN_PK_OPS_H__
+
+#include <botan/bigint.h>
+#include <botan/dl_group.h>
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/point_gfp.h>
+#endif
+
+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() {}
+ };
+
+#if defined(BOTAN_HAS_ECDSA)
+/*************************************************
+* ECDSA Operation *
+*************************************************/
+class BOTAN_DLL ECDSA_Operation
+ {
+ public:
+ virtual bool verify(const byte sig[], u32bit sig_len,
+ const byte msg[], u32bit msg_len) const = 0;
+
+ virtual SecureVector<byte> sign(const byte message[],
+ u32bit mess_len) const = 0;
+
+ virtual ECDSA_Operation* clone() const = 0;
+
+ virtual ~ECDSA_Operation() {}
+ };
+
+/*************************************************
+* ECKAEG Operation *
+*************************************************/
+class BOTAN_DLL ECKAEG_Operation
+ {
+ public:
+ virtual SecureVector<byte> agree(const PointGFp&) const = 0;
+ virtual ECKAEG_Operation* clone() const = 0;
+ virtual ~ECKAEG_Operation() {}
+ };
+#endif
+
+}
+
+#endif
diff --git a/src/pubkey/pubkey/pkcs8.cpp b/src/pubkey/pubkey/pkcs8.cpp
new file mode 100644
index 000000000..a79a616a2
--- /dev/null
+++ b/src/pubkey/pubkey/pkcs8.cpp
@@ -0,0 +1,307 @@
+/*************************************************
+* PKCS #8 Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/pkcs8.h>
+#include <botan/get_pbe.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 <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/pubkey/pubkey/pkcs8.h b/src/pubkey/pubkey/pkcs8.h
new file mode 100644
index 000000000..383b1604a
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/pubkey.cpp b/src/pubkey/pubkey/pubkey.cpp
new file mode 100644
index 000000000..06bb44bca
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/pubkey.h b/src/pubkey/pubkey/pubkey.h
new file mode 100644
index 000000000..52f14c5b3
--- /dev/null
+++ b/src/pubkey/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_pad.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/pubkey/pubkey/rsa_op.cpp b/src/pubkey/pubkey/rsa_op.cpp
new file mode 100644
index 000000000..0b151bf3b
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/x509_key.cpp b/src/pubkey/pubkey/x509_key.cpp
new file mode 100644
index 000000000..26ce16a72
--- /dev/null
+++ b/src/pubkey/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/pubkey/pubkey/x509_key.h b/src/pubkey/pubkey/x509_key.h
new file mode 100644
index 000000000..abaeaaced
--- /dev/null
+++ b/src/pubkey/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
diff --git a/src/pubkey/rsa/info.txt b/src/pubkey/rsa/info.txt
new file mode 100644
index 000000000..b9f7df3ae
--- /dev/null
+++ b/src/pubkey/rsa/info.txt
@@ -0,0 +1,19 @@
+realname "RSA"
+
+define RSA
+
+load_on auto
+
+<add>
+rsa.cpp
+rsa.h
+</add>
+
+<requires>
+asn1
+bigint
+if_algo
+keypair
+numbertheory
+pubkey
+</requires>
diff --git a/src/pubkey/rsa/rsa.cpp b/src/pubkey/rsa/rsa.cpp
new file mode 100644
index 000000000..8faec9972
--- /dev/null
+++ b/src/pubkey/rsa/rsa.cpp
@@ -0,0 +1,161 @@
+/*************************************************
+* RSA Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/rsa.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*************************************************
+* RSA_PublicKey Constructor *
+*************************************************/
+RSA_PublicKey::RSA_PublicKey(const BigInt& mod, const BigInt& exp)
+ {
+ n = mod;
+ e = exp;
+ X509_load_hook();
+ }
+
+/*************************************************
+* RSA Public Operation *
+*************************************************/
+BigInt RSA_PublicKey::public_op(const BigInt& i) const
+ {
+ if(i >= n)
+ throw Invalid_Argument(algo_name() + "::public_op: input is too large");
+ return core.public_op(i);
+ }
+
+/*************************************************
+* RSA Encryption Function *
+*************************************************/
+SecureVector<byte> RSA_PublicKey::encrypt(const byte in[], u32bit len,
+ RandomNumberGenerator&) const
+ {
+ BigInt i(in, len);
+ return BigInt::encode_1363(public_op(i), n.bytes());
+ }
+
+/*************************************************
+* RSA Verification Function *
+*************************************************/
+SecureVector<byte> RSA_PublicKey::verify(const byte in[], u32bit len) const
+ {
+ BigInt i(in, len);
+ return BigInt::encode(public_op(i));
+ }
+
+/*************************************************
+* Create a RSA private key *
+*************************************************/
+RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng,
+ u32bit bits, u32bit exp)
+ {
+ if(bits < 512)
+ throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
+ to_string(bits) + " bits long");
+ if(exp < 3 || exp % 2 == 0)
+ throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
+
+ e = exp;
+ p = random_prime(rng, (bits + 1) / 2, e);
+ q = random_prime(rng, bits - p.bits(), e);
+ d = inverse_mod(e, lcm(p - 1, q - 1));
+
+ PKCS8_load_hook(rng, true);
+
+ if(n.bits() != bits)
+ throw Self_Test_Failure(algo_name() + " private key generation failed");
+ }
+
+/*************************************************
+* RSA_PrivateKey Constructor *
+*************************************************/
+RSA_PrivateKey::RSA_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;
+
+ if(d == 0)
+ d = inverse_mod(e, lcm(p - 1, q - 1));
+
+ PKCS8_load_hook(rng);
+ }
+
+/*************************************************
+* RSA Private Operation *
+*************************************************/
+BigInt RSA_PrivateKey::private_op(const byte in[], u32bit length) const
+ {
+ BigInt i(in, length);
+ if(i >= n)
+ throw Invalid_Argument(algo_name() + "::private_op: input is too large");
+
+ BigInt r = core.private_op(i);
+ if(i != public_op(r))
+ throw Self_Test_Failure(algo_name() + " private operation check failed");
+ return r;
+ }
+
+/*************************************************
+* RSA Decryption Operation *
+*************************************************/
+SecureVector<byte> RSA_PrivateKey::decrypt(const byte in[], u32bit len) const
+ {
+ return BigInt::encode(private_op(in, len));
+ }
+
+/*************************************************
+* RSA Signature Operation *
+*************************************************/
+SecureVector<byte> RSA_PrivateKey::sign(const byte in[], u32bit len,
+ RandomNumberGenerator&) const
+ {
+ return BigInt::encode_1363(private_op(in, len), n.bytes());
+ }
+
+/*************************************************
+* 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;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_encryptor(*this, "EME1(SHA-1)"),
+ get_pk_decryptor(*this, "EME1(SHA-1)")
+ );
+
+ KeyPair::check_key(rng,
+ get_pk_signer(*this, "EMSA4(SHA-1)"),
+ get_pk_verifier(*this, "EMSA4(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h
new file mode 100644
index 000000000..445902a6f
--- /dev/null
+++ b/src/pubkey/rsa/rsa.h
@@ -0,0 +1,63 @@
+/*************************************************
+* RSA Header File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_RSA_H__
+#define BOTAN_RSA_H__
+
+#include <botan/if_algo.h>
+
+namespace Botan {
+
+/*************************************************
+* RSA Public Key *
+*************************************************/
+class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key,
+ public PK_Verifying_with_MR_Key,
+ public virtual IF_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "RSA"; }
+
+ SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ RSA_PublicKey() {}
+ RSA_PublicKey(const BigInt&, const BigInt&);
+ protected:
+ BigInt public_op(const BigInt&) const;
+ };
+
+/*************************************************
+* RSA Private Key *
+*************************************************/
+class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey,
+ public PK_Decrypting_Key,
+ public PK_Signing_Key,
+ public IF_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator&) const;
+
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ RSA_PrivateKey() {}
+
+ RSA_PrivateKey(RandomNumberGenerator&,
+ const BigInt& p, const BigInt& q, const BigInt& e,
+ const BigInt& d = 0, const BigInt& n = 0);
+
+ RSA_PrivateKey(RandomNumberGenerator&, u32bit bits, u32bit = 65537);
+ private:
+ BigInt private_op(const byte[], u32bit) const;
+ };
+
+}
+
+#endif
diff --git a/src/pubkey/rw/info.txt b/src/pubkey/rw/info.txt
new file mode 100644
index 000000000..ab43ebbf4
--- /dev/null
+++ b/src/pubkey/rw/info.txt
@@ -0,0 +1,19 @@
+realname "Rabin-Williams"
+
+define RW
+
+load_on auto
+
+<add>
+rw.cpp
+rw.h
+</add>
+
+<requires>
+asn1
+bigint
+if_algo
+keypair
+numbertheory
+pubkey
+</requires>
diff --git a/src/pubkey/rw/rw.cpp b/src/pubkey/rw/rw.cpp
new file mode 100644
index 000000000..39cbcdd6e
--- /dev/null
+++ b/src/pubkey/rw/rw.cpp
@@ -0,0 +1,145 @@
+/*************************************************
+* Rabin-Williams Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/rw.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*************************************************
+* RW_PublicKey Constructor *
+*************************************************/
+RW_PublicKey::RW_PublicKey(const BigInt& mod, const BigInt& exp)
+ {
+ n = mod;
+ e = exp;
+ X509_load_hook();
+ }
+
+/*************************************************
+* Rabin-Williams Public Operation *
+*************************************************/
+BigInt RW_PublicKey::public_op(const BigInt& i) const
+ {
+ if((i > (n >> 1)) || i.is_negative())
+ throw Invalid_Argument(algo_name() + "::public_op: i > n / 2 || i < 0");
+
+ BigInt r = core.public_op(i);
+ if(r % 16 == 12) return r;
+ if(r % 8 == 6) return 2*r;
+
+ r = n - r;
+ if(r % 16 == 12) return r;
+ if(r % 8 == 6) return 2*r;
+
+ throw Invalid_Argument(algo_name() + "::public_op: Invalid input");
+ }
+
+/*************************************************
+* Rabin-Williams Verification Function *
+*************************************************/
+SecureVector<byte> RW_PublicKey::verify(const byte in[], u32bit len) const
+ {
+ BigInt i(in, len);
+ return BigInt::encode(public_op(i));
+ }
+
+/*************************************************
+* Create a Rabin-Williams private key *
+*************************************************/
+RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng,
+ u32bit bits, u32bit exp)
+ {
+ if(bits < 512)
+ throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
+ to_string(bits) + " bits long");
+ if(exp < 2 || exp % 2 == 1)
+ throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
+
+ e = exp;
+ 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);
+ d = inverse_mod(e, lcm(p - 1, q - 1) >> 1);
+
+ PKCS8_load_hook(rng, true);
+
+ if(n.bits() != bits)
+ throw Self_Test_Failure(algo_name() + " private key generation failed");
+ }
+
+/*************************************************
+* RW_PrivateKey Constructor *
+*************************************************/
+RW_PrivateKey::RW_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;
+
+ if(d == 0)
+ d = inverse_mod(e, lcm(p - 1, q - 1) >> 1);
+
+ PKCS8_load_hook(rng);
+ }
+
+/*************************************************
+* Rabin-Williams Signature Operation *
+*************************************************/
+SecureVector<byte> RW_PrivateKey::sign(const byte in[], u32bit len,
+ RandomNumberGenerator&) const
+ {
+ BigInt i(in, len);
+ if(i >= n || i % 16 != 12)
+ throw Invalid_Argument(algo_name() + "::sign: Invalid input");
+
+ BigInt r;
+ if(jacobi(i, n) == 1) r = core.private_op(i);
+ else r = core.private_op(i >> 1);
+
+ r = std::min(r, n - r);
+ if(i != public_op(r))
+ throw Self_Test_Failure(algo_name() + " private operation check failed");
+
+ return BigInt::encode_1363(r, n.bytes());
+ }
+
+/*************************************************
+* 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;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_signer(*this, "EMSA2(SHA-1)"),
+ get_pk_verifier(*this, "EMSA2(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/pubkey/rw/rw.h b/src/pubkey/rw/rw.h
new file mode 100644
index 000000000..d9f95eaa9
--- /dev/null
+++ b/src/pubkey/rw/rw.h
@@ -0,0 +1,54 @@
+/*************************************************
+* Rabin-Williams Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_RW_H__
+#define BOTAN_RW_H__
+
+#include <botan/if_algo.h>
+
+namespace Botan {
+
+/*************************************************
+* Rabin-Williams Public Key *
+*************************************************/
+class BOTAN_DLL RW_PublicKey : public PK_Verifying_with_MR_Key,
+ public virtual IF_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "RW"; }
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ RW_PublicKey() {}
+ RW_PublicKey(const BigInt&, const BigInt&);
+ protected:
+ BigInt public_op(const BigInt&) const;
+ };
+
+/*************************************************
+* Rabin-Williams Private Key *
+*************************************************/
+class BOTAN_DLL RW_PrivateKey : public RW_PublicKey,
+ public PK_Signing_Key,
+ public IF_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ RW_PrivateKey() {}
+
+ RW_PrivateKey(RandomNumberGenerator&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt& = 0, const BigInt& = 0);
+
+ RW_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit = 2);
+ };
+
+}
+
+#endif