aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cmd/speed_pk.cpp9
-rw-r--r--src/lib/pubkey/dsa/dsa.cpp16
-rw-r--r--src/lib/pubkey/ecdsa/ecdsa.cpp32
-rw-r--r--src/lib/pubkey/gost_3410/gost_3410.cpp34
-rw-r--r--src/lib/pubkey/info.txt1
-rw-r--r--src/lib/pubkey/nr/nr.cpp34
-rw-r--r--src/lib/pubkey/pk_ops.cpp58
-rw-r--r--src/lib/pubkey/pk_ops.h150
-rw-r--r--src/lib/pubkey/pk_ops_impl.h146
-rw-r--r--src/lib/pubkey/pk_utils.h2
-rw-r--r--src/lib/pubkey/pubkey.cpp210
-rw-r--r--src/lib/pubkey/pubkey.h27
-rw-r--r--src/lib/pubkey/rsa/rsa.cpp20
-rw-r--r--src/lib/pubkey/rw/rw.cpp20
14 files changed, 393 insertions, 366 deletions
diff --git a/src/cmd/speed_pk.cpp b/src/cmd/speed_pk.cpp
index 313892a23..ed3349cd5 100644
--- a/src/cmd/speed_pk.cpp
+++ b/src/cmd/speed_pk.cpp
@@ -80,9 +80,6 @@ using namespace Botan;
#include <memory>
#include <set>
-#define BENCH_FAULT_PROT DISABLE_FAULT_PROTECTION
-//#define BENCH_FAULT_PROT ENABLE_FAULT_PROTECTION
-
namespace {
const char* ec_domains[] = {
@@ -347,7 +344,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng,
ECDSA_PrivateKey key(rng, params);
keygen_timer.stop();
- PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
+ PK_Signer sig(key, padding, IEEE_1363);
PK_Verifier ver(key, padding);
benchmark_sig_ver(ver, sig, verify_timer,
@@ -389,7 +386,7 @@ void benchmark_gost_3410(RandomNumberGenerator& rng,
GOST_3410_PrivateKey key(rng, params);
keygen_timer.stop();
- PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
+ PK_Signer sig(key, padding, IEEE_1363);
PK_Verifier ver(key, padding);
benchmark_sig_ver(ver, sig, verify_timer,
@@ -496,7 +493,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng,
algo_name = key.algo_name();
keygen_timer.stop();
- PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
+ PK_Signer sig(key, padding, IEEE_1363);
PK_Verifier ver(key, padding);
benchmark_sig_ver(ver, sig, verify_timer,
diff --git a/src/lib/pubkey/dsa/dsa.cpp b/src/lib/pubkey/dsa/dsa.cpp
index ca5e93f4e..90cc18fdc 100644
--- a/src/lib/pubkey/dsa/dsa.cpp
+++ b/src/lib/pubkey/dsa/dsa.cpp
@@ -74,11 +74,12 @@ namespace {
/**
* Object that can create a DSA signature
*/
-class DSA_Signature_Operation : public PK_Ops::Signature
+class DSA_Signature_Operation : public PK_Ops::Signature_with_EMSA
{
public:
typedef DSA_PrivateKey Key_Type;
DSA_Signature_Operation(const DSA_PrivateKey& dsa, const std::string& emsa) :
+ PK_Ops::Signature_with_EMSA(emsa),
q(dsa.group_q()),
x(dsa.get_x()),
powermod_g_p(dsa.group_g(), dsa.group_p()),
@@ -91,8 +92,8 @@ class DSA_Signature_Operation : public PK_Ops::Signature
size_t message_part_size() const override { return q.bytes(); }
size_t max_input_bits() const override { return q.bits(); }
- secure_vector<byte> sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng) override;
+ secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
private:
const BigInt& q;
const BigInt& x;
@@ -102,8 +103,8 @@ class DSA_Signature_Operation : public PK_Ops::Signature
};
secure_vector<byte>
-DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator&)
+DSA_Signature_Operation::raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&)
{
BigInt i(msg, msg_len);
@@ -132,12 +133,13 @@ DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
/**
* Object that can verify a DSA signature
*/
-class DSA_Verification_Operation : public PK_Ops::Verification
+class DSA_Verification_Operation : public PK_Ops::Verification_with_EMSA
{
public:
typedef DSA_PublicKey Key_Type;
DSA_Verification_Operation(const DSA_PublicKey& dsa,
- const std::string&) :
+ const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
q(dsa.group_q()), y(dsa.get_y())
{
powermod_g_p = Fixed_Base_Power_Mod(dsa.group_g(), dsa.group_p());
diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp
index d2ad82b94..2518a14fe 100644
--- a/src/lib/pubkey/ecdsa/ecdsa.cpp
+++ b/src/lib/pubkey/ecdsa/ecdsa.cpp
@@ -32,13 +32,14 @@ namespace {
/**
* ECDSA signature operation
*/
-class ECDSA_Signature_Operation : public PK_Ops::Signature
+class ECDSA_Signature_Operation : public PK_Ops::Signature_with_EMSA
{
public:
typedef ECDSA_PrivateKey Key_Type;
ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa,
const std::string& emsa) :
+ PK_Ops::Signature_with_EMSA(emsa),
base_point(ecdsa.domain().get_base_point()),
order(ecdsa.domain().get_order()),
x(ecdsa.private_value()),
@@ -47,12 +48,12 @@ class ECDSA_Signature_Operation : public PK_Ops::Signature
{
}
- secure_vector<byte> sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng);
+ secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
- size_t message_parts() const { return 2; }
- size_t message_part_size() const { return order.bytes(); }
- size_t max_input_bits() const { return order.bits(); }
+ size_t message_parts() const override { return 2; }
+ size_t message_part_size() const override { return order.bytes(); }
+ size_t max_input_bits() const override { return order.bits(); }
private:
const PointGFp& base_point;
@@ -63,8 +64,8 @@ class ECDSA_Signature_Operation : public PK_Ops::Signature
};
secure_vector<byte>
-ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator&)
+ECDSA_Signature_Operation::raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&)
{
const BigInt m(msg, msg_len);
@@ -87,12 +88,13 @@ ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
/**
* ECDSA verification operation
*/
-class ECDSA_Verification_Operation : public PK_Ops::Verification
+class ECDSA_Verification_Operation : public PK_Ops::Verification_with_EMSA
{
public:
typedef ECDSA_PublicKey Key_Type;
ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa,
- const std::string&) :
+ const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
m_base_point(ecdsa.domain().get_base_point()),
m_public_point(ecdsa.public_point()),
m_order(ecdsa.domain().get_order()),
@@ -101,14 +103,14 @@ class ECDSA_Verification_Operation : public PK_Ops::Verification
//m_public_point.precompute_multiples();
}
- size_t message_parts() const { return 2; }
- size_t message_part_size() const { return m_order.bytes(); }
- size_t max_input_bits() const { return m_order.bits(); }
+ size_t message_parts() const override { return 2; }
+ size_t message_part_size() const override { return m_order.bytes(); }
+ size_t max_input_bits() const override { return m_order.bits(); }
- bool with_recovery() const { return false; }
+ bool with_recovery() const override { return false; }
bool verify(const byte msg[], size_t msg_len,
- const byte sig[], size_t sig_len);
+ const byte sig[], size_t sig_len) override;
private:
const PointGFp& m_base_point;
const PointGFp& m_public_point;
diff --git a/src/lib/pubkey/gost_3410/gost_3410.cpp b/src/lib/pubkey/gost_3410/gost_3410.cpp
index 497712fd9..8eb711617 100644
--- a/src/lib/pubkey/gost_3410/gost_3410.cpp
+++ b/src/lib/pubkey/gost_3410/gost_3410.cpp
@@ -94,21 +94,23 @@ BigInt decode_le(const byte msg[], size_t msg_len)
/**
* GOST-34.10 signature operation
*/
-class GOST_3410_Signature_Operation : public PK_Ops::Signature
+class GOST_3410_Signature_Operation : public PK_Ops::Signature_with_EMSA
{
public:
typedef GOST_3410_PrivateKey Key_Type;
- GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410, const std::string&):
+ GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410,
+ const std::string& emsa) :
+ PK_Ops::Signature_with_EMSA(emsa),
base_point(gost_3410.domain().get_base_point()),
order(gost_3410.domain().get_order()),
x(gost_3410.private_value()) {}
- size_t message_parts() const { return 2; }
- size_t message_part_size() const { return order.bytes(); }
- size_t max_input_bits() const { return order.bits(); }
+ size_t message_parts() const override { return 2; }
+ size_t message_part_size() const override { return order.bytes(); }
+ size_t max_input_bits() const override { return order.bits(); }
- secure_vector<byte> sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng);
+ secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
private:
const PointGFp& base_point;
@@ -117,8 +119,8 @@ class GOST_3410_Signature_Operation : public PK_Ops::Signature
};
secure_vector<byte>
-GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng)
+GOST_3410_Signature_Operation::raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
{
BigInt k;
do
@@ -150,21 +152,23 @@ GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len,
/**
* GOST-34.10 verification operation
*/
-class GOST_3410_Verification_Operation : public PK_Ops::Verification
+class GOST_3410_Verification_Operation : public PK_Ops::Verification_with_EMSA
{
public:
typedef GOST_3410_PublicKey Key_Type;
- GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost, const std::string&) :
+ GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost,
+ const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
base_point(gost.domain().get_base_point()),
public_point(gost.public_point()),
order(gost.domain().get_order()) {}
- size_t message_parts() const { return 2; }
- size_t message_part_size() const { return order.bytes(); }
- size_t max_input_bits() const { return order.bits(); }
+ size_t message_parts() const override { return 2; }
+ size_t message_part_size() const override { return order.bytes(); }
+ size_t max_input_bits() const override { return order.bits(); }
- bool with_recovery() const { return false; }
+ bool with_recovery() const override { return false; }
bool verify(const byte msg[], size_t msg_len,
const byte sig[], size_t sig_len);
diff --git a/src/lib/pubkey/info.txt b/src/lib/pubkey/info.txt
index 4bb6288f9..055ebc320 100644
--- a/src/lib/pubkey/info.txt
+++ b/src/lib/pubkey/info.txt
@@ -24,6 +24,7 @@ workfactor.h
<header:internal>
pk_algs.h
pk_utils.h
+pk_ops_impl.h
</header:internal>
<requires>
diff --git a/src/lib/pubkey/nr/nr.cpp b/src/lib/pubkey/nr/nr.cpp
index 6e3a8f0c1..ed90c2345 100644
--- a/src/lib/pubkey/nr/nr.cpp
+++ b/src/lib/pubkey/nr/nr.cpp
@@ -78,11 +78,12 @@ namespace {
/**
* Nyberg-Rueppel signature operation
*/
-class NR_Signature_Operation : public PK_Ops::Signature
+class NR_Signature_Operation : public PK_Ops::Signature_with_EMSA
{
public:
typedef NR_PrivateKey Key_Type;
- NR_Signature_Operation(const NR_PrivateKey& nr, const std::string&) :
+ NR_Signature_Operation(const NR_PrivateKey& nr, const std::string& emsa) :
+ PK_Ops::Signature_with_EMSA(emsa),
q(nr.group_q()),
x(nr.get_x()),
powermod_g_p(nr.group_g(), nr.group_p()),
@@ -90,12 +91,12 @@ class NR_Signature_Operation : public PK_Ops::Signature
{
}
- size_t message_parts() const { return 2; }
- size_t message_part_size() const { return q.bytes(); }
- size_t max_input_bits() const { return (q.bits() - 1); }
+ size_t message_parts() const override { return 2; }
+ size_t message_part_size() const override { return q.bytes(); }
+ size_t max_input_bits() const override { return (q.bits() - 1); }
- secure_vector<byte> sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng);
+ secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
private:
const BigInt& q;
const BigInt& x;
@@ -104,8 +105,8 @@ class NR_Signature_Operation : public PK_Ops::Signature
};
secure_vector<byte>
-NR_Signature_Operation::sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng)
+NR_Signature_Operation::raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
{
rng.add_entropy(msg, msg_len);
@@ -137,11 +138,12 @@ NR_Signature_Operation::sign(const byte msg[], size_t msg_len,
/**
* Nyberg-Rueppel verification operation
*/
-class NR_Verification_Operation : public PK_Ops::Verification
+class NR_Verification_Operation : public PK_Ops::Verification_with_EMSA
{
public:
typedef NR_PublicKey Key_Type;
- NR_Verification_Operation(const NR_PublicKey& nr, const std::string&) :
+ NR_Verification_Operation(const NR_PublicKey& nr, const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
q(nr.group_q()), y(nr.get_y())
{
powermod_g_p = Fixed_Base_Power_Mod(nr.group_g(), nr.group_p());
@@ -150,13 +152,13 @@ class NR_Verification_Operation : public PK_Ops::Verification
mod_q = Modular_Reducer(nr.group_q());
}
- size_t message_parts() const { return 2; }
- size_t message_part_size() const { return q.bytes(); }
- size_t max_input_bits() const { return (q.bits() - 1); }
+ size_t message_parts() const override { return 2; }
+ size_t message_part_size() const override { return q.bytes(); }
+ size_t max_input_bits() const override { return (q.bits() - 1); }
- bool with_recovery() const { return true; }
+ bool with_recovery() const override { return true; }
- secure_vector<byte> verify_mr(const byte msg[], size_t msg_len);
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len) override;
private:
const BigInt& q;
const BigInt& y;
diff --git a/src/lib/pubkey/pk_ops.cpp b/src/lib/pubkey/pk_ops.cpp
index 718cd3998..f78861b9f 100644
--- a/src/lib/pubkey/pk_ops.cpp
+++ b/src/lib/pubkey/pk_ops.cpp
@@ -5,7 +5,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include <botan/pk_ops.h>
+#include <botan/internal/pk_ops_impl.h>
#include <botan/eme.h>
#include <botan/kdf.h>
#include <botan/emsa.h>
@@ -17,7 +17,7 @@ PK_Ops::Encryption_with_EME::Encryption_with_EME(const std::string& eme)
{
m_eme.reset(get_eme(eme));
if(!m_eme.get())
- throw std::runtime_error("EME " + eme + " not found");
+ throw Algorithm_Not_Found(eme);
}
PK_Ops::Encryption_with_EME::~Encryption_with_EME() {}
@@ -44,7 +44,7 @@ PK_Ops::Decryption_with_EME::Decryption_with_EME(const std::string& eme)
{
m_eme.reset(get_eme(eme));
if(!m_eme.get())
- throw std::runtime_error("EME " + eme + " not found");
+ throw Algorithm_Not_Found(eme);
}
PK_Ops::Decryption_with_EME::~Decryption_with_EME() {}
@@ -77,4 +77,56 @@ secure_vector<byte> PK_Ops::Key_Agreement_with_KDF::agree(size_t key_len,
return z;
}
+PK_Ops::Signature_with_EMSA::Signature_with_EMSA(const std::string& emsa)
+ {
+ m_emsa.reset(get_emsa(emsa));
+ if(!m_emsa)
+ throw Algorithm_Not_Found(emsa);
+ }
+
+PK_Ops::Signature_with_EMSA::~Signature_with_EMSA() {}
+
+void PK_Ops::Signature_with_EMSA::update(const byte msg[], size_t msg_len)
+ {
+ m_emsa->update(msg, msg_len);
+ }
+
+secure_vector<byte> PK_Ops::Signature_with_EMSA::sign(RandomNumberGenerator& rng)
+ {
+ const secure_vector<byte> msg = m_emsa->raw_data();
+ const auto padded = m_emsa->encoding_of(msg, this->max_input_bits(), rng);
+ return raw_sign(&padded[0], padded.size(), rng);
+ }
+
+PK_Ops::Verification_with_EMSA::Verification_with_EMSA(const std::string& emsa)
+ {
+ m_emsa.reset(get_emsa(emsa));
+ if(!m_emsa)
+ throw Algorithm_Not_Found(emsa);
+ }
+
+PK_Ops::Verification_with_EMSA::~Verification_with_EMSA() {}
+
+void PK_Ops::Verification_with_EMSA::update(const byte msg[], size_t msg_len)
+ {
+ m_emsa->update(msg, msg_len);
+ }
+
+bool PK_Ops::Verification_with_EMSA::is_valid_signature(const byte sig[], size_t sig_len)
+ {
+ const secure_vector<byte> msg = m_emsa->raw_data();
+
+ if(with_recovery())
+ {
+ secure_vector<byte> output_of_key = verify_mr(sig, sig_len);
+ return m_emsa->verify(output_of_key, msg, max_input_bits());
+ }
+ else
+ {
+ Null_RNG rng;
+ secure_vector<byte> encoded = m_emsa->encoding_of(msg, max_input_bits(), rng);
+ return verify(&encoded[0], encoded.size(), sig, sig_len);
+ }
+ }
+
}
diff --git a/src/lib/pubkey/pk_ops.h b/src/lib/pubkey/pk_ops.h
index 754bcf82d..3a2a8bdb5 100644
--- a/src/lib/pubkey/pk_ops.h
+++ b/src/lib/pubkey/pk_ops.h
@@ -21,7 +21,7 @@ class EMSA;
namespace PK_Ops {
template<typename Key>
-struct PK_Spec
+class PK_Spec
{
public:
PK_Spec(const Key& key, const std::string& pad) :
@@ -38,6 +38,9 @@ struct PK_Spec
const std::string m_pad;
};
+typedef PK_Spec<Public_Key> PK_Spec_Public_Key;
+typedef PK_Spec<Private_Key> PK_Spec_Private_Key;
+
/**
* Public key encryption interface
*/
@@ -48,68 +51,53 @@ class BOTAN_DLL Encryption
virtual secure_vector<byte> encrypt(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) = 0;
- typedef PK_Spec<Public_Key> Spec;
+ typedef PK_Spec_Public_Key Spec;
virtual ~Encryption() {}
};
-class BOTAN_DLL Encryption_with_EME : public Encryption
- {
- public:
- size_t max_input_bits() const override;
-
- secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng) override;
-
- ~Encryption_with_EME();
- protected:
- Encryption_with_EME(const std::string& eme);
- private:
- virtual size_t max_raw_input_bits() const = 0;
-
- virtual secure_vector<byte> raw_encrypt(const byte msg[], size_t len,
- RandomNumberGenerator& rng) = 0;
- std::unique_ptr<EME> m_eme;
- };
-
/**
* Public key decryption interface
*/
class BOTAN_DLL Decryption
{
public:
+ typedef PK_Spec_Private_Key Spec;
+
virtual size_t max_input_bits() const = 0;
virtual secure_vector<byte> decrypt(const byte msg[], size_t msg_len) = 0;
- typedef PK_Spec<Private_Key> Spec;
-
virtual ~Decryption() {}
};
-class BOTAN_DLL Decryption_with_EME : public Decryption
+/**
+* Public key signature verification interface
+*/
+class BOTAN_DLL Verification
{
public:
- size_t max_input_bits() const override;
+ typedef PK_Spec_Public_Key Spec;
- secure_vector<byte> decrypt(const byte msg[], size_t msg_len) override;
+ /*
+ * Add more data to the message currently being signed
+ * @param msg the message
+ * @param msg_len the length of msg in bytes
+ */
+ virtual void update(const byte msg[], size_t msg_len) = 0;
- ~Decryption_with_EME();
- protected:
- Decryption_with_EME(const std::string& eme);
- private:
- virtual size_t max_raw_input_bits() const = 0;
- virtual secure_vector<byte> raw_decrypt(const byte msg[], size_t len) = 0;
- std::unique_ptr<EME> m_eme;
- };
+ /*
+ * Perform a signature operation
+ * @param rng a random number generator
+ */
+ virtual bool is_valid_signature(const byte sig[], size_t sig_len) = 0;
+ /**
+ * Get the maximum message size in bits supported by this public key.
+ * @return maximum message in bits
+ */
+ virtual size_t max_input_bits() const = 0;
-/**
-* Public key signature creation interface
-*/
-class BOTAN_DLL Signature
- {
- public:
/**
* Find out the number of message parts supported by this scheme.
* @return number of message parts
@@ -122,37 +110,16 @@ class BOTAN_DLL Signature
*/
virtual size_t message_part_size() const { return 0; }
- /**
- * Get the maximum message size in bits supported by this public key.
- * @return maximum message in bits
- */
- virtual size_t max_input_bits() const = 0;
-
- /*
- * Perform a signature operation
- * @param msg the message
- * @param msg_len the length of msg in bytes
- * @param rng a random number generator
- */
- virtual secure_vector<byte> sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng) = 0;
-
- typedef PK_Spec<Private_Key> Spec;
-
- virtual ~Signature() {}
+ virtual ~Verification() {}
};
/**
-* Public key signature verification interface
+* Public key signature creation interface
*/
-class BOTAN_DLL Verification
+class BOTAN_DLL Signature
{
public:
- /**
- * Get the maximum message size in bits supported by this public key.
- * @return maximum message in bits
- */
- virtual size_t max_input_bits() const = 0;
+ typedef PK_Spec_Private_Key Spec;
/**
* Find out the number of message parts supported by this scheme.
@@ -166,42 +133,20 @@ class BOTAN_DLL Verification
*/
virtual size_t message_part_size() const { return 0; }
- /**
- * @return boolean specifying if this key type supports message
- * recovery and thus if you need to call verify() or verify_mr()
- */
- virtual bool with_recovery() const = 0;
-
/*
- * Perform a signature check operation
+ * Add more data to the message currently being signed
* @param msg the message
* @param msg_len the length of msg in bytes
- * @param sig the signature
- * @param sig_len the length of sig in bytes
- * @returns if signature is a valid one for message
*/
- virtual bool verify(const byte[], size_t,
- const byte[], size_t)
- {
- throw Invalid_State("Message recovery required");
- }
+ virtual void update(const byte msg[], size_t msg_len) = 0;
/*
- * Perform a signature operation (with message recovery)
- * Only call this if with_recovery() returns true
- * @param msg the message
- * @param msg_len the length of msg in bytes
- * @returns recovered message
+ * Perform a signature operation
+ * @param rng a random number generator
*/
- virtual secure_vector<byte> verify_mr(const byte[],
- size_t)
- {
- throw Invalid_State("Message recovery not supported");
- }
+ virtual secure_vector<byte> sign(RandomNumberGenerator& rng) = 0;
- typedef PK_Spec<Public_Key> Spec;
-
- virtual ~Verification() {}
+ virtual ~Signature() {}
};
/**
@@ -210,30 +155,15 @@ class BOTAN_DLL Verification
class BOTAN_DLL Key_Agreement
{
public:
+ typedef PK_Spec_Private_Key Spec;
+
virtual secure_vector<byte> agree(size_t key_len,
const byte other_key[], size_t other_key_len,
const byte salt[], size_t salt_len) = 0;
- typedef PK_Spec<Private_Key> Spec;
-
virtual ~Key_Agreement() {}
};
-class BOTAN_DLL Key_Agreement_with_KDF : public Key_Agreement
- {
- public:
- secure_vector<byte> agree(size_t key_len,
- const byte other_key[], size_t other_key_len,
- const byte salt[], size_t salt_len) override;
-
- protected:
- Key_Agreement_with_KDF(const std::string& kdf);
- ~Key_Agreement_with_KDF();
- private:
- virtual secure_vector<byte> raw_agree(const byte w[], size_t w_len) = 0;
- std::unique_ptr<KDF> m_kdf;
- };
-
}
}
diff --git a/src/lib/pubkey/pk_ops_impl.h b/src/lib/pubkey/pk_ops_impl.h
new file mode 100644
index 000000000..f27de4af4
--- /dev/null
+++ b/src/lib/pubkey/pk_ops_impl.h
@@ -0,0 +1,146 @@
+/*
+* (C) 2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PK_OPERATION_IMPL_H__
+#define BOTAN_PK_OPERATION_IMPL_H__
+
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+namespace PK_Ops {
+
+class Encryption_with_EME : public Encryption
+ {
+ public:
+ size_t max_input_bits() const override;
+
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
+
+ ~Encryption_with_EME();
+ protected:
+ Encryption_with_EME(const std::string& eme);
+ private:
+ virtual size_t max_raw_input_bits() const = 0;
+
+ virtual secure_vector<byte> raw_encrypt(const byte msg[], size_t len,
+ RandomNumberGenerator& rng) = 0;
+ std::unique_ptr<EME> m_eme;
+ };
+
+class Decryption_with_EME : public Decryption
+ {
+ public:
+ size_t max_input_bits() const override;
+
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len) override;
+
+ ~Decryption_with_EME();
+ protected:
+ Decryption_with_EME(const std::string& eme);
+ private:
+ virtual size_t max_raw_input_bits() const = 0;
+ virtual secure_vector<byte> raw_decrypt(const byte msg[], size_t len) = 0;
+ std::unique_ptr<EME> m_eme;
+ };
+
+class Verification_with_EMSA : public Verification
+ {
+ public:
+ void update(const byte msg[], size_t msg_len) override;
+ bool is_valid_signature(const byte sig[], size_t sig_len) override;
+
+ bool do_check(const secure_vector<byte>& msg,
+ const byte sig[], size_t sig_len);
+
+ protected:
+
+ Verification_with_EMSA(const std::string& emsa);
+ ~Verification_with_EMSA();
+
+ /**
+ * @return boolean specifying if this key type supports message
+ * recovery and thus if you need to call verify() or verify_mr()
+ */
+ virtual bool with_recovery() const = 0;
+
+ /*
+ * Perform a signature check operation
+ * @param msg the message
+ * @param msg_len the length of msg in bytes
+ * @param sig the signature
+ * @param sig_len the length of sig in bytes
+ * @returns if signature is a valid one for message
+ */
+ virtual bool verify(const byte[], size_t,
+ const byte[], size_t)
+ {
+ throw Invalid_State("Message recovery required");
+ }
+
+ /*
+ * Perform a signature operation (with message recovery)
+ * Only call this if with_recovery() returns true
+ * @param msg the message
+ * @param msg_len the length of msg in bytes
+ * @returns recovered message
+ */
+ virtual secure_vector<byte> verify_mr(const byte[], size_t)
+ {
+ throw Invalid_State("Message recovery not supported");
+ }
+
+ private:
+ std::unique_ptr<EMSA> m_emsa;
+ };
+
+class Signature_with_EMSA : public Signature
+ {
+ public:
+ void update(const byte msg[], size_t msg_len) override;
+
+ secure_vector<byte> sign(RandomNumberGenerator& rng) override;
+ protected:
+ Signature_with_EMSA(const std::string& emsa);
+ ~Signature_with_EMSA();
+ private:
+
+ /**
+ * Get the maximum message size in bits supported by this public key.
+ * @return maximum message in bits
+ */
+ virtual size_t max_input_bits() const = 0;
+
+ bool self_test_signature(const std::vector<byte>& msg,
+ const std::vector<byte>& sig) const;
+
+ virtual secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) = 0;
+
+ std::unique_ptr<EMSA> m_emsa;
+ };
+
+class Key_Agreement_with_KDF : public Key_Agreement
+ {
+ public:
+ secure_vector<byte> agree(size_t key_len,
+ const byte other_key[], size_t other_key_len,
+ const byte salt[], size_t salt_len) override;
+
+ protected:
+ Key_Agreement_with_KDF(const std::string& kdf);
+ ~Key_Agreement_with_KDF();
+ private:
+ virtual secure_vector<byte> raw_agree(const byte w[], size_t w_len) = 0;
+ std::unique_ptr<KDF> m_kdf;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/lib/pubkey/pk_utils.h b/src/lib/pubkey/pk_utils.h
index 2d643d862..14c304ac5 100644
--- a/src/lib/pubkey/pk_utils.h
+++ b/src/lib/pubkey/pk_utils.h
@@ -9,7 +9,7 @@
#define BOTAN_PK_UTILS_H__
#include <botan/internal/algo_registry.h>
-#include <botan/pk_ops.h>
+#include <botan/internal/pk_ops_impl.h>
#include <botan/numthry.h>
#include <algorithm>
diff --git a/src/lib/pubkey/pubkey.cpp b/src/lib/pubkey/pubkey.cpp
index a2bb44e5c..1d32697f5 100644
--- a/src/lib/pubkey/pubkey.cpp
+++ b/src/lib/pubkey/pubkey.cpp
@@ -5,18 +5,10 @@
*/
#include <botan/pubkey.h>
+#include <botan/internal/algo_registry.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/bigint.h>
-#include <botan/parsing.h>
-#include <botan/internal/algo_registry.h>
-#include <botan/internal/bit_ops.h>
-
-#if defined(BOTAN_HAS_SYSTEM_RNG)
- #include <botan/system_rng.h>
-#else
- #include <botan/auto_rng.h>
-#endif
namespace Botan {
@@ -73,132 +65,88 @@ SymmetricKey PK_Key_Agreement::derive_key(size_t key_len,
return m_op->agree(key_len, in, in_len, salt, salt_len);
}
-/*
-* PK_Signer Constructor
-*/
-PK_Signer::PK_Signer(const Private_Key& key,
- const std::string& emsa,
- Signature_Format format,
- Fault_Protection prot)
- {
- m_op.reset(get_pk_op<PK_Ops::Signature>(key, emsa));
-
- if(prot == ENABLE_FAULT_PROTECTION)
- m_verify_op.reset(get_pk_op<PK_Ops::Verification>(key, emsa));
-
- if(!m_op || (prot == ENABLE_FAULT_PROTECTION && !m_verify_op))
- throw Lookup_Error("Signing with " + key.algo_name() + " not supported");
-
- m_emsa.reset(get_emsa(emsa));
- m_sig_format = format;
- }
+namespace {
-/*
-* Sign a message
-*/
-std::vector<byte> PK_Signer::sign_message(const byte msg[], size_t length,
- RandomNumberGenerator& rng)
+std::vector<byte> der_encode_signature(const std::vector<byte>& sig, size_t parts)
{
- update(msg, length);
- return signature(rng);
- }
+ if(sig.size() % parts)
+ throw Encoding_Error("PK_Signer: strange signature size found");
+ const size_t SIZE_OF_PART = sig.size() / parts;
-/*
-* Add more to the message to be signed
-*/
-void PK_Signer::update(const byte in[], size_t length)
- {
- m_emsa->update(in, length);
+ std::vector<BigInt> sig_parts(parts);
+ for(size_t j = 0; j != sig_parts.size(); ++j)
+ sig_parts[j].binary_decode(&sig[SIZE_OF_PART*j], SIZE_OF_PART);
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_list(sig_parts)
+ .end_cons()
+ .get_contents_unlocked();
}
-/*
-* Check the signature we just created, to help prevent fault attacks
-*/
-bool PK_Signer::self_test_signature(const std::vector<byte>& msg,
- const std::vector<byte>& sig) const
+std::vector<byte> der_decode_signature(const byte sig[], size_t len,
+ size_t part_size, size_t parts)
{
- if(!m_verify_op)
- return true; // checking disabled, assume ok
+ std::vector<byte> real_sig;
+ BER_Decoder decoder(sig, len);
+ BER_Decoder ber_sig = decoder.start_cons(SEQUENCE);
- if(m_verify_op->with_recovery())
+ size_t count = 0;
+ while(ber_sig.more_items())
{
- std::vector<byte> recovered =
- unlock(m_verify_op->verify_mr(&sig[0], sig.size()));
+ BigInt sig_part;
+ ber_sig.decode(sig_part);
+ real_sig += BigInt::encode_1363(sig_part, part_size);
+ ++count;
+ }
- if(msg.size() > recovered.size())
- {
- size_t extra_0s = msg.size() - recovered.size();
+ if(count != parts)
+ throw Decoding_Error("PK_Verifier: signature size invalid");
+ return real_sig;
+ }
- for(size_t i = 0; i != extra_0s; ++i)
- if(msg[i] != 0)
- return false;
+}
- return same_mem(&msg[extra_0s], &recovered[0], recovered.size());
- }
+PK_Signer::PK_Signer(const Private_Key& key,
+ const std::string& emsa,
+ Signature_Format format)
+ {
+ m_op.reset(get_pk_op<PK_Ops::Signature>(key, emsa));
+ if(!m_op)
+ throw Lookup_Error("Signing with " + key.algo_name() + "/" + emsa + " not supported");
+ m_sig_format = format;
+ }
- return (recovered == msg);
- }
- else
- return m_verify_op->verify(&msg[0], msg.size(),
- &sig[0], sig.size());
+void PK_Signer::update(const byte in[], size_t length)
+ {
+ m_op->update(in, length);
}
-/*
-* Create a signature
-*/
std::vector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
{
- std::vector<byte> encoded = unlock(m_emsa->encoding_of(m_emsa->raw_data(),
- m_op->max_input_bits(),
- rng));
-
- std::vector<byte> plain_sig = unlock(m_op->sign(&encoded[0], encoded.size(), rng));
-
- BOTAN_ASSERT(self_test_signature(encoded, plain_sig), "Signature was consistent");
+ const std::vector<byte> plain_sig = unlock(m_op->sign(rng));
+ const size_t parts = m_op->message_parts();
- if(m_op->message_parts() == 1 || m_sig_format == IEEE_1363)
+ if(parts == 1 || m_sig_format == IEEE_1363)
return plain_sig;
-
- if(m_sig_format == DER_SEQUENCE)
- {
- if(plain_sig.size() % m_op->message_parts())
- throw Encoding_Error("PK_Signer: strange signature size found");
- const size_t SIZE_OF_PART = plain_sig.size() / m_op->message_parts();
-
- std::vector<BigInt> sig_parts(m_op->message_parts());
- for(size_t j = 0; j != sig_parts.size(); ++j)
- sig_parts[j].binary_decode(&plain_sig[SIZE_OF_PART*j], SIZE_OF_PART);
-
- return DER_Encoder()
- .start_cons(SEQUENCE)
- .encode_list(sig_parts)
- .end_cons()
- .get_contents_unlocked();
- }
+ else if(m_sig_format == DER_SEQUENCE)
+ return der_encode_signature(plain_sig, parts);
else
throw Encoding_Error("PK_Signer: Unknown signature format " +
std::to_string(m_sig_format));
}
-/*
-* PK_Verifier Constructor
-*/
PK_Verifier::PK_Verifier(const Public_Key& key,
const std::string& emsa_name,
Signature_Format format)
{
m_op.reset(get_pk_op<PK_Ops::Verification>(key, emsa_name));
-
if(!m_op)
throw Lookup_Error("Verification with " + key.algo_name() + " not supported");
- m_emsa.reset(get_emsa(emsa_name));
m_sig_format = format;
}
-/*
-* Set the signature format
-*/
void PK_Verifier::set_input_format(Signature_Format format)
{
if(m_op->message_parts() == 1 && format != IEEE_1363)
@@ -206,9 +154,6 @@ void PK_Verifier::set_input_format(Signature_Format format)
m_sig_format = format;
}
-/*
-* Verify a message
-*/
bool PK_Verifier::verify_message(const byte msg[], size_t msg_length,
const byte sig[], size_t sig_length)
{
@@ -216,42 +161,25 @@ bool PK_Verifier::verify_message(const byte msg[], size_t msg_length,
return check_signature(sig, sig_length);
}
-/*
-* Append to the message
-*/
void PK_Verifier::update(const byte in[], size_t length)
{
- m_emsa->update(in, length);
+ m_op->update(in, length);
}
-/*
-* Check a signature
-*/
bool PK_Verifier::check_signature(const byte sig[], size_t length)
{
try {
if(m_sig_format == IEEE_1363)
- return validate_signature(m_emsa->raw_data(), sig, length);
+ {
+ return m_op->is_valid_signature(sig, length);
+ }
else if(m_sig_format == DER_SEQUENCE)
{
- BER_Decoder decoder(sig, length);
- BER_Decoder ber_sig = decoder.start_cons(SEQUENCE);
-
- size_t count = 0;
- std::vector<byte> real_sig;
- while(ber_sig.more_items())
- {
- BigInt sig_part;
- ber_sig.decode(sig_part);
- real_sig += BigInt::encode_1363(sig_part, m_op->message_part_size());
- ++count;
- }
-
- if(count != m_op->message_parts())
- throw Decoding_Error("PK_Verifier: signature size invalid");
-
- return validate_signature(m_emsa->raw_data(),
- &real_sig[0], real_sig.size());
+ std::vector<byte> real_sig = der_decode_signature(sig, length,
+ m_op->message_part_size(),
+ m_op->message_parts());
+
+ return m_op->is_valid_signature(&real_sig[0], real_sig.size());
}
else
throw Decoding_Error("PK_Verifier: Unknown signature format " +
@@ -260,26 +188,4 @@ bool PK_Verifier::check_signature(const byte sig[], size_t length)
catch(Invalid_Argument) { return false; }
}
-/*
-* Verify a signature
-*/
-bool PK_Verifier::validate_signature(const secure_vector<byte>& msg,
- const byte sig[], size_t sig_len)
- {
- if(m_op->with_recovery())
- {
- secure_vector<byte> output_of_key = m_op->verify_mr(sig, sig_len);
- return m_emsa->verify(output_of_key, msg, m_op->max_input_bits());
- }
- else
- {
- Null_RNG rng;
-
- secure_vector<byte> encoded =
- m_emsa->encoding_of(msg, m_op->max_input_bits(), rng);
-
- return m_op->verify(&encoded[0], encoded.size(), sig, sig_len);
- }
- }
-
}
diff --git a/src/lib/pubkey/pubkey.h b/src/lib/pubkey/pubkey.h
index ffb00979d..54c55c597 100644
--- a/src/lib/pubkey/pubkey.h
+++ b/src/lib/pubkey/pubkey.h
@@ -24,14 +24,6 @@ namespace Botan {
enum Signature_Format { IEEE_1363, DER_SEQUENCE };
/**
-* Enum marking if protection against fault attacks should be used
-*/
-enum Fault_Protection {
- ENABLE_FAULT_PROTECTION,
- DISABLE_FAULT_PROTECTION
-};
-
-/**
* Public Key Encryptor
*/
class BOTAN_DLL PK_Encryptor
@@ -136,7 +128,11 @@ class BOTAN_DLL PK_Signer
* @return signature
*/
std::vector<byte> sign_message(const byte in[], size_t length,
- RandomNumberGenerator& rng);
+ RandomNumberGenerator& rng)
+ {
+ this->update(in, length);
+ return this->signature(rng);
+ }
/**
* Sign a message.
@@ -191,19 +187,12 @@ class BOTAN_DLL PK_Signer
* @param emsa the EMSA to use
* An example would be "EMSA1(SHA-224)".
* @param format the signature format to use
- * @param prot says if fault protection should be enabled
*/
PK_Signer(const Private_Key& key,
const std::string& emsa,
- Signature_Format format = IEEE_1363,
- Fault_Protection prot = ENABLE_FAULT_PROTECTION);
+ Signature_Format format = IEEE_1363);
private:
- bool self_test_signature(const std::vector<byte>& msg,
- const std::vector<byte>& sig) const;
-
std::unique_ptr<PK_Ops::Signature> m_op;
- std::unique_ptr<PK_Ops::Verification> m_verify_op;
- std::unique_ptr<EMSA> m_emsa;
Signature_Format m_sig_format;
};
@@ -299,11 +288,7 @@ class BOTAN_DLL PK_Verifier
const std::string& emsa,
Signature_Format format = IEEE_1363);
private:
- bool validate_signature(const secure_vector<byte>& msg,
- const byte sig[], size_t sig_len);
-
std::unique_ptr<PK_Ops::Verification> m_op;
- std::unique_ptr<EMSA> m_emsa;
Signature_Format m_sig_format;
};
diff --git a/src/lib/pubkey/rsa/rsa.cpp b/src/lib/pubkey/rsa/rsa.cpp
index 464055cd7..13425a46f 100644
--- a/src/lib/pubkey/rsa/rsa.cpp
+++ b/src/lib/pubkey/rsa/rsa.cpp
@@ -112,7 +112,7 @@ class RSA_Private_Operation
Blinder m_blinder;
};
-class RSA_Signature_Operation : public PK_Ops::Signature,
+class RSA_Signature_Operation : public PK_Ops::Signature_with_EMSA,
private RSA_Private_Operation
{
public:
@@ -120,20 +120,18 @@ class RSA_Signature_Operation : public PK_Ops::Signature,
size_t max_input_bits() const override { return get_max_input_bits(); };
- RSA_Signature_Operation(const RSA_PrivateKey& rsa, const std::string&) :
+ RSA_Signature_Operation(const RSA_PrivateKey& rsa, const std::string& emsa) :
+ PK_Ops::Signature_with_EMSA(emsa),
RSA_Private_Operation(rsa)
{
}
- secure_vector<byte> sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator&) override
+ secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&) override
{
- /* We don't check signatures against powermod_e_n here because
- PK_Signer checks verification consistency for all signature
- algorithms.
- */
const BigInt m(msg, msg_len);
const BigInt x = blinded_private_op(m);
+ BOTAN_ASSERT(m == m_powermod_e_n(x), "RSA sign consistency check");
return BigInt::encode_1363(x, n.bytes());
}
};
@@ -161,7 +159,6 @@ class RSA_Decryption_Operation : public PK_Ops::Decryption_with_EME,
}
};
-
/**
* RSA public (encrypt/verify) operation
*/
@@ -208,7 +205,7 @@ class RSA_Encryption_Operation : public PK_Ops::Encryption_with_EME,
}
};
-class RSA_Verify_Operation : public PK_Ops::Verification,
+class RSA_Verify_Operation : public PK_Ops::Verification_with_EMSA,
private RSA_Public_Operation
{
public:
@@ -216,7 +213,8 @@ class RSA_Verify_Operation : public PK_Ops::Verification,
size_t max_input_bits() const override { return get_max_input_bits(); };
- RSA_Verify_Operation(const RSA_PublicKey& rsa, const std::string&) :
+ RSA_Verify_Operation(const RSA_PublicKey& rsa, const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
RSA_Public_Operation(rsa)
{
}
diff --git a/src/lib/pubkey/rw/rw.cpp b/src/lib/pubkey/rw/rw.cpp
index 32ba398b0..b706d6730 100644
--- a/src/lib/pubkey/rw/rw.cpp
+++ b/src/lib/pubkey/rw/rw.cpp
@@ -67,13 +67,14 @@ namespace {
/**
* Rabin-Williams Signature Operation
*/
-class RW_Signature_Operation : public PK_Ops::Signature
+class RW_Signature_Operation : public PK_Ops::Signature_with_EMSA
{
public:
typedef RW_PrivateKey Key_Type;
RW_Signature_Operation(const RW_PrivateKey& rw,
- const std::string&) :
+ const std::string& emsa) :
+ PK_Ops::Signature_with_EMSA(emsa),
n(rw.get_n()),
e(rw.get_e()),
q(rw.get_q()),
@@ -87,10 +88,10 @@ class RW_Signature_Operation : public PK_Ops::Signature
{
}
- size_t max_input_bits() const { return (n.bits() - 1); }
+ size_t max_input_bits() const override { return (n.bits() - 1); }
- secure_vector<byte> sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator& rng);
+ secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng) override;
private:
const BigInt& n;
const BigInt& e;
@@ -103,8 +104,8 @@ class RW_Signature_Operation : public PK_Ops::Signature
};
secure_vector<byte>
-RW_Signature_Operation::sign(const byte msg[], size_t msg_len,
- RandomNumberGenerator&)
+RW_Signature_Operation::raw_sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&)
{
BigInt i(msg, msg_len);
@@ -130,12 +131,13 @@ RW_Signature_Operation::sign(const byte msg[], size_t msg_len,
/**
* Rabin-Williams Verification Operation
*/
-class RW_Verification_Operation : public PK_Ops::Verification
+class RW_Verification_Operation : public PK_Ops::Verification_with_EMSA
{
public:
typedef RW_PublicKey Key_Type;
- RW_Verification_Operation(const RW_PublicKey& rw, const std::string&) :
+ RW_Verification_Operation(const RW_PublicKey& rw, const std::string& emsa) :
+ PK_Ops::Verification_with_EMSA(emsa),
n(rw.get_n()), powermod_e_n(rw.get_e(), rw.get_n())
{}