Botan 3.4.0
Crypto and TLS for C&
hmac.cpp
Go to the documentation of this file.
1/*
2* HMAC
3* (C) 1999-2007,2014,2020 Jack Lloyd
4* 2007 Yves Jerschow
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/internal/hmac.h>
10
11#include <botan/internal/ct_utils.h>
12#include <botan/internal/fmt.h>
13
14namespace Botan {
15
16/*
17* Update a HMAC Calculation
18*/
19void HMAC::add_data(std::span<const uint8_t> input) {
21 m_hash->update(input);
22}
23
24/*
25* Finalize a HMAC Calculation
26*/
27void HMAC::final_result(std::span<uint8_t> mac) {
29 m_hash->final(mac);
30 m_hash->update(m_okey);
31 m_hash->update(mac.first(m_hash_output_length));
32 m_hash->final(mac);
33 m_hash->update(m_ikey);
34}
35
37 // Support very long lengths for things like PBKDF2 and the TLS PRF
38 return Key_Length_Specification(0, 4096);
39}
40
41size_t HMAC::output_length() const {
42 return m_hash_output_length;
43}
44
46 return !m_okey.empty();
47}
48
49/*
50* HMAC Key Schedule
51*/
52void HMAC::key_schedule(std::span<const uint8_t> key) {
53 const uint8_t ipad = 0x36;
54 const uint8_t opad = 0x5C;
55
56 m_hash->clear();
57
58 m_ikey.resize(m_hash_block_size);
59 m_okey.resize(m_hash_block_size);
60
61 clear_mem(m_ikey.data(), m_ikey.size());
62 clear_mem(m_okey.data(), m_okey.size());
63
64 /*
65 * Sometimes the HMAC key length itself is sensitive, as with PBKDF2 where it
66 * reveals the length of the passphrase. Make some attempt to hide this to
67 * side channels. Clearly if the secret is longer than the block size then the
68 * branch to hash first reveals that. In addition, counting the number of
69 * compression functions executed reveals the size at the granularity of the
70 * hash function's block size.
71 *
72 * The greater concern is for smaller keys; being able to detect when a
73 * passphrase is say 4 bytes may assist choosing weaker targets. Even though
74 * the loop bounds are constant, we can only actually read key[0..length] so
75 * it doesn't seem possible to make this computation truly constant time.
76 *
77 * We don't mind leaking if the length is exactly zero since that's
78 * trivial to simply check.
79 */
80
81 if(key.size() > m_hash_block_size) {
82 m_hash->update(key);
83 m_hash->final(m_ikey.data());
84 } else if(!key.empty()) {
85 for(size_t i = 0, i_mod_length = 0; i != m_hash_block_size; ++i) {
86 /*
87 access key[i % length] but avoiding division due to variable
88 time computation on some processors.
89 */
90 auto needs_reduction = CT::Mask<size_t>::is_lte(key.size(), i_mod_length);
91 i_mod_length = needs_reduction.select(0, i_mod_length);
92 const uint8_t kb = key[i_mod_length];
93
94 auto in_range = CT::Mask<size_t>::is_lt(i, key.size());
95 m_ikey[i] = static_cast<uint8_t>(in_range.if_set_return(kb));
96 i_mod_length += 1;
97 }
98 }
99
100 for(size_t i = 0; i != m_hash_block_size; ++i) {
101 m_ikey[i] ^= ipad;
102 m_okey[i] = m_ikey[i] ^ ipad ^ opad;
103 }
104
105 m_hash->update(m_ikey);
106}
107
108/*
109* Clear memory of sensitive data
110*/
112 m_hash->clear();
113 zap(m_ikey);
114 zap(m_okey);
115}
116
117/*
118* Return the name of this type
119*/
120std::string HMAC::name() const {
121 return fmt("HMAC({})", m_hash->name());
122}
123
124/*
125* Return a new_object of this object
126*/
127std::unique_ptr<MessageAuthenticationCode> HMAC::new_object() const {
128 return std::make_unique<HMAC>(m_hash->new_object());
129}
130
131/*
132* HMAC Constructor
133*/
134HMAC::HMAC(std::unique_ptr<HashFunction> hash) :
135 m_hash(std::move(hash)),
136 m_hash_output_length(m_hash->output_length()),
137 m_hash_block_size(m_hash->hash_block_size()) {
138 BOTAN_ARG_CHECK(m_hash_block_size >= m_hash_output_length, "HMAC is not compatible with this hash function");
139}
140
141} // namespace Botan
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
static constexpr Mask< T > is_lte(T x, T y)
Definition ct_utils.h:149
static constexpr Mask< T > is_lt(T x, T y)
Definition ct_utils.h:139
bool has_keying_material() const override
Definition hmac.cpp:45
size_t output_length() const override
Definition hmac.cpp:41
std::string name() const override
Definition hmac.cpp:120
std::unique_ptr< MessageAuthenticationCode > new_object() const override
Definition hmac.cpp:127
Key_Length_Specification key_spec() const override
Definition hmac.cpp:36
HMAC(std::unique_ptr< HashFunction > hash)
Definition hmac.cpp:134
void clear() override
Definition hmac.cpp:111
void assert_key_material_set() const
Definition sym_algo.h:139
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:117
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:120