aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/prov/bearssl/bearssl_ec.cpp8
-rw-r--r--src/lib/prov/openssl/openssl_ec.cpp14
-rw-r--r--src/lib/prov/openssl/openssl_rsa.cpp2
-rw-r--r--src/lib/prov/pkcs11/p11_ecdsa.cpp2
-rw-r--r--src/lib/prov/pkcs11/p11_rsa.cpp2
-rw-r--r--src/lib/prov/tpm/tpm.cpp5
-rw-r--r--src/lib/prov/tpm/tpm.h7
-rw-r--r--src/lib/pubkey/dl_group/dl_group.cpp7
-rw-r--r--src/lib/pubkey/dl_group/dl_group.h7
-rw-r--r--src/lib/pubkey/dsa/dsa.cpp5
-rw-r--r--src/lib/pubkey/ecdsa/ecdsa.cpp2
-rw-r--r--src/lib/pubkey/ecgdsa/ecgdsa.cpp2
-rw-r--r--src/lib/pubkey/eckcdsa/eckcdsa.cpp1
-rw-r--r--src/lib/pubkey/ed25519/ed25519_key.cpp4
-rw-r--r--src/lib/pubkey/gost_3410/gost_3410.cpp2
-rw-r--r--src/lib/pubkey/pk_ops.h5
-rw-r--r--src/lib/pubkey/pubkey.cpp16
-rw-r--r--src/lib/pubkey/pubkey.h8
-rw-r--r--src/lib/pubkey/rsa/rsa.cpp2
-rw-r--r--src/lib/pubkey/sm2/sm2.cpp2
-rw-r--r--src/lib/pubkey/xmss/xmss_signature_operation.cpp6
-rw-r--r--src/lib/pubkey/xmss/xmss_signature_operation.h2
-rw-r--r--src/tests/test_pubkey.cpp3
23 files changed, 101 insertions, 13 deletions
diff --git a/src/lib/prov/bearssl/bearssl_ec.cpp b/src/lib/prov/bearssl/bearssl_ec.cpp
index 23f566043..89f7773aa 100644
--- a/src/lib/prov/bearssl/bearssl_ec.cpp
+++ b/src/lib/prov/bearssl/bearssl_ec.cpp
@@ -77,7 +77,7 @@ class BearSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification
{
public:
BearSSL_ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, const std::string& emsa) :
- m_order_bits(ecdsa.domain().get_order().bits())
+ m_order_bits(ecdsa.domain().get_order_bits())
{
const int curve = BearSSL_EC_curve_for(ecdsa.domain().get_oid());
if (curve < 0)
@@ -132,7 +132,8 @@ class BearSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature
{
public:
BearSSL_ECDSA_Signing_Operation(const ECDSA_PrivateKey& ecdsa, const std::string& emsa) :
- m_order_bits(ecdsa.domain().get_order().bits())
+ m_order_bits(ecdsa.domain().get_order_bits()),
+ m_order_bytes(ecdsa.domain().get_order_bytes())
{
const int curve = BearSSL_EC_curve_for(ecdsa.domain().get_oid());
if(curve < 0)
@@ -175,12 +176,15 @@ class BearSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature
size_t max_input_bits() const { return m_order_bits; }
+ size_t signature_length() const override { return 2*m_order_bytes; }
+
private:
br_ec_private_key m_key;
std::unique_ptr<HashFunction> m_hf;
secure_vector<uint8_t> m_x_buf;
const br_hash_class *m_hash;
size_t m_order_bits;
+ size_t m_order_bytes;
};
}
diff --git a/src/lib/prov/openssl/openssl_ec.cpp b/src/lib/prov/openssl/openssl_ec.cpp
index b9e53b6fd..33f277d5a 100644
--- a/src/lib/prov/openssl/openssl_ec.cpp
+++ b/src/lib/prov/openssl/openssl_ec.cpp
@@ -229,8 +229,11 @@ class OpenSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
m_order_bits = ::EC_GROUP_get_degree(group);
+ m_order_bytes = (m_order_bits + 7) / 8;
}
+ size_t signature_length() const { return 2*m_order_bytes; }
+
secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
RandomNumberGenerator&) override
{
@@ -240,8 +243,6 @@ class OpenSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
if(!sig)
throw OpenSSL_Error("ECDSA_do_sign");
- const size_t order_bytes = (m_order_bits + 7) / 8;
-
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
const BIGNUM* r = sig->r;
const BIGNUM* s = sig->s;
@@ -253,9 +254,9 @@ class OpenSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
const size_t r_bytes = BN_num_bytes(r);
const size_t s_bytes = BN_num_bytes(s);
- secure_vector<uint8_t> sigval(2*order_bytes);
- BN_bn2bin(r, &sigval[order_bytes - r_bytes]);
- BN_bn2bin(s, &sigval[2*order_bytes - s_bytes]);
+ secure_vector<uint8_t> sigval(2*m_order_bytes);
+ BN_bn2bin(r, &sigval[m_order_bytes - r_bytes]);
+ BN_bn2bin(s, &sigval[2*m_order_bytes - s_bytes]);
return sigval;
}
@@ -263,7 +264,8 @@ class OpenSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
private:
std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec;
- size_t m_order_bits = 0;
+ size_t m_order_bits;
+ size_t m_order_bytes;
};
}
diff --git a/src/lib/prov/openssl/openssl_rsa.cpp b/src/lib/prov/openssl/openssl_rsa.cpp
index 6385bcbb3..cf9c2b52b 100644
--- a/src/lib/prov/openssl/openssl_rsa.cpp
+++ b/src/lib/prov/openssl/openssl_rsa.cpp
@@ -205,6 +205,8 @@ class OpenSSL_RSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
throw OpenSSL_Error("d2i_RSAPrivateKey");
}
+ size_t signature_length() const override { return ::RSA_size(m_openssl_rsa.get()); }
+
secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
RandomNumberGenerator&) override
{
diff --git a/src/lib/prov/pkcs11/p11_ecdsa.cpp b/src/lib/prov/pkcs11/p11_ecdsa.cpp
index a93e761b1..bdea2c1fa 100644
--- a/src/lib/prov/pkcs11/p11_ecdsa.cpp
+++ b/src/lib/prov/pkcs11/p11_ecdsa.cpp
@@ -100,6 +100,8 @@ class PKCS11_ECDSA_Signature_Operation final : public PK_Ops::Signature
return signature;
}
+ size_t signature_length() const override { return 2*m_order.bytes(); }
+
private:
const PKCS11_EC_PrivateKey& m_key;
const BigInt& m_order;
diff --git a/src/lib/prov/pkcs11/p11_rsa.cpp b/src/lib/prov/pkcs11/p11_rsa.cpp
index e62c038ec..65bcd2d22 100644
--- a/src/lib/prov/pkcs11/p11_rsa.cpp
+++ b/src/lib/prov/pkcs11/p11_rsa.cpp
@@ -206,6 +206,8 @@ class PKCS11_RSA_Signature_Operation final : public PK_Ops::Signature
: m_key(key), m_mechanism(MechanismWrapper::create_rsa_sign_mechanism(padding))
{}
+ size_t signature_length() const override { return m_key.get_n().bytes(); }
+
void update(const uint8_t msg[], size_t msg_len) override
{
if(!m_initialized)
diff --git a/src/lib/prov/tpm/tpm.cpp b/src/lib/prov/tpm/tpm.cpp
index ccc6e9958..4847b0df6 100644
--- a/src/lib/prov/tpm/tpm.cpp
+++ b/src/lib/prov/tpm/tpm.cpp
@@ -394,6 +394,11 @@ class TPM_Signing_Operation final : public PK_Ops::Signature
{
}
+ size_t signature_length() const override
+ {
+ return m_key.get_n().bytes();
+ }
+
void update(const uint8_t msg[], size_t msg_len) override
{
m_hash->update(msg, msg_len);
diff --git a/src/lib/prov/tpm/tpm.h b/src/lib/prov/tpm/tpm.h
index bb215a476..b6e220935 100644
--- a/src/lib/prov/tpm/tpm.h
+++ b/src/lib/prov/tpm/tpm.h
@@ -159,6 +159,10 @@ class BOTAN_PUBLIC_API(2,0) TPM_PrivateKey final : public Private_Key
bool check_key(RandomNumberGenerator& rng, bool) const override;
+ BigInt get_n() const;
+
+ BigInt get_e() const;
+
std::string algo_name() const override { return "RSA"; } // ???
std::unique_ptr<PK_Ops::Signature>
@@ -167,9 +171,6 @@ class BOTAN_PUBLIC_API(2,0) TPM_PrivateKey final : public Private_Key
const std::string& provider) const override;
private:
- BigInt get_n() const;
- BigInt get_e() const;
-
TPM_Context& m_ctx;
TSS_HKEY m_key;
diff --git a/src/lib/pubkey/dl_group/dl_group.cpp b/src/lib/pubkey/dl_group/dl_group.cpp
index abc14ec0c..804859044 100644
--- a/src/lib/pubkey/dl_group/dl_group.cpp
+++ b/src/lib/pubkey/dl_group/dl_group.cpp
@@ -67,6 +67,7 @@ class DL_Group_Data final
size_t p_bits() const { return m_p_bits; }
size_t q_bits() const { return m_q_bits; }
size_t p_bytes() const { return (m_p_bits + 7) / 8; }
+ size_t q_bytes() const { return (m_q_bits + 7) / 8; }
size_t estimated_strength() const { return m_estimated_strength; }
@@ -448,6 +449,12 @@ size_t DL_Group::q_bits() const
return data().q_bits();
}
+size_t DL_Group::q_bytes() const
+ {
+ data().assert_q_is_set("q_bytes");
+ return data().q_bytes();
+ }
+
size_t DL_Group::estimated_strength() const
{
return data().estimated_strength();
diff --git a/src/lib/pubkey/dl_group/dl_group.h b/src/lib/pubkey/dl_group/dl_group.h
index 6bc918761..43756c806 100644
--- a/src/lib/pubkey/dl_group/dl_group.h
+++ b/src/lib/pubkey/dl_group/dl_group.h
@@ -269,6 +269,13 @@ class BOTAN_PUBLIC_API(2,0) DL_Group final
size_t q_bits() const;
/**
+ * Return the size of q in bytes
+ * Same as get_q().bytes()
+ * Throws if q is unset
+ */
+ size_t q_bytes() const;
+
+ /**
* Return size in bits of a secret exponent
*
* This attempts to balance between the attack costs of NFS
diff --git a/src/lib/pubkey/dsa/dsa.cpp b/src/lib/pubkey/dsa/dsa.cpp
index 35240292c..412270173 100644
--- a/src/lib/pubkey/dsa/dsa.cpp
+++ b/src/lib/pubkey/dsa/dsa.cpp
@@ -89,7 +89,8 @@ class DSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
m_b_inv = m_group.inverse_mod_q(m_b);
}
- size_t max_input_bits() const override { return m_group.get_q().bits(); }
+ size_t signature_length() const override { return 2*m_group.q_bytes(); }
+ size_t max_input_bits() const override { return m_group.q_bits(); }
secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
RandomNumberGenerator& rng) override;
@@ -157,7 +158,7 @@ class DSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
{
}
- size_t max_input_bits() const override { return m_group.get_q().bits(); }
+ size_t max_input_bits() const override { return m_group.q_bits(); }
bool with_recovery() const override { return false; }
diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp
index a239aab73..cbb9eba67 100644
--- a/src/lib/pubkey/ecdsa/ecdsa.cpp
+++ b/src/lib/pubkey/ecdsa/ecdsa.cpp
@@ -65,6 +65,8 @@ class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
m_b_inv = m_group.inverse_mod_order(m_b);
}
+ size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
+
size_t max_input_bits() const override { return m_group.get_order_bits(); }
secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
diff --git a/src/lib/pubkey/ecgdsa/ecgdsa.cpp b/src/lib/pubkey/ecgdsa/ecgdsa.cpp
index 61b7ae055..7ed876315 100644
--- a/src/lib/pubkey/ecgdsa/ecgdsa.cpp
+++ b/src/lib/pubkey/ecgdsa/ecgdsa.cpp
@@ -46,6 +46,8 @@ class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
RandomNumberGenerator& rng) override;
+ size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
+
size_t max_input_bits() const override { return m_group.get_order_bits(); }
private:
diff --git a/src/lib/pubkey/eckcdsa/eckcdsa.cpp b/src/lib/pubkey/eckcdsa/eckcdsa.cpp
index 90716228a..40d942514 100644
--- a/src/lib/pubkey/eckcdsa/eckcdsa.cpp
+++ b/src/lib/pubkey/eckcdsa/eckcdsa.cpp
@@ -61,6 +61,7 @@ class ECKCDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
RandomNumberGenerator& rng) override;
+ size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
size_t max_input_bits() const override { return m_group.get_order_bits(); }
bool has_prefix() override { return true; }
diff --git a/src/lib/pubkey/ed25519/ed25519_key.cpp b/src/lib/pubkey/ed25519/ed25519_key.cpp
index 5f5aff369..bdb6a8547 100644
--- a/src/lib/pubkey/ed25519/ed25519_key.cpp
+++ b/src/lib/pubkey/ed25519/ed25519_key.cpp
@@ -175,6 +175,8 @@ class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature
return sig;
}
+ size_t signature_length() const override { return 64; }
+
private:
std::vector<uint8_t> m_msg;
const Ed25519_PrivateKey& m_key;
@@ -191,6 +193,8 @@ class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature
m_hash = HashFunction::create_or_throw(hash);
}
+ size_t signature_length() const override { return 64; }
+
void update(const uint8_t msg[], size_t msg_len) override
{
m_hash->update(msg, msg_len);
diff --git a/src/lib/pubkey/gost_3410/gost_3410.cpp b/src/lib/pubkey/gost_3410/gost_3410.cpp
index d6e8874ab..d2324fd13 100644
--- a/src/lib/pubkey/gost_3410/gost_3410.cpp
+++ b/src/lib/pubkey/gost_3410/gost_3410.cpp
@@ -108,6 +108,8 @@ class GOST_3410_Signature_Operation final : public PK_Ops::Signature_with_EMSA
m_x(gost_3410.private_value())
{}
+ size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
+
size_t max_input_bits() const override { return m_group.get_order_bits(); }
secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
diff --git a/src/lib/pubkey/pk_ops.h b/src/lib/pubkey/pk_ops.h
index 0aaf0b0df..3e38cc8ca 100644
--- a/src/lib/pubkey/pk_ops.h
+++ b/src/lib/pubkey/pk_ops.h
@@ -99,6 +99,11 @@ class BOTAN_PUBLIC_API(2,0) Signature
*/
virtual secure_vector<uint8_t> sign(RandomNumberGenerator& rng) = 0;
+ /*
+ * Return an upper bound on the length of the output signature
+ */
+ virtual size_t signature_length() const = 0;
+
virtual ~Signature() = default;
};
diff --git a/src/lib/pubkey/pubkey.cpp b/src/lib/pubkey/pubkey.cpp
index 99d892766..6296adbb2 100644
--- a/src/lib/pubkey/pubkey.cpp
+++ b/src/lib/pubkey/pubkey.cpp
@@ -252,6 +252,22 @@ std::vector<uint8_t> der_encode_signature(const std::vector<uint8_t>& sig,
}
+size_t PK_Signer::signature_length() const
+ {
+ if(m_sig_format == IEEE_1363)
+ {
+ return m_op->signature_length();
+ }
+ else if(m_sig_format == DER_SEQUENCE)
+ {
+ // This is a large over-estimate but its easier than computing
+ // the exact value
+ return m_op->signature_length() + (8 + 4*m_parts);
+ }
+ else
+ throw Internal_Error("PK_Signer: Invalid signature format enum");
+ }
+
std::vector<uint8_t> PK_Signer::signature(RandomNumberGenerator& rng)
{
const std::vector<uint8_t> sig = unlock(m_op->sign(rng));
diff --git a/src/lib/pubkey/pubkey.h b/src/lib/pubkey/pubkey.h
index 64bb1cc9e..8328861fd 100644
--- a/src/lib/pubkey/pubkey.h
+++ b/src/lib/pubkey/pubkey.h
@@ -264,11 +264,19 @@ class BOTAN_PUBLIC_API(2,0) PK_Signer final
*/
std::vector<uint8_t> signature(RandomNumberGenerator& rng);
+
/**
* Set the output format of the signature.
* @param format the signature format to use
*/
void set_output_format(Signature_Format format) { m_sig_format = format; }
+
+ /**
+ * Return an upper bound on the length of the signatures this
+ * PK_Signer will produce
+ */
+ size_t signature_length() const;
+
private:
std::unique_ptr<PK_Ops::Signature> m_op;
Signature_Format m_sig_format;
diff --git a/src/lib/pubkey/rsa/rsa.cpp b/src/lib/pubkey/rsa/rsa.cpp
index eb4c612ae..eefbea869 100644
--- a/src/lib/pubkey/rsa/rsa.cpp
+++ b/src/lib/pubkey/rsa/rsa.cpp
@@ -298,6 +298,8 @@ class RSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA,
size_t max_input_bits() const override { return get_max_input_bits(); }
+ size_t signature_length() const override { return m_key.get_n().bytes(); }
+
RSA_Signature_Operation(const RSA_PrivateKey& rsa, const std::string& emsa, RandomNumberGenerator& rng) :
PK_Ops::Signature_with_EMSA(emsa),
RSA_Private_Operation(rsa, rng)
diff --git a/src/lib/pubkey/sm2/sm2.cpp b/src/lib/pubkey/sm2/sm2.cpp
index c042693b3..45b14dac6 100644
--- a/src/lib/pubkey/sm2/sm2.cpp
+++ b/src/lib/pubkey/sm2/sm2.cpp
@@ -98,6 +98,8 @@ class SM2_Signature_Operation final : public PK_Ops::Signature
m_hash->update(m_za);
}
+ size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
+
void update(const uint8_t msg[], size_t msg_len) override
{
m_hash->update(msg, msg_len);
diff --git a/src/lib/pubkey/xmss/xmss_signature_operation.cpp b/src/lib/pubkey/xmss/xmss_signature_operation.cpp
index c3e43bfc9..d6a57bb08 100644
--- a/src/lib/pubkey/xmss/xmss_signature_operation.cpp
+++ b/src/lib/pubkey/xmss/xmss_signature_operation.cpp
@@ -52,6 +52,12 @@ XMSS_Signature_Operation::sign(const secure_vector<uint8_t>& msg_hash,
return sig;
}
+size_t XMSS_Signature_Operation::signature_length() const
+ {
+ // TODO bound this by the params
+ return 128*1024;
+ }
+
wots_keysig_t
XMSS_Signature_Operation::build_auth_path(XMSS_PrivateKey& priv_key,
XMSS_Address& adrs)
diff --git a/src/lib/pubkey/xmss/xmss_signature_operation.h b/src/lib/pubkey/xmss/xmss_signature_operation.h
index 5c1a14662..a1c395fa6 100644
--- a/src/lib/pubkey/xmss/xmss_signature_operation.h
+++ b/src/lib/pubkey/xmss/xmss_signature_operation.h
@@ -48,6 +48,8 @@ class XMSS_Signature_Operation final : public virtual PK_Ops::Signature,
void update(const uint8_t msg[], size_t msg_len) override;
+ size_t signature_length() const override;
+
private:
/**
* Algorithm 11: "treeSig"
diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp
index 8340e1d54..6b40e8d3c 100644
--- a/src/tests/test_pubkey.cpp
+++ b/src/tests/test_pubkey.cpp
@@ -157,6 +157,9 @@ PK_Signature_Generation_Test::run_one_test(const std::string& pad_hdr, const Var
signer.reset(new Botan::PK_Signer(*privkey, Test::rng(), padding, Botan::IEEE_1363, sign_provider));
generated_signature = signer->sign_message(message, rng ? *rng : Test::rng());
+
+ result.test_lte("Generated signature within announced bound",
+ generated_signature.size(), signer->signature_length());
}
catch(Botan::Lookup_Error&)
{