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