diff options
Diffstat (limited to 'src/lib/pubkey/pubkey.cpp')
-rw-r--r-- | src/lib/pubkey/pubkey.cpp | 210 |
1 files changed, 58 insertions, 152 deletions
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); - } - } - } |