diff options
author | Jack Lloyd <[email protected]> | 2017-05-13 12:54:23 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-05-19 16:47:48 -0400 |
commit | ef2c04db178d0610352a27219e7b61b5169b826b (patch) | |
tree | f9231aa1191b81eef8bdcea256e1d07926f3681e /src/lib/misc/hotp/hotp.cpp | |
parent | dd2c8aa1707e59844ef4a30f01983b9ee5fe60fa (diff) |
Add HOTP (RFC 4226) and TOTP (RFC 6238)
Diffstat (limited to 'src/lib/misc/hotp/hotp.cpp')
-rw-r--r-- | src/lib/misc/hotp/hotp.cpp | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/lib/misc/hotp/hotp.cpp b/src/lib/misc/hotp/hotp.cpp new file mode 100644 index 000000000..f07c11c9f --- /dev/null +++ b/src/lib/misc/hotp/hotp.cpp @@ -0,0 +1,62 @@ +/* +* HOTP +* (C) 2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/hotp.h> + +namespace Botan { + +HOTP::HOTP(const SymmetricKey& key, const std::string& hash_algo, size_t digits) + { + if(digits == 6) + m_digit_mod = 1000000; + else if(digits == 7) + m_digit_mod = 10000000; + else if(digits == 8) + m_digit_mod = 100000000; + else + throw Invalid_Argument("Invalid HOTP digits"); + + /* + RFC 4228 only supports SHA-1 but TOTP allows SHA-256 and SHA-512 + and some HOTP libs support one or both as extensions + */ + if(hash_algo == "SHA-1") + m_mac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-1)"); + else if(hash_algo == "SHA-256") + m_mac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); + else if(hash_algo == "SHA-512") + m_mac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-512)"); + else + throw Invalid_Argument("Unsupported HOTP hash function"); + + m_mac->set_key(key); + } + +uint32_t HOTP::generate_hotp(uint64_t counter) + { + uint8_t counter8[8] = { 0 }; + store_be(counter, counter8); + m_mac->update(counter8, sizeof(counter8)); + const secure_vector<uint8_t> mac = m_mac->final(); + + const size_t offset = mac[mac.size()-1] & 0x0F; + const uint32_t code = load_be<uint32_t>(mac.data() + offset, 0) & 0x7FFFFFFF; + return code % m_digit_mod; + } + +std::pair<bool,uint64_t> HOTP::verify_hotp(uint32_t otp, uint64_t starting_counter, size_t resync_range) + { + for(size_t i = 0; i <= resync_range; ++i) + { + if(generate_hotp(starting_counter + i) == otp) + return std::make_pair(true, starting_counter + i + 1); + } + return std::make_pair(false, starting_counter); + } + +} + |