diff options
Diffstat (limited to 'src/lib/pk_pad/eme_oaep')
-rw-r--r-- | src/lib/pk_pad/eme_oaep/info.txt | 8 | ||||
-rw-r--r-- | src/lib/pk_pad/eme_oaep/oaep.cpp | 134 | ||||
-rw-r--r-- | src/lib/pk_pad/eme_oaep/oaep.h | 42 |
3 files changed, 184 insertions, 0 deletions
diff --git a/src/lib/pk_pad/eme_oaep/info.txt b/src/lib/pk_pad/eme_oaep/info.txt new file mode 100644 index 000000000..7a9360633 --- /dev/null +++ b/src/lib/pk_pad/eme_oaep/info.txt @@ -0,0 +1,8 @@ +define EME_OAEP 20140118 + +load_on auto + +<requires> +hash +mgf1 +</requires> diff --git a/src/lib/pk_pad/eme_oaep/oaep.cpp b/src/lib/pk_pad/eme_oaep/oaep.cpp new file mode 100644 index 000000000..6186ba1e9 --- /dev/null +++ b/src/lib/pk_pad/eme_oaep/oaep.cpp @@ -0,0 +1,134 @@ +/* +* OAEP +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/oaep.h> +#include <botan/mgf1.h> +#include <botan/mem_ops.h> +#include <memory> + +namespace Botan { + +/* +* OAEP Pad Operation +*/ +secure_vector<byte> OAEP::pad(const byte in[], size_t in_length, + size_t key_length, + RandomNumberGenerator& rng) const + { + key_length /= 8; + + if(key_length < in_length + 2*m_Phash.size() + 1) + throw Invalid_Argument("OAEP: Input is too large"); + + secure_vector<byte> out(key_length); + + rng.randomize(&out[0], m_Phash.size()); + + buffer_insert(out, m_Phash.size(), &m_Phash[0], m_Phash.size()); + out[out.size() - in_length - 1] = 0x01; + buffer_insert(out, out.size() - in_length, in, in_length); + + mgf1_mask(*m_hash, + &out[0], m_Phash.size(), + &out[m_Phash.size()], out.size() - m_Phash.size()); + + mgf1_mask(*m_hash, + &out[m_Phash.size()], out.size() - m_Phash.size(), + &out[0], m_Phash.size()); + + return out; + } + +/* +* OAEP Unpad Operation +*/ +secure_vector<byte> OAEP::unpad(const byte in[], size_t in_length, + size_t key_length) const + { + /* + Must be careful about error messages here; if an attacker can + distinguish them, it is easy to use the differences as an oracle to + find the secret key, as described in "A Chosen Ciphertext Attack on + RSA Optimal Asymmetric Encryption Padding (OAEP) as Standardized in + PKCS #1 v2.0", James Manger, Crypto 2001 + + Also have to be careful about timing attacks! Pointed out by Falko + Strenzke. + */ + + key_length /= 8; + + // Invalid input: truncate to zero length input, causing later + // checks to fail + if(in_length > key_length) + in_length = 0; + + secure_vector<byte> input(key_length); + buffer_insert(input, key_length - in_length, in, in_length); + + mgf1_mask(*m_hash, + &input[m_Phash.size()], input.size() - m_Phash.size(), + &input[0], m_Phash.size()); + + mgf1_mask(*m_hash, + &input[0], m_Phash.size(), + &input[m_Phash.size()], input.size() - m_Phash.size()); + + bool waiting_for_delim = true; + bool bad_input = false; + size_t delim_idx = 2 * m_Phash.size(); + + /* + * GCC 4.5 on x86-64 compiles this in a way that is still vunerable + * to timing analysis. Other compilers, or GCC on other platforms, + * may or may not. + */ + for(size_t i = delim_idx; i < input.size(); ++i) + { + const bool zero_p = !input[i]; + const bool one_p = input[i] == 0x01; + + const bool add_1 = waiting_for_delim && zero_p; + + bad_input |= waiting_for_delim && !(zero_p || one_p); + + delim_idx += add_1; + + waiting_for_delim &= zero_p; + } + + // If we never saw any non-zero byte, then it's not valid input + bad_input |= waiting_for_delim; + + bad_input |= !same_mem(&input[m_Phash.size()], &m_Phash[0], m_Phash.size()); + + if(bad_input) + throw Decoding_Error("Invalid OAEP encoding"); + + return secure_vector<byte>(&input[delim_idx + 1], &input[input.size()]); + } + +/* +* Return the max input size for a given key size +*/ +size_t OAEP::maximum_input_size(size_t keybits) const + { + if(keybits / 8 > 2*m_Phash.size() + 1) + return ((keybits / 8) - 2*m_Phash.size() - 1); + else + return 0; + } + +/* +* OAEP Constructor +*/ +OAEP::OAEP(HashFunction* hash, const std::string& P) : m_hash(hash) + { + m_Phash = m_hash->process(P); + } + +} diff --git a/src/lib/pk_pad/eme_oaep/oaep.h b/src/lib/pk_pad/eme_oaep/oaep.h new file mode 100644 index 000000000..250759821 --- /dev/null +++ b/src/lib/pk_pad/eme_oaep/oaep.h @@ -0,0 +1,42 @@ +/* +* OAEP +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_OAEP_H__ +#define BOTAN_OAEP_H__ + +#include <botan/eme.h> +#include <botan/kdf.h> +#include <botan/hash.h> +#include <memory> + +namespace Botan { + +/** +* OAEP (called EME1 in IEEE 1363 and in earlier versions of the library) +*/ +class BOTAN_DLL OAEP : public EME + { + public: + size_t maximum_input_size(size_t) const; + + /** + * @param hash object to use for hashing (takes ownership) + * @param P an optional label. Normally empty. + */ + OAEP(HashFunction* hash, const std::string& P = ""); + private: + secure_vector<byte> pad(const byte[], size_t, size_t, + RandomNumberGenerator&) const; + secure_vector<byte> unpad(const byte[], size_t, size_t) const; + + secure_vector<byte> m_Phash; + std::unique_ptr<HashFunction> m_hash; + }; + +} + +#endif |