diff options
Diffstat (limited to 'lib/kdf/prf_x942')
-rw-r--r-- | lib/kdf/prf_x942/info.txt | 7 | ||||
-rw-r--r-- | lib/kdf/prf_x942/prf_x942.cpp | 92 | ||||
-rw-r--r-- | lib/kdf/prf_x942/prf_x942.h | 34 |
3 files changed, 133 insertions, 0 deletions
diff --git a/lib/kdf/prf_x942/info.txt b/lib/kdf/prf_x942/info.txt new file mode 100644 index 000000000..ff4a6f160 --- /dev/null +++ b/lib/kdf/prf_x942/info.txt @@ -0,0 +1,7 @@ +define X942_PRF 20131128 + +<requires> +asn1 +oid_lookup +sha1 +</requires> diff --git a/lib/kdf/prf_x942/prf_x942.cpp b/lib/kdf/prf_x942/prf_x942.cpp new file mode 100644 index 000000000..149be163f --- /dev/null +++ b/lib/kdf/prf_x942/prf_x942.cpp @@ -0,0 +1,92 @@ +/* +* X9.42 PRF +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/prf_x942.h> +#include <botan/der_enc.h> +#include <botan/oids.h> +#include <botan/sha160.h> +#include <botan/loadstor.h> +#include <algorithm> +#include <memory> + +namespace Botan { + +namespace { + +/* +* Encode an integer as an OCTET STRING +*/ +std::vector<byte> encode_x942_int(u32bit n) + { + byte n_buf[4] = { 0 }; + store_be(n, n_buf); + return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents_unlocked(); + } + +} + +/* +* X9.42 PRF +*/ +secure_vector<byte> X942_PRF::derive(size_t key_len, + const byte secret[], size_t secret_len, + const byte salt[], size_t salt_len) const + { + SHA_160 hash; + const OID kek_algo(key_wrap_oid); + + secure_vector<byte> key; + u32bit counter = 1; + + while(key.size() != key_len && counter) + { + hash.update(secret, secret_len); + + hash.update( + DER_Encoder().start_cons(SEQUENCE) + + .start_cons(SEQUENCE) + .encode(kek_algo) + .raw_bytes(encode_x942_int(counter)) + .end_cons() + + .encode_if(salt_len != 0, + DER_Encoder() + .start_explicit(0) + .encode(salt, salt_len, OCTET_STRING) + .end_explicit() + ) + + .start_explicit(2) + .raw_bytes(encode_x942_int(static_cast<u32bit>(8 * key_len))) + .end_explicit() + + .end_cons().get_contents() + ); + + secure_vector<byte> digest = hash.final(); + const size_t needed = std::min(digest.size(), key_len - key.size()); + key += std::make_pair(&digest[0], needed); + + ++counter; + } + + return key; + } + +/* +* X9.42 Constructor +*/ +X942_PRF::X942_PRF(const std::string& oid) + { + if(OIDS::have_oid(oid)) + key_wrap_oid = OIDS::lookup(oid).as_string(); + else + key_wrap_oid = oid; + } + +} diff --git a/lib/kdf/prf_x942/prf_x942.h b/lib/kdf/prf_x942/prf_x942.h new file mode 100644 index 000000000..f86b1bdd5 --- /dev/null +++ b/lib/kdf/prf_x942/prf_x942.h @@ -0,0 +1,34 @@ +/* +* X9.42 PRF +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_ANSI_X942_PRF_H__ +#define BOTAN_ANSI_X942_PRF_H__ + +#include <botan/kdf.h> + +namespace Botan { + +/** +* PRF from ANSI X9.42 +*/ +class BOTAN_DLL X942_PRF : public KDF + { + public: + secure_vector<byte> derive(size_t, const byte[], size_t, + const byte[], size_t) const; + + std::string name() const { return "X942_PRF(" + key_wrap_oid + ")"; } + KDF* clone() const { return new X942_PRF(key_wrap_oid); } + + X942_PRF(const std::string& oid); + private: + std::string key_wrap_oid; + }; + +} + +#endif |