-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhmac.hpp
More file actions
190 lines (157 loc) · 4.87 KB
/
hmac.hpp
File metadata and controls
190 lines (157 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/* Copyright (c) 2009, Markus Peloquin <markus@cs.wisc.edu>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#ifndef FLUKS_HMAC_HPP
#define FLUKS_HMAC_HPP
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <openssl/hmac.h>
#include "hash.hpp"
#include "luks.hpp"
#include "support.hpp"
namespace fluks {
/** Computes hash function digests using HMAC */
struct Hmac_function {
protected:
/** Init the hash properties
* \param type The hash type
*/
Hmac_function(hash_type type) :
_traits(Hash_traits::traits(type))
{}
/** Init the hash properties
* \param traits The hash information
*/
Hmac_function(const Hash_traits *traits) : _traits(traits) {}
public:
/**
* Create an HMAC function, in an abstract sense, given a hash spec.
*
* \param name The hash spec.
* \return An HMAC function pointer, <code>nullptr</code> for
* unrecognized specs.
* \see create(type)
*/
static std::shared_ptr<Hmac_function> create(const std::string &name)
{ return create(Hash_traits::type(name)); }
/**
* Create an HMAC function, in an abstract sense, given a hash type.
*
* \param type The hash algorithm.
* \return An HMAC function pointer.
*/
static std::shared_ptr<Hmac_function> create(hash_type type);
virtual ~Hmac_function() noexcept {}
/**
* Call this to set or reset the HMAC function's context. It must be
* called at the start of each HMAC computation (i.e. each sequence of
* calls to add()).
*
* \param key The HMAC %key.
* \param sz The size of <code>%key</code> in bytes.
*/
virtual void init(const uint8_t *key, size_t sz) noexcept = 0;
/** Pipe data into the HMAC computation.
*
* \param buf Bytes to add.
* \param sz Number of bytes in <code>buf</code>.
*/
virtual void add(const uint8_t *buf, size_t sz) noexcept = 0;
/** End the hashing sequence and return the result.
*
* \param[out] buf Output buffer. At least
* <code>traits()->digest_size</code> bytes.
*/
virtual void end(uint8_t *buf) noexcept = 0;
/** Get the traits of the underlying hash function.
*
* \return The hash function properties
*/
const Hash_traits *traits() const
{ return _traits; }
private:
const Hash_traits *_traits;
};
/** An HMAC function implemented in terms of a Hash_function object */
class Hmac_impl : public Hmac_function {
public:
static const uint8_t IPAD = 0x36;
static const uint8_t OPAD = 0x5c;
/** Create an HMAC object tied to a particular hash function
*
* \param hashfn A hash object.
*/
Hmac_impl(std::shared_ptr<Hash_function> hashfn) :
Hmac_function(hashfn->traits()),
_hashfn(hashfn),
_key(new uint8_t[hashfn->traits()->block_size])
{}
~Hmac_impl() noexcept {}
void init(const uint8_t *key, size_t sz) noexcept;
void add(const uint8_t *buf, size_t sz) noexcept
{ _hashfn->add(buf, sz); }
void end(uint8_t *out) noexcept;
private:
Hmac_impl(const Hmac_impl &) : Hmac_function(0) {}
void operator=(const Hmac_impl &) {}
std::shared_ptr<Hash_function> _hashfn;
std::unique_ptr<uint8_t> _key;
};
/** OpenSSL HMAC function template */
template <
const EVP_MD *(*EVP_hashfn)(),
hash_type type>
class Hmac_ssl : public Hmac_function {
public:
Hmac_ssl() :
Hmac_function(type),
_md(EVP_hashfn()),
_valid(false)
{
_ctx = HMAC_CTX_new();
if (!_ctx)
throw Ssl_error("HMAC_CTX_new() failed");
}
~Hmac_ssl() noexcept {
HMAC_CTX_free(_ctx);
}
void init(const uint8_t *key, size_t sz) noexcept {
HMAC_Init_ex(_ctx, key, sz, _md, 0);
_valid = true;
}
void add(const uint8_t *data, size_t sz) noexcept {
if (!_valid) return;
HMAC_Update(_ctx, data, sz);
}
void end(uint8_t *out) noexcept {
if (!_valid) return;
unsigned sz = traits()->digest_size;
HMAC_Final(_ctx, out, &sz);
_valid = false;
}
private:
HMAC_CTX *_ctx;
const EVP_MD *_md;
bool _valid;
};
typedef Hmac_ssl<EVP_md5, hash_type::MD5> Hmac_md5;
typedef Hmac_ssl<EVP_ripemd160, hash_type::RMD160> Hmac_rmd160;
typedef Hmac_ssl<EVP_sha1, hash_type::SHA1> Hmac_sha1;
typedef Hmac_ssl<EVP_sha224, hash_type::SHA224> Hmac_sha224;
typedef Hmac_ssl<EVP_sha256, hash_type::SHA256> Hmac_sha256;
typedef Hmac_ssl<EVP_sha384, hash_type::SHA384> Hmac_sha384;
typedef Hmac_ssl<EVP_sha512, hash_type::SHA512> Hmac_sha512;
}
#endif