9#include <botan/internal/hmac.h>
11#include <botan/internal/ct_utils.h>
12#include <botan/internal/fmt.h>
19void HMAC::add_data(std::span<const uint8_t> input) {
21 m_hash->update(input);
27void HMAC::final_result(std::span<uint8_t> mac) {
30 m_hash->update(m_okey);
31 m_hash->update(mac.first(m_hash_output_length));
33 m_hash->update(m_ikey);
42 return m_hash_output_length;
46 return !m_okey.empty();
52void HMAC::key_schedule(std::span<const uint8_t> key) {
53 const uint8_t ipad = 0x36;
54 const uint8_t opad = 0x5C;
58 m_ikey.resize(m_hash_block_size);
59 m_okey.resize(m_hash_block_size);
81 if(key.size() > m_hash_block_size) {
83 m_hash->final(m_ikey.data());
84 }
else if(key.size() >= 20) {
87 copy_mem(std::span{m_ikey}.first(key.size()), key);
88 }
else if(!key.empty()) {
89 for(
size_t i = 0, i_mod_length = 0; i != m_hash_block_size; ++i) {
95 i_mod_length = needs_reduction.select(0, i_mod_length);
96 const uint8_t kb = key[i_mod_length];
99 m_ikey[i] =
static_cast<uint8_t
>(in_range.if_set_return(kb));
104 for(
size_t i = 0; i != m_hash_block_size; ++i) {
106 m_okey[i] = m_ikey[i] ^ ipad ^ opad;
109 m_hash->update(m_ikey);
125 return fmt(
"HMAC({})", m_hash->name());
132 return std::make_unique<HMAC>(m_hash->new_object());
139 m_hash(std::move(hash)),
140 m_hash_output_length(m_hash->output_length()),
141 m_hash_block_size(m_hash->hash_block_size()) {
142 BOTAN_ARG_CHECK(m_hash_block_size >= m_hash_output_length,
"HMAC is not compatible with this hash function");
#define BOTAN_ARG_CHECK(expr, msg)
static constexpr Mask< T > is_lte(T x, T y)
static constexpr Mask< T > is_lt(T x, T y)
bool has_keying_material() const override
size_t output_length() const override
std::string name() const override
std::unique_ptr< MessageAuthenticationCode > new_object() const override
Key_Length_Specification key_spec() const override
HMAC(std::unique_ptr< HashFunction > hash)
void assert_key_material_set() const
void zap(std::vector< T, Alloc > &vec)
std::string fmt(std::string_view format, const T &... args)
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr void clear_mem(T *ptr, size_t n)