OpenVPN 3 Core Library
Loading...
Searching...
No Matches
ovpnhmac.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// OpenVPN HMAC classes
13
14#ifndef OPENVPN_CRYPTO_OVPNHMAC_H
15#define OPENVPN_CRYPTO_OVPNHMAC_H
16
17#include <string>
18
21#include <openvpn/common/rc.hpp>
25
26namespace openvpn {
27
28// OpenVPN protocol HMAC usage for HMAC/CBC integrity checking and tls-auth
29
30template <typename CRYPTO_API>
32{
33 public:
34 OPENVPN_SIMPLE_EXCEPTION(ovpn_hmac_context_digest_size);
35 OPENVPN_SIMPLE_EXCEPTION(ovpn_hmac_context_bad_sizing);
36
37 public:
39 {
40 }
41
42 OvpnHMAC(const CryptoAlgs::Type digest, const StaticKey &key)
43 {
44 init(digest, key);
45 }
46
47 bool defined() const
48 {
49 return ctx.is_initialized();
50 }
51
52 // size of out buffer to pass to hmac
53 size_t output_size() const
54 {
55 return ctx.size();
56 }
57
58 void init(const CryptoAlgs::Type digest, const StaticKey &key)
59 {
60 const CryptoAlgs::Alg &alg = CryptoAlgs::get(digest);
61
62 // check that key is large enough
63 if (key.size() < alg.size())
64 throw ovpn_hmac_context_digest_size();
65
66 // initialize HMAC context with digest type and key
67 ctx.init(digest, key.data(), alg.size());
68 }
69
70 void hmac(unsigned char *out,
71 const size_t out_size,
72 const unsigned char *in,
73 const size_t in_size)
74 {
75 ctx.reset();
76 ctx.update(in, in_size);
77 ctx.final(out);
78 }
79
80 // Special HMAC for OpenVPN control packets
81
82 void ovpn_hmac_gen(unsigned char *data,
83 const size_t data_size,
84 const size_t l1,
85 const size_t l2,
86 const size_t l3)
87 {
88 if (ovpn_hmac_pre(data, data_size, l1, l2, l3))
89 ctx.final(data + l1);
90 else
91 throw ovpn_hmac_context_bad_sizing();
92 }
93
94 // verify the HMAC generated by ovpn_hmac_gen, return true if verified
95 bool ovpn_hmac_cmp(const unsigned char *data,
96 const size_t data_size,
97 const size_t l1,
98 const size_t l2,
99 const size_t l3)
100 {
101 unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE];
102 if (ovpn_hmac_pre(data, data_size, l1, l2, l3))
103 {
104 ctx.final(local_hmac);
105 return !crypto::memneq(data + l1, local_hmac, l2);
106 }
107 else
108 return false;
109 }
110
111 private:
112 // Convoluting OpenVPN control channel packets for HMAC:
113 // <-- L1 --> <-L2> <L3>
114 // [OP] [PSID] [HMAC] [PID] [...] -> canonical order
115 //
116 // [HMAC] [PID] [OP] [PSID] [...] -> HMAC order
117
118 bool ovpn_hmac_pre(const unsigned char *data,
119 const size_t data_size,
120 const size_t l1,
121 const size_t l2,
122 const size_t l3)
123 {
124 const size_t lsum = l1 + l2 + l3;
125 if (lsum > data_size || l2 != ctx.size())
126 return false;
127 ctx.reset();
128 ctx.update(data + l1 + l2, l3);
129 ctx.update(data, l1);
130 ctx.update(data + lsum, data_size - lsum);
131 return true;
132 }
133
134 typename CRYPTO_API::HMACContext ctx;
135};
136
137// OvpnHMAC wrapper API using dynamic polymorphism
138
139class OvpnHMACInstance : public RC<thread_unsafe_refcount>
140{
141 public:
143
144 virtual void init(const StaticKey &key) = 0;
145
146 virtual size_t output_size() const = 0;
147
148 virtual void ovpn_hmac_gen(unsigned char *data,
149 const size_t data_size,
150 const size_t l1,
151 const size_t l2,
152 const size_t l3) = 0;
153
154 virtual bool ovpn_hmac_cmp(const unsigned char *data,
155 const size_t data_size,
156 const size_t l1,
157 const size_t l2,
158 const size_t l3) = 0;
159};
160
161class OvpnHMACContext : public RC<thread_unsafe_refcount>
162{
163 public:
165
166 virtual size_t size() const = 0;
167
169};
170
171class OvpnHMACFactory : public RC<thread_unsafe_refcount>
172{
173 public:
175
176 virtual OvpnHMACContext::Ptr new_obj(const CryptoAlgs::Type digest_type) = 0;
177};
178
179// OvpnHMAC wrapper implementation using dynamic polymorphism
180
181template <typename CRYPTO_API>
183{
184 public:
186 : digest(digest_arg)
187 {
188 }
189
190 void init(const StaticKey &key) override
191 {
192 ovpn_hmac.init(digest, key);
193 }
194
195 size_t output_size() const override
196 {
197 return ovpn_hmac.output_size();
198 }
199
200 void ovpn_hmac_gen(unsigned char *data,
201 const size_t data_size,
202 const size_t l1,
203 const size_t l2,
204 const size_t l3) override
205 {
206 ovpn_hmac.ovpn_hmac_gen(data, data_size, l1, l2, l3);
207 }
208
209 bool ovpn_hmac_cmp(const unsigned char *data,
210 const size_t data_size,
211 const size_t l1,
212 const size_t l2,
213 const size_t l3) override
214 {
215 return ovpn_hmac.ovpn_hmac_cmp(data, data_size, l1, l2, l3);
216 }
217
218 private:
221};
222
223template <typename CRYPTO_API>
225{
226 public:
228 : digest(digest_type)
229 {
230 }
231
232 size_t size() const override
233 {
234 return CryptoAlgs::size(digest);
235 }
236
241
242 private:
244};
245
246template <typename CRYPTO_API>
248{
249 public:
251 {
252 return new CryptoOvpnHMACContext<CRYPTO_API>(digest_type);
253 }
254};
255
256} // namespace openvpn
257
258#endif
OvpnHMACInstance::Ptr new_obj() override
Definition ovpnhmac.hpp:237
CryptoOvpnHMACContext(const CryptoAlgs::Type digest_type)
Definition ovpnhmac.hpp:227
size_t size() const override
Definition ovpnhmac.hpp:232
OvpnHMACContext::Ptr new_obj(const CryptoAlgs::Type digest_type) override
Definition ovpnhmac.hpp:250
bool ovpn_hmac_cmp(const unsigned char *data, const size_t data_size, const size_t l1, const size_t l2, const size_t l3) override
Definition ovpnhmac.hpp:209
void ovpn_hmac_gen(unsigned char *data, const size_t data_size, const size_t l1, const size_t l2, const size_t l3) override
Definition ovpnhmac.hpp:200
CryptoOvpnHMACInstance(const CryptoAlgs::Type digest_arg)
Definition ovpnhmac.hpp:185
OvpnHMAC< CRYPTO_API > ovpn_hmac
Definition ovpnhmac.hpp:220
void init(const StaticKey &key) override
Definition ovpnhmac.hpp:190
size_t output_size() const override
Definition ovpnhmac.hpp:195
virtual OvpnHMACInstance::Ptr new_obj()=0
virtual size_t size() const =0
RCPtr< OvpnHMACContext > Ptr
Definition ovpnhmac.hpp:164
virtual OvpnHMACContext::Ptr new_obj(const CryptoAlgs::Type digest_type)=0
RCPtr< OvpnHMACFactory > Ptr
Definition ovpnhmac.hpp:174
virtual void ovpn_hmac_gen(unsigned char *data, const size_t data_size, const size_t l1, const size_t l2, const size_t l3)=0
virtual void init(const StaticKey &key)=0
virtual bool ovpn_hmac_cmp(const unsigned char *data, const size_t data_size, const size_t l1, const size_t l2, const size_t l3)=0
RCPtr< OvpnHMACInstance > Ptr
Definition ovpnhmac.hpp:142
virtual size_t output_size() const =0
bool defined() const
Definition ovpnhmac.hpp:47
bool ovpn_hmac_pre(const unsigned char *data, const size_t data_size, const size_t l1, const size_t l2, const size_t l3)
Definition ovpnhmac.hpp:118
void ovpn_hmac_gen(unsigned char *data, const size_t data_size, const size_t l1, const size_t l2, const size_t l3)
Definition ovpnhmac.hpp:82
size_t output_size() const
Definition ovpnhmac.hpp:53
OPENVPN_SIMPLE_EXCEPTION(ovpn_hmac_context_digest_size)
bool ovpn_hmac_cmp(const unsigned char *data, const size_t data_size, const size_t l1, const size_t l2, const size_t l3)
Definition ovpnhmac.hpp:95
CRYPTO_API::HMACContext ctx
Definition ovpnhmac.hpp:134
void init(const CryptoAlgs::Type digest, const StaticKey &key)
Definition ovpnhmac.hpp:58
OvpnHMAC(const CryptoAlgs::Type digest, const StaticKey &key)
Definition ovpnhmac.hpp:42
void hmac(unsigned char *out, const size_t out_size, const unsigned char *in, const size_t in_size)
Definition ovpnhmac.hpp:70
OPENVPN_SIMPLE_EXCEPTION(ovpn_hmac_context_bad_sizing)
The smart pointer class.
Definition rc.hpp:119
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
const unsigned char * data() const
size_t size() const
const Alg & get(const Type type)
size_t size(const Type type)
bool memneq(const void *a, const void *b, size_t size)
Definition memneq.hpp:79
static std::stringstream out
Definition test_path.cpp:10