| Kea 3.0.2-git

openssl_hmac.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2025 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>
10#include <cryptolink/crypto_hmac.h>
11
12#include <boost/scoped_ptr.hpp>
13
14#include <openssl/evp.h>
15
16#include <cryptolink/openssl_common.h>
17
18#include <cstring>
19
20 namespace isc {
21 namespace cryptolink {
22
25 class HMACImpl {
26 public:
34 explicit HMACImpl(const void* secret, size_t secret_len,
35 const HashAlgorithm hash_algorithm)
36 : hash_algorithm_(hash_algorithm), md_(), digest_() {
37 const EVP_MD* algo = ossl::getHashAlgorithm(hash_algorithm);
38 if (algo == 0) {
39 isc_throw(UnsupportedAlgorithm,
40 "Unknown hash algorithm: " <<
41 static_cast<int>(hash_algorithm));
42 }
43 if (secret_len == 0) {
44 isc_throw(BadKey, "Bad HMAC secret length: 0");
45 }
46
47 md_ = EVP_MD_CTX_new();
48 if (md_ == 0) {
49 isc_throw(LibraryError, "OpenSSL EVP_MD_CTX_new() failed");
50 }
51
52 EVP_PKEY* pkey =
53 EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
54 reinterpret_cast<const unsigned char*>(secret),
55 secret_len);
56
57 if (pkey == 0) {
58 isc_throw(LibraryError,
59 "OpenSSL EVP_PKEY_new_raw_private_key() failed");
60 }
61
62 if (!EVP_DigestSignInit(md_, NULL, algo, NULL, pkey)) {
63 EVP_PKEY_free(pkey);
64 isc_throw(LibraryError, "OpenSSL EVP_DigestSignInit() failed");
65 }
66
67 EVP_PKEY_free(pkey);
68 }
69
71 ~HMACImpl() {
72 if (md_) {
73 EVP_MD_CTX_free(md_);
74 }
75 md_ = 0;
76 }
77
79 HashAlgorithm getHashAlgorithm() const {
80 return (hash_algorithm_);
81 }
82
86 size_t getOutputLength() const {
87 return (EVP_MD_CTX_size(md_));
88 }
89
93 void update(const void* data, const size_t len) {
94 if (len == 0) {
95 return;
96 }
97
98 if (!EVP_DigestSignUpdate(md_, data, len)) {
99 isc_throw(LibraryError, "OpenSSL EVP_DigestSignUpdate() failed");
100 }
101 }
102
106 void sign(isc::util::OutputBuffer& result, size_t len) {
107 size_t size = getOutputLength();
108 ossl::SecBuf<unsigned char> digest(size);
109 size_t digest_len = size;
110 if (!EVP_DigestSignFinal(md_, &digest[0], &digest_len)) {
111 isc_throw(LibraryError, "OpenSSL EVP_DigestSignFinal() failed");
112 }
113 if (digest_len != size) {
114 isc_throw(LibraryError, "OpenSSL partial EVP_DigestSignFinal()");
115 }
116 if (len > size) {
117 len = size;
118 }
119 result.writeData(&digest[0], len);
120 }
121
125 void sign(void* result, size_t len) {
126 size_t size = getOutputLength();
127 ossl::SecBuf<unsigned char> digest(size);
128 size_t digest_len = size;
129 if (!EVP_DigestSignFinal(md_, &digest[0], &digest_len)) {
130 isc_throw(LibraryError, "OpenSSL EVP_DigestSignFinal() failed");
131 }
132 if (digest_len != size) {
133 isc_throw(LibraryError, "OpenSSL partial EVP_DigestSignFinal()");
134 }
135 if (len > size) {
136 len = size;
137 }
138 std::memcpy(result, &digest[0], len);
139 }
140
144 std::vector<uint8_t> sign(size_t len) {
145 size_t size = getOutputLength();
146 ossl::SecBuf<unsigned char> digest(size);
147 size_t digest_len = size;
148 if (!EVP_DigestSignFinal(md_, &digest[0], &digest_len)) {
149 isc_throw(LibraryError, "OpenSSL EVP_DigestSignFinal() failed");
150 }
151 if (digest_len != size) {
152 isc_throw(LibraryError, "OpenSSL partial EVP_DigestSignFinal()");
153 }
154 if (len < size) {
155 digest.resize(len);
156 }
157 return (std::vector<uint8_t>(digest.begin(), digest.end()));
158 }
159
163 bool verify(const void* sig, size_t len) {
164 // Check the length
165 size_t size = getOutputLength();
166 if (len < 10 || len < size / 2) {
167 return (false);
168 }
169 if (digest_.size() == 0) {
170 digest_.resize(size);
171 size_t digest_len = size;
172 if (!EVP_DigestSignFinal(md_, &digest_[0], &digest_len)) {
173 isc_throw(LibraryError, "OpenSSL EVP_DigestSignFinal() failed");
174 }
175 if (digest_len != size) {
176 isc_throw(LibraryError, "OpenSSL partial EVP_DigestSignFinal()");
177 }
178 }
179 if (len > size) {
180 len = size;
181 }
182 return (digest_.same(sig, len));
183 }
184
185 private:
187 HashAlgorithm hash_algorithm_;
188
190 EVP_MD_CTX* md_;
191
193 ossl::SecBuf<unsigned char> digest_;
194};
195
196HMAC::HMAC(const void* secret, size_t secret_length,
197 const HashAlgorithm hash_algorithm)
198{
199 impl_ = new HMACImpl(secret, secret_length, hash_algorithm);
200}
201
202 HMAC::~HMAC() {
203 delete impl_;
204}
205
206 HashAlgorithm
207 HMAC::getHashAlgorithm() const {
208 return (impl_->getHashAlgorithm());
209}
210
211 size_t
212 HMAC::getOutputLength() const {
213 return (impl_->getOutputLength());
214}
215
216 void
217 HMAC::update(const void* data, const size_t len) {
218 impl_->update(data, len);
219}
220
221 void
222 HMAC::sign(isc::util::OutputBuffer& result, size_t len) {
223 impl_->sign(result, len);
224}
225
226 void
227 HMAC::sign(void* result, size_t len) {
228 impl_->sign(result, len);
229}
230
231std::vector<uint8_t>
232 HMAC::sign(size_t len) {
233 return impl_->sign(len);
234}
235
236 bool
237 HMAC::verify(const void* sig, const size_t len) {
238 return (impl_->verify(sig, len));
239}
240
241} // namespace cryptolink
242} // namespace isc
isc::cryptolink::BadKey
This exception is thrown when the underlying library could not handle the key data.
Definition cryptolink.h:76
isc::cryptolink::HMACImpl
Botan implementation of HMAC.
Definition botan_hmac.cc:46
isc::cryptolink::HMACImpl::sign
std::vector< uint8_t > sign(size_t len)
Calculate the final signature.
Definition openssl_hmac.cc:144
isc::cryptolink::HMACImpl::~HMACImpl
~HMACImpl()
Destructor.
Definition openssl_hmac.cc:71
isc::cryptolink::HMACImpl::sign
void sign(void *result, size_t len)
Calculate the final signature.
Definition openssl_hmac.cc:125
isc::cryptolink::HMACImpl::getOutputLength
size_t getOutputLength() const
Returns the output size of the digest.
Definition openssl_hmac.cc:86
isc::cryptolink::HMACImpl::getHashAlgorithm
HashAlgorithm getHashAlgorithm() const
Returns the HashAlgorithm of the object.
Definition openssl_hmac.cc:79
isc::cryptolink::HMACImpl::HMACImpl
HMACImpl(const void *secret, size_t secret_len, const HashAlgorithm hash_algorithm)
Constructor from a secret and a hash algorithm.
Definition openssl_hmac.cc:34
isc::cryptolink::HMACImpl::sign
void sign(isc::util::OutputBuffer &result, size_t len)
Calculate the final signature.
Definition openssl_hmac.cc:106
isc::cryptolink::HMACImpl::verify
bool verify(const void *sig, size_t len)
Verify an existing signature.
Definition openssl_hmac.cc:163
isc::cryptolink::HMACImpl::update
void update(const void *data, const size_t len)
Add data to digest.
Definition openssl_hmac.cc:93
isc::cryptolink::HMAC::update
void update(const void *data, const size_t len)
Add data to digest.
Definition botan_hmac.cc:219
isc::cryptolink::HMAC::verify
bool verify(const void *sig, size_t len)
Verify an existing signature.
Definition botan_hmac.cc:239
isc::cryptolink::HMAC::getOutputLength
size_t getOutputLength() const
Returns the output size of the digest.
Definition botan_hmac.cc:214
isc::cryptolink::HMAC::~HMAC
~HMAC()
Destructor.
Definition botan_hmac.cc:204
isc::cryptolink::HMAC::sign
void sign(isc::util::OutputBuffer &result, size_t len)
Calculate the final signature.
Definition botan_hmac.cc:224
isc::cryptolink::HMAC::getHashAlgorithm
HashAlgorithm getHashAlgorithm() const
Returns the HashAlgorithm of the object.
Definition botan_hmac.cc:209
isc::cryptolink::LibraryError
This exception is raised when a general error that was not specifically caught is thrown by the under...
Definition cryptolink.h:86
isc::cryptolink::UnsupportedAlgorithm
This exception is thrown when a cryptographic action is requested for an algorithm that is not suppor...
Definition cryptolink.h:68
isc::cryptolink::ossl::SecBuf
Secure Buffers which are wiped out when released.
Definition openssl_common.h:23
isc::util::OutputBuffer
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition buffer.h:346
isc::util::OutputBuffer::writeData
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition buffer.h:559
crypto_hmac.h
cryptolink.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
isc::cryptolink::ossl::getHashAlgorithm
const EVP_MD * getHashAlgorithm(isc::cryptolink::HashAlgorithm algorithm)
Decode the HashAlgorithm enum into an EVP_MD pointer (or 0).
Definition openssl_hash.cc:24
isc::cryptolink
Definition botan_common.h:8
isc::cryptolink::HashAlgorithm
HashAlgorithm
Hash algorithm identifiers.
Definition cryptolink.h:23
isc::cryptolink::digest
void digest(const void *data, const size_t data_len, const HashAlgorithm hash_algorithm, isc::util::OutputBuffer &result, size_t len)
Create an Hash digest for the given data.
Definition crypto_hash.cc:20
isc::data
Definition base_stamped_element.cc:12
isc
Defines the logger used by the top-level component of kea-lfc.
Definition agent_parser.cc:148
openssl_common.h