diff options
author | Jack Lloyd <[email protected]> | 2017-09-20 10:06:38 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-09-20 10:06:38 -0400 |
commit | 5909cd78d0f834076690632ebf06b47cb15aab08 (patch) | |
tree | 35ca7b4a38eb648bfaec21ee1e4d4e629896c2ec /src/lib | |
parent | f26eb881d648814163a82a2cc9e841fa55b6ce3b (diff) | |
parent | 8cae1ee8e81b4bc395a4cca338c71893cad3ddb5 (diff) |
Merge GH #1212 Add support for 'raw' PSS signatures
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/pk_pad/emsa.cpp | 13 | ||||
-rw-r--r-- | src/lib/pk_pad/emsa_pssr/pssr.cpp | 167 | ||||
-rw-r--r-- | src/lib/pk_pad/emsa_pssr/pssr.h | 38 |
3 files changed, 167 insertions, 51 deletions
diff --git a/src/lib/pk_pad/emsa.cpp b/src/lib/pk_pad/emsa.cpp index 0fd35ef43..d78c562c9 100644 --- a/src/lib/pk_pad/emsa.cpp +++ b/src/lib/pk_pad/emsa.cpp @@ -73,9 +73,10 @@ EMSA* get_emsa(const std::string& algo_spec) #if defined(BOTAN_HAS_EMSA_PSSR) if(req.algo_name() == "PSSR" || - req.algo_name() == "EMSA-PSS" || - req.algo_name() == "PSS-MGF1" || - req.algo_name() == "EMSA4") + req.algo_name() == "EMSA-PSS" || + req.algo_name() == "PSS-MGF1" || + req.algo_name() == "EMSA4" || + req.algo_name() == "PSSR_Raw") { if(req.arg_count_between(1, 3)) { @@ -85,7 +86,11 @@ EMSA* get_emsa(const std::string& algo_spec) if(auto h = HashFunction::create(req.arg(0))) { const size_t salt_size = req.arg_as_integer(2, h->output_length()); - return new PSSR(h.release(), salt_size); + + if(req.algo_name() == "PSSR_Raw") + return new PSSR_Raw(h.release(), salt_size); + else + return new PSSR(h.release(), salt_size); } } } diff --git a/src/lib/pk_pad/emsa_pssr/pssr.cpp b/src/lib/pk_pad/emsa_pssr/pssr.cpp index 65ee5a145..f0fd69a78 100644 --- a/src/lib/pk_pad/emsa_pssr/pssr.cpp +++ b/src/lib/pk_pad/emsa_pssr/pssr.cpp @@ -1,6 +1,6 @@ /* * PSSR -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2007,2017 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -11,65 +11,49 @@ namespace Botan { -/* -* PSSR Update Operation -*/ -void PSSR::update(const uint8_t input[], size_t length) - { - m_hash->update(input, length); - } - -/* -* Return the raw (unencoded) data -*/ -secure_vector<uint8_t> PSSR::raw_data() - { - return m_hash->final(); - } +namespace { /* * PSSR Encode Operation */ -secure_vector<uint8_t> PSSR::encoding_of(const secure_vector<uint8_t>& msg, - size_t output_bits, - RandomNumberGenerator& rng) +secure_vector<uint8_t> pss_encode(HashFunction& hash, + const secure_vector<uint8_t>& msg, + const secure_vector<uint8_t>& salt, + size_t output_bits) { - const size_t HASH_SIZE = m_hash->output_length(); + const size_t HASH_SIZE = hash.output_length(); + const size_t SALT_SIZE = salt.size(); if(msg.size() != HASH_SIZE) - throw Encoding_Error("PSSR::encoding_of: Bad input length"); - if(output_bits < 8*HASH_SIZE + 8*m_SALT_SIZE + 9) - throw Encoding_Error("PSSR::encoding_of: Output length is too small"); + throw Encoding_Error("Cannot encode PSS string, input length invalid for hash"); + if(output_bits < 8*HASH_SIZE + 8*SALT_SIZE + 9) + throw Encoding_Error("Cannot encode PSS string, output length too small"); const size_t output_length = (output_bits + 7) / 8; - secure_vector<uint8_t> salt = rng.random_vec(m_SALT_SIZE); - - for(size_t j = 0; j != 8; ++j) - m_hash->update(0); - m_hash->update(msg); - m_hash->update(salt); - secure_vector<uint8_t> H = m_hash->final(); + for(size_t i = 0; i != 8; ++i) + hash.update(0); + hash.update(msg); + hash.update(salt); + secure_vector<uint8_t> H = hash.final(); secure_vector<uint8_t> EM(output_length); - EM[output_length - HASH_SIZE - m_SALT_SIZE - 2] = 0x01; - buffer_insert(EM, output_length - 1 - HASH_SIZE - m_SALT_SIZE, salt); - mgf1_mask(*m_hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - 1); + EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01; + buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt); + mgf1_mask(hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - 1); EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits); buffer_insert(EM, output_length - 1 - HASH_SIZE, H); EM[output_length-1] = 0xBC; - return EM; } -/* -* PSSR Decode/Verify Operation -*/ -bool PSSR::verify(const secure_vector<uint8_t>& const_coded, - const secure_vector<uint8_t>& raw, size_t key_bits) +bool pss_verify(HashFunction& hash, + const secure_vector<uint8_t>& const_coded, + const secure_vector<uint8_t>& raw, + size_t key_bits) { - const size_t HASH_SIZE = m_hash->output_length(); + const size_t HASH_SIZE = hash.output_length(); const size_t KEY_BYTES = (key_bits + 7) / 8; if(key_bits < 8*HASH_SIZE + 9) @@ -102,7 +86,7 @@ bool PSSR::verify(const secure_vector<uint8_t>& const_coded, const uint8_t* H = &coded[DB_size]; const size_t H_size = HASH_SIZE; - mgf1_mask(*m_hash, H, H_size, DB, DB_size); + mgf1_mask(hash, H, H_size, DB, DB_size); DB[0] &= 0xFF >> TOP_BITS; size_t salt_offset = 0; @@ -116,23 +100,112 @@ bool PSSR::verify(const secure_vector<uint8_t>& const_coded, if(salt_offset == 0) return false; + const size_t salt_size = DB_size - salt_offset; + for(size_t j = 0; j != 8; ++j) - m_hash->update(0); - m_hash->update(raw); - m_hash->update(&DB[salt_offset], DB_size - salt_offset); - secure_vector<uint8_t> H2 = m_hash->final(); + hash.update(0); + hash.update(raw); + hash.update(&DB[salt_offset], salt_size); + + secure_vector<uint8_t> H2 = hash.final(); return constant_time_compare(H, H2.data(), HASH_SIZE); } +} + PSSR::PSSR(HashFunction* h) : - m_SALT_SIZE(h->output_length()), m_hash(h) + m_hash(h), m_SALT_SIZE(m_hash->output_length()) { } PSSR::PSSR(HashFunction* h, size_t salt_size) : - m_SALT_SIZE(salt_size), m_hash(h) + m_hash(h), m_SALT_SIZE(salt_size) + { + } + +/* +* PSSR Update Operation +*/ +void PSSR::update(const uint8_t input[], size_t length) + { + m_hash->update(input, length); + } + +/* +* Return the raw (unencoded) data +*/ +secure_vector<uint8_t> PSSR::raw_data() + { + return m_hash->final(); + } + +secure_vector<uint8_t> PSSR::encoding_of(const secure_vector<uint8_t>& msg, + size_t output_bits, + RandomNumberGenerator& rng) + { + secure_vector<uint8_t> salt = rng.random_vec(m_SALT_SIZE); + return pss_encode(*m_hash, msg, salt, output_bits); + } + +/* +* PSSR Decode/Verify Operation +*/ +bool PSSR::verify(const secure_vector<uint8_t>& coded, + const secure_vector<uint8_t>& raw, + size_t key_bits) + { + return pss_verify(*m_hash, coded, raw, key_bits); + } + +PSSR_Raw::PSSR_Raw(HashFunction* h) : + m_hash(h), m_SALT_SIZE(m_hash->output_length()) + { + } + +PSSR_Raw::PSSR_Raw(HashFunction* h, size_t salt_size) : + m_hash(h), m_SALT_SIZE(salt_size) + { + } + +/* +* PSSR_Raw Update Operation +*/ +void PSSR_Raw::update(const uint8_t input[], size_t length) + { + m_msg.insert(m_msg.end(), input, input + length); + } + +/* +* Return the raw (unencoded) data +*/ +secure_vector<uint8_t> PSSR_Raw::raw_data() + { + secure_vector<uint8_t> ret; + std::swap(ret, m_msg); + + if(ret.size() != m_hash->output_length()) + throw Encoding_Error("PSSR_Raw Bad input length, did not match hash"); + + return ret; + } + +secure_vector<uint8_t> PSSR_Raw::encoding_of(const secure_vector<uint8_t>& msg, + size_t output_bits, + RandomNumberGenerator& rng) + { + secure_vector<uint8_t> salt = rng.random_vec(m_SALT_SIZE); + return pss_encode(*m_hash, msg, salt, output_bits); + } + +/* +* PSSR_Raw Decode/Verify Operation +*/ +bool PSSR_Raw::verify(const secure_vector<uint8_t>& coded, + const secure_vector<uint8_t>& raw, + size_t key_bits) { + return pss_verify(*m_hash, coded, raw, key_bits); } } diff --git a/src/lib/pk_pad/emsa_pssr/pssr.h b/src/lib/pk_pad/emsa_pssr/pssr.h index 63a09b9c4..85dfefc2c 100644 --- a/src/lib/pk_pad/emsa_pssr/pssr.h +++ b/src/lib/pk_pad/emsa_pssr/pssr.h @@ -45,8 +45,46 @@ class BOTAN_PUBLIC_API(2,0) PSSR final : public EMSA const secure_vector<uint8_t>& raw, size_t key_bits) override; + std::unique_ptr<HashFunction> m_hash; size_t m_SALT_SIZE; + }; + +/** +* PSSR_Raw +* This accepts a pre-hashed buffer +*/ +class BOTAN_DLL PSSR_Raw final : public EMSA + { + public: + + /** + * @param hash the hash function to use + */ + explicit PSSR_Raw(HashFunction* hash); + + /** + * @param hash the hash function to use + * @param salt_size the size of the salt to use in bytes + */ + PSSR_Raw(HashFunction* hash, size_t salt_size); + + EMSA* clone() override { return new PSSR_Raw(m_hash->clone(), m_SALT_SIZE); } + private: + void update(const uint8_t input[], size_t length) override; + + secure_vector<uint8_t> raw_data() override; + + secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg, + size_t output_bits, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector<uint8_t>& coded, + const secure_vector<uint8_t>& raw, + size_t key_bits) override; + std::unique_ptr<HashFunction> m_hash; + size_t m_SALT_SIZE; + secure_vector<uint8_t> m_msg; }; } |