Kea 2.0.2
openssl_hmac.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <cryptolink.h>
11
12#include <boost/scoped_ptr.hpp>
13
14#include <openssl/hmac.h>
15
17#define KEA_HMAC
19
20#include <cstring>
21
22namespace isc {
23namespace cryptolink {
24
27class HMACImpl {
28public:
36 explicit HMACImpl(const void* secret, size_t secret_len,
37 const HashAlgorithm hash_algorithm)
38 : hash_algorithm_(hash_algorithm), md_() {
39 const EVP_MD* algo = ossl::getHashAlgorithm(hash_algorithm);
40 if (algo == 0) {
42 "Unknown hash algorithm: " <<
43 static_cast<int>(hash_algorithm));
44 }
45 if (secret_len == 0) {
46 isc_throw(BadKey, "Bad HMAC secret length: 0");
47 }
48
49 md_ = HMAC_CTX_new();
50 if (md_ == 0) {
51 isc_throw(LibraryError, "OpenSSL HMAC_CTX_new() failed");
52 }
53
54 if (!HMAC_Init_ex(md_, secret,
55 static_cast<int>(secret_len),
56 algo, NULL)) {
57 isc_throw(LibraryError, "OpenSSL HMAC_Init_ex() failed");
58 }
59 }
60
63 if (md_) {
64 HMAC_CTX_free(md_);
65 }
66 md_ = 0;
67 }
68
71 return (hash_algorithm_);
72 }
73
77 size_t getOutputLength() const {
78 int size = HMAC_size(md_);
79 if (size < 0) {
80 isc_throw(LibraryError, "OpenSSL HMAC_size() failed");
81 }
82 return (static_cast<size_t>(size));
83 }
84
88 void update(const void* data, const size_t len) {
89 if (!HMAC_Update(md_,
90 static_cast<const unsigned char*>(data),
91 len)) {
92 isc_throw(LibraryError, "OpenSSLHMAC_Update() failed");
93 }
94 }
95
99 void sign(isc::util::OutputBuffer& result, size_t len) {
100 size_t size = getOutputLength();
102 if (!HMAC_Final(md_, &digest[0], NULL)) {
103 isc_throw(LibraryError, "OpenSSL HMAC_Final() failed");
104 }
105 if (len > size) {
106 len = size;
107 }
108 result.writeData(&digest[0], len);
109 }
110
114 void sign(void* result, size_t len) {
115 size_t size = getOutputLength();
117 if (!HMAC_Final(md_, &digest[0], NULL)) {
118 isc_throw(LibraryError, "OpenSSL HMAC_Final() failed");
119 }
120 if (len > size) {
121 len = size;
122 }
123 std::memcpy(result, &digest[0], len);
124 }
125
129 std::vector<uint8_t> sign(size_t len) {
130 size_t size = getOutputLength();
132 if (!HMAC_Final(md_, &digest[0], NULL)) {
133 isc_throw(LibraryError, "OpenSSL HMAC_Final() failed");
134 }
135 if (len < size) {
136 digest.resize(len);
137 }
138 return (std::vector<uint8_t>(digest.begin(), digest.end()));
139 }
140
144 bool verify(const void* sig, size_t len) {
145 // Check the length
146 size_t size = getOutputLength();
147 if (len < 10 || len < size / 2) {
148 return (false);
149 }
150 // Get the digest from a copy of the context
151 HMAC_CTX* tmp = HMAC_CTX_new();
152 if (tmp == 0) {
153 isc_throw(LibraryError, "OpenSSL HMAC_CTX_new() failed");
154 }
155 if (!HMAC_CTX_copy(tmp, md_)) {
156 HMAC_CTX_free(tmp);
157 isc_throw(LibraryError, "OpenSSL HMAC_CTX_copy() failed");
158 }
160 if (!HMAC_Final(tmp, &digest[0], NULL)) {
161 HMAC_CTX_free(tmp);
162 isc_throw(LibraryError, "OpenSSL HMAC_Final() failed");
163 }
164 HMAC_CTX_free(tmp);
165 if (len > size) {
166 len = size;
167 }
168 return (digest.same(sig, len));
169 }
170
171private:
173 HashAlgorithm hash_algorithm_;
174
176 HMAC_CTX* md_;
177};
178
179HMAC::HMAC(const void* secret, size_t secret_length,
180 const HashAlgorithm hash_algorithm)
181{
182 impl_ = new HMACImpl(secret, secret_length, hash_algorithm);
183}
184
185HMAC::~HMAC() {
186 delete impl_;
187}
188
191 return (impl_->getHashAlgorithm());
192}
193
194size_t
195HMAC::getOutputLength() const {
196 return (impl_->getOutputLength());
197}
198
199void
200HMAC::update(const void* data, const size_t len) {
201 impl_->update(data, len);
202}
203
204void
205HMAC::sign(isc::util::OutputBuffer& result, size_t len) {
206 impl_->sign(result, len);
207}
208
209void
210HMAC::sign(void* result, size_t len) {
211 impl_->sign(result, len);
212}
213
214std::vector<uint8_t>
215HMAC::sign(size_t len) {
216 return impl_->sign(len);
217}
218
219bool
220HMAC::verify(const void* sig, const size_t len) {
221 return (impl_->verify(sig, len));
222}
223
224} // namespace cryptolink
225} // namespace isc
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:550
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-lfc.