OpenVPN 3 Core Library
Loading...
Searching...
No Matches
mac.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// Wrap the OpenSSL HMAC API defined in <openssl/hmac.h> so
13// that it can be used as part of the crypto layer of the OpenVPN core.
14
15#pragma once
16
17#include <string>
18
19#include <openssl/opensslv.h>
20/* The HMAC_* methods are deprecated in OpenSSL 3.0 and the EVP_MAC methods
21 * do no exist in OpenSSL 1.1 yet. So use two distinct implementations */
22#if OPENSSL_VERSION_NUMBER < 0x30000000L
24#else
25
29
30#include <openssl/params.h>
31
32
33namespace openvpn::OpenSSLCrypto {
34class HMACContext
35{
36 HMACContext(const HMACContext &) = delete;
37 HMACContext &operator=(const HMACContext &) = delete;
38
39 public:
41 {
42 erase();
43 ctx = rhs.ctx;
44 rhs.ctx = nullptr;
45 return *this;
46 }
47
48 OPENVPN_SIMPLE_EXCEPTION(openssl_mac_uninitialized);
49 OPENVPN_EXCEPTION(openssl_mac_error);
50
51 enum
52 {
53 MAX_HMAC_SIZE = EVP_MAX_MD_SIZE
54 };
55
56 HMACContext() = default;
57
58 HMACContext(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size)
59 {
60 init(digest, key, key_size);
61 }
62
64 {
65 erase();
66 }
67
68 void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size)
69 {
70 erase();
71 EVP_MAC *hmac = EVP_MAC_fetch(NULL, "HMAC", NULL);
72 ctx = EVP_MAC_CTX_new(hmac);
73 EVP_MAC_free(hmac);
74
75 /* Save key since the caller might clear it */
76 std::memcpy(this->key, key, key_size);
77
78 /* Lookup/setting of parameters in OpenSSL 3.0 are string based */
79 /* The OSSL_PARAM_construct_utf8_string needs a non const str even
80 * though it does not modify the string */
81 params[0] = OSSL_PARAM_construct_utf8_string("digest", const_cast<char *>(CryptoAlgs::name(digest)), 0);
82 params[1] = OSSL_PARAM_construct_octet_string("key", this->key, key_size);
83 params[2] = OSSL_PARAM_construct_end();
84
85 if (!EVP_MAC_init(ctx, NULL, 0, params))
86 {
88 EVP_MAC_CTX_free(ctx);
89 ctx = nullptr;
90 throw openssl_mac_error("EVP_MAC_init (init)");
91 }
92 }
93
94 void reset()
95 {
97 if (!EVP_MAC_init(ctx, nullptr, 0, params))
98 {
100 throw openssl_mac_error("EVP_HMAC_Init (reset)");
101 }
102 }
103
104
105 void update(const unsigned char *in, const size_t size)
106 {
108
109 if (!EVP_MAC_update(ctx, in, size))
110 {
112 throw openssl_mac_error("EVP_MAC_Update");
113 }
114 }
115
116 /* TODO: This function currently assumes that out has a length of MAX_HMAC_SIZE */
117 size_t final(unsigned char *out)
118 {
120 size_t outlen;
121 if (!EVP_MAC_final(ctx, out, &outlen, MAX_HMAC_SIZE))
122 {
124 throw openssl_mac_error("HMAC_Final");
125 }
126 return outlen;
127 }
128
129 size_t size() const
130 {
132 return size_();
133 }
134
135 bool is_initialized() const
136 {
137 return ctx != nullptr;
138 }
139
140 private:
141 void erase()
142 {
143 EVP_MAC_CTX_free(ctx);
144 ctx = nullptr;
145 }
146
147 size_t size_() const
148 {
149 return EVP_MAC_CTX_get_mac_size(ctx);
150 }
151
152 void check_initialized() const
153 {
154#ifdef OPENVPN_ENABLE_ASSERT
155 if (!ctx)
156 throw openssl_mac_uninitialized();
157#endif
158 }
159
160 OSSL_PARAM params[3];
161 uint8_t key[EVP_MAX_MD_SIZE];
162 EVP_MAC_CTX *ctx = nullptr;
163};
164} // namespace openvpn::OpenSSLCrypto
165
166#endif
void update(const unsigned char *in, const size_t size)
void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size)
HMACContext & operator=(const HMACContext &)=delete
#define OPENVPN_SIMPLE_EXCEPTION(C)
Definition exception.hpp:74
#define OPENVPN_EXCEPTION(C)
Definition exception.hpp:99
const char * name(const KeyDerivation kd)
void openssl_clear_error_stack()
Definition error.hpp:239
static std::stringstream out
Definition test_path.cpp:10