OpenVPN 3 Core Library
Loading...
Searching...
No Matches
psid_cookie_impl.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) 2022- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// A 64-bit protocol session ID, used by ProtoContext. But, unlike being random
13// in psid.hpp, the PsidCookieImpl class derives it via an HMAC of information
14// on the incoming client's OpenVPN HARD_RESET control message. This creates a
15// session id that acts like a syn-cookie on the OpenVPN startup 3-way
16// handshake.
17
18#pragma once
19
21
23#include <openvpn/common/rc.hpp>
26
27#include <openvpn/ssl/psid.hpp>
30
31#include <optional>
32
33namespace openvpn {
34
46{
47 public:
48 static constexpr int SID_SIZE = ProtoSessionID::SIZE;
49 static constexpr int OPCODE_SIZE = 1;
50
51 // must be called _before_ the server implementation starts threads; it guarantees
52 // that all per thread instances get the same psid cookie hmac key
53 static void pre_threading_setup()
54 {
55 get_key();
56 }
57
59 : pcfg_(*psfp->proto_context_config),
60 now_(pcfg_.now), handwindow_(pcfg_.handshake_window)
61 {
63 {
66
67 // init tls_auth hmac (see ProtoContext.reset() case TLS_AUTH; also TLSAuthPreValidate ctor)
68 if (pcfg_.key_direction >= 0)
69 {
70 // key-direction is 0 or 1
73 | OpenVPNStaticKey::ENCRYPT | key_dir));
75 | OpenVPNStaticKey::DECRYPT | key_dir));
76 }
77 else
78 {
79 // key-direction bidirectional mode
82 }
83 }
84
85 // initialize psid HMAC context with digest type and key
86 const StaticKey &key = get_key();
87 hmac_ctx_.init(digest_, key.data(), key.size());
88 }
89
90 Intercept intercept(Buffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) override
91 {
94
95 if (pkt_buf.empty())
96 return Intercept::EARLY_DROP; // packet validation fails, no opcode
97
98 CookieHelper chelp(pkt_buf[0]);
99
100 const bool is_tls_crypt_v2 = (chelp.is_tls_crypt_v2() && pcfg_.tls_crypt_v2_enabled());
101
102 if (chelp.is_clients_initial_reset())
103 {
104 return is_tls_crypt_v2
105 ? process_clients_initial_reset_tls_crypt(pkt_buf, pcaib, chelp)
107 }
108 if (is_tls_crypt_v2 && chelp.is_clients_handshake_ack_tls_crypt_v2())
109 {
110 return process_clients_server_reset_ack_tls_crypt(pkt_buf, pcaib);
111 }
113 {
114 return process_clients_server_reset_ack_tls_auth(pkt_buf, pcaib, chelp.is_ack_v1());
115 }
116
117 // JMD_TODO: log failure? Logging DDoS?
118 return Intercept::EARLY_DROP; // bad op field
119 }
120
122 {
125 return ret_val;
126 }
127
129 {
130 pctb_ = std::move(pctb);
131 }
132
133#ifndef UNIT_TEST
134 private:
135#endif
137
138 // Returns true iff the reliable::id_t read from `buf` is within the early-handshake
139 // range (0 or 1); false for mid-session values (> 1).
140 template <typename Buf>
141 static bool read_id_is_early_handshake(Buf &buf)
142 {
143 reliable::id_t net_id;
144 buf.read(&net_id, sizeof(net_id));
145 return ntohl(net_id) <= 1;
146 }
147
148 // Validates the payload of the third 3WHS packet (client ACK of server HARD_RESET).
149 // The "0 or 1" tolerance on pktids matches OpenVPN 2's check_session_hmac_and_pkt_id():
150 // anything higher is clearly mid-session traffic, not a 3WHS completion.
151 // When has_own_pktid is false (P_ACK_V1 wire format), the own message-id field is
152 // absent on the wire and the check is skipped.
153 // Sets cookie_psid_ and returns true on success.
154 template <typename Buf>
156 const ProtoSessionID &cli_psid,
157 const PsidCookieAddrInfoBase &pcaib,
158 bool has_own_pktid = true)
159 {
160 // We _should_ have one ACK (for the HARD_RESET previous message).
161 if (buf[0] != 1)
162 return false;
163
164 buf.advance(1);
165
167 return false;
168
169 cookie_psid_.read(buf);
170
171 if (has_own_pktid && !read_id_is_early_handshake(buf))
172 return false;
173
174 return check_session_id_hmac(cookie_psid_, cli_psid, pcaib);
175 }
176
178 {
179 static const size_t hmac_size = ta_hmac_recv_->output_size();
180
181 // ovpn_hmac_cmp checks for adequate pkt_buf.size()
182 bool pkt_hmac_valid = ta_hmac_recv_->ovpn_hmac_cmp(pkt_buf.c_data(),
183 pkt_buf.size(),
185 hmac_size,
187 if (!pkt_hmac_valid)
188 {
189 // JMD_TODO: log failure? Logging DDoS?
190 return Intercept::DROP_1ST;
191 }
192
193 // check for adequate packet size to complete this function
194 static const size_t reqd_packet_size
195 // clang-format off
196 // [op_field] [cli_psid] [HMAC] [cli_auth_pktid] [cli_pktid]
198 // clang-format on
199 if (pkt_buf.size() < reqd_packet_size)
200 {
201 // JMD_TODO: log failure? Logging DDoS?
202 return Intercept::DROP_1ST;
203 }
204
205 // "buf_copy" here uses the same underlying data, but has it's own offset; skip
206 // past client's op_field.
207 ConstBuffer recv_buf_copy(pkt_buf.c_data() + 1, pkt_buf.size() - 1, true);
208 // decapsulate_tls_auth
209 const ProtoSessionID cli_psid(recv_buf_copy);
210 recv_buf_copy.advance(hmac_size);
211
212 PacketIDControl cli_auth_pktid; // a.k.a, replay_packet_id in draft RFC
213 cli_auth_pktid.read(recv_buf_copy);
214
215 uint8_t cli_net_id[4]; // a.k.a., packet_id in draft RFC
216
217 recv_buf_copy.read(cli_net_id, sizeof(cli_net_id));
218
219 // start building the server reply HARD_RESET packet
220 BufferAllocated send_buf;
221 static const Frame &frame = *pcfg_.frame;
222 frame.prepare(Frame::WRITE_SSL_INIT, send_buf);
223
224 // set server packet id (a.k.a., msg seq no) which would come from the
225 // reliability layer, if we had one
226 const reliable::id_t net_id = 0; // no htonl(0) since result is 0
227 send_buf.prepend(static_cast<const void *>(&net_id), sizeof(net_id));
228
229 // prepend_dest_psid_and_acks
230 cli_psid.prepend(send_buf);
231 send_buf.prepend(cli_net_id, sizeof(cli_net_id));
232 send_buf.push_front((unsigned char)1);
233
234 // gen head
235 PacketIDControlSend svr_auth_pid{};
236 svr_auth_pid.write_next(send_buf, true, now_->seconds_since_epoch());
237 // make space for tls-auth HMAC
239 // write source PSID
240 const ProtoSessionID srv_psid = calculate_session_id_hmac(cli_psid, pcaib, 0);
241 srv_psid.prepend(send_buf);
242 // write opcode
243 const unsigned char op_field = CookieHelper::get_server_hard_reset_opfield();
244 send_buf.push_front(op_field);
245 // write hmac
246 ta_hmac_send_->ovpn_hmac_gen(send_buf.data(),
247 send_buf.size(),
251
252 // consumer's implementation to send the SERVER_HARD_RESET to the client
253 bool send_ok = pctb_->psid_cookie_send_const(send_buf, pcaib);
254 if (send_ok)
255 {
257 }
258
259 return Intercept::DROP_1ST;
260 }
261
263 const PsidCookieAddrInfoBase &pcaib,
264 bool is_ack_v1)
265 {
266 static const size_t hmac_size = ta_hmac_recv_->output_size();
267 // ovpn_hmac_cmp checks for adequate pkt_buf.size()
268 bool pkt_hmac_valid = ta_hmac_recv_->ovpn_hmac_cmp(pkt_buf.c_data(),
269 pkt_buf.size(),
271 hmac_size,
273 if (!pkt_hmac_valid)
274 {
275 // JMD_TODO: log failure? Logging DDoS?
276 return Intercept::DROP_2ND;
277 }
278
279 // [op_field][cli_psid][HMAC][cli_auth_pktid][acked][srv_psid] and,
280 // for CONTROL_V1 only, a trailing [own_pktid]. P_ACK_V1 has no own
281 // message-id on the wire, so its required size is shorter.
282 const size_t reqd_packet_size = OPCODE_SIZE + SID_SIZE + hmac_size + PacketIDControl::size() + 5 + SID_SIZE
283 + (is_ack_v1 ? 0 : reliable::id_size);
284 if (pkt_buf.size() < reqd_packet_size)
285 {
286 // JMD_TODO: log failure? Logging DDoS?
287 return Intercept::DROP_2ND;
288 }
289
290 // "buf_copy" here uses the same underlying data, but has it's own offset; skip
291 // past client's op_field.
292 ConstBuffer recv_buf_copy(pkt_buf.c_data() + 1, pkt_buf.size() - 1, true);
293 // decapsulate_tls_auth
294 const ProtoSessionID cli_psid(recv_buf_copy);
295 recv_buf_copy.advance(hmac_size);
296
297 PacketIDControl cli_auth_pktid; // a.k.a, replay_packet_id in draft RFC
298 cli_auth_pktid.read(recv_buf_copy);
299
300 return validate_3whs_ack_payload(recv_buf_copy, cli_psid, pcaib, !is_ack_v1)
303 }
304
306 const PsidCookieAddrInfoBase &pcaib,
307 const CookieHelper &ch)
308 {
309 static const size_t hmac_size = pcfg_.tls_crypt_context->digest_size();
310
311 ConstBuffer recv_buf_copy(pkt_buf.c_data() + 1, pkt_buf.size() - 1, true);
312
313 ProtoSessionID client_session_id(recv_buf_copy);
314 PacketIDControl replay_packet_id;
315 replay_packet_id.read(recv_buf_copy);
316
317 // This could be user-configurable so that we could just drop packets here if
318 // we don't want to allow clients that don't support re-sending the WKc.
319 if (!ch.supports_early_negotiation(replay_packet_id))
321
322 auto pipes = init_tls_crypt_v2(pkt_buf);
323
324 if (!pipes)
325 return Intercept::DROP_1ST;
326
327 auto [send, recv] = *pipes;
328
329 // Create synthetic RESET packet payload.
330 BufferAllocated payload;
332
334
335 PacketIDControl packet_id{.id = 0, .time = 0};
336 packet_id.write(payload, true);
337
338 client_session_id.prepend(payload);
339
340 const reliable::id_t acked_packet_id = 0;
341 payload.prepend(&acked_packet_id, sizeof(acked_packet_id));
342 payload.push_front((unsigned char)1);
343
345 // in 'work' we store all the fields that are not supposed to be encrypted
347 // make space for HMAC
348 work.prepend_alloc(hmac_size);
349 // write tls-crypt packet ID
350 PacketIDControlSend svr_auth_pid;
351 svr_auth_pid.write_next(work, true, now_->seconds_since_epoch());
352 // write source PSID
353 const ProtoSessionID srv_psid = calculate_session_id_hmac(client_session_id, pcaib, 0);
354 srv_psid.prepend(work);
355 // write opcode
357
358 // compute HMAC using header fields (from 'work') and plaintext
359 // payload
360 send->hmac_gen(work.data(), TLSCryptContext::hmac_offset, payload.c_data(), payload.size());
361
362 const size_t data_offset = TLSCryptContext::hmac_offset + hmac_size;
363
364 // encrypt the content of 'payload' (packet payload) into 'work'
365 const size_t encrypt_bytes = send->encrypt(work.c_data() + TLSCryptContext::hmac_offset,
366 work.data() + data_offset,
367 work.max_size() - data_offset,
368 payload.c_data(),
369 payload.size());
370 work.inc_size(encrypt_bytes);
371
372 // consumer's implementation to send the SERVER_HARD_RESET to the client
373 bool send_ok = pctb_->psid_cookie_send_const(work, pcaib);
374 if (send_ok)
376
377 return Intercept::DROP_1ST;
378 }
379
381 {
382 auto pipes = init_tls_crypt_v2(pkt_buf);
383
384 if (!pipes)
385 return Intercept::DROP_2ND;
386
387 auto [send, recv] = *pipes;
388
389 static const size_t hmac_size = pcfg_.tls_crypt_context->digest_size();
390
391 const size_t head_size = OPCODE_SIZE + ProtoSessionID::SIZE + PacketIDControl::size();
392 const unsigned char *orig_data = pkt_buf.c_data();
393
394 ConstBuffer recv_buf_copy(pkt_buf.c_data() + 1, pkt_buf.size() - 1, true);
395
396 ProtoSessionID client_session_id(recv_buf_copy);
397 recv_buf_copy.advance(PacketIDControl::size() + hmac_size);
398
401
402 // Decrypt into `work`.
403 const size_t decrypt_bytes = recv->decrypt(orig_data + head_size,
404 work.data(),
405 work.max_size(),
406 recv_buf_copy.c_data(),
407 recv_buf_copy.size());
408 if (!decrypt_bytes)
409 return Intercept::DROP_2ND;
410
411 work.inc_size(decrypt_bytes);
412
413 // Verify HMAC.
414 if (!recv->hmac_cmp(orig_data, TLSCryptContext::hmac_offset, work.c_data(), work.size()))
415 return Intercept::DROP_2ND;
416
417 // Decrypted plaintext layout: ack_count(1) | acked_pktid(4) | peer_session_id(8) | packet_id(4) | payload
418 static const size_t reqd_decrypted_size = 1 + reliable::id_size + ProtoSessionID::SIZE + reliable::id_size;
419 if (work.size() < reqd_decrypted_size)
420 return Intercept::DROP_2ND;
421
422 return validate_3whs_ack_payload(work, client_session_id, pcaib)
425 }
426
427 // key must be common to all threads
429 {
430 StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI());
432
433 // guarantee that the key is large enough
434 StaticKey key;
435 key.init_from_rng(*rng, alg.size());
436 return key;
437 }
438
439 static const StaticKey &get_key()
440 {
441 static const StaticKey key = create_key();
442 return key;
443 }
444
454 const PsidCookieAddrInfoBase &pcaib,
455 unsigned int offset)
456 {
458
459 // Get the time window for which the ProtoSessionID hmac is valid. The window
460 // size is an interval given by handwindow/2, one half of the configured
461 // handshake timeout, typically 30 seconds. The valid_time is the count of
462 // intervals since the beginning of the epoch. With offset zero, the valid_time
463 // is the server's current interval; with offsets 1 to n, it is the server's nth
464 // previous interval.
465 //
466 // There is the theoretical issue of valid_time wrapping after 2^32 intervals.
467 // With 30 second intervals, around the year 4010. Will not spoil my weekend.
468 uint64_t interval = (handwindow_.raw() + 1) / 2;
469 uint32_t valid_time = static_cast<uint32_t>(now_->raw() / interval - offset);
470 // no endian concerns; hmac is created and checked by the same host
471 hmac_ctx_.update(reinterpret_cast<const unsigned char *>(&valid_time),
472 sizeof(valid_time));
473
474 // the memory slab at cli_addr_port of size cli_addrport_size is a reproducibly
475 // hashable representation of the client's address and port
476 size_t cli_addrport_size;
477 const unsigned char *cli_addr_port = pcaib.get_abstract_cli_addrport(cli_addrport_size);
478 hmac_ctx_.update(cli_addr_port, cli_addrport_size);
479
480 // add session id of client
481 const Buffer cli_psid_buf = cli_psid.get_buf();
482 hmac_ctx_.update(cli_psid_buf.c_data(), SID_SIZE);
483
484 // finalize the hmac and package it as the server's ProtoSessionID
485 BufferAllocated hmac_result(SSLLib::CryptoAPI::HMACContext::MAX_HMAC_SIZE);
486 ProtoSessionID srv_psid;
487 hmac_ctx_.final(hmac_result.write_alloc(hmac_ctx_.size()));
488 srv_psid.read(hmac_result);
489
490 return srv_psid;
491 }
492
494 const ProtoSessionID &cli_psid,
495 const PsidCookieAddrInfoBase &pcaib)
496 {
497 // check the current timestamp and the previous one in case the server's clock
498 // has moved to the one following that given to the client
499 for (unsigned int offset = 0; offset <= 1; ++offset)
500 {
501 ProtoSessionID calc_psid = calculate_session_id_hmac(cli_psid, pcaib, offset);
502
503 if (srv_psid.match(calc_psid))
504 {
505 return true;
506 }
507 }
508 return false;
509 }
510
517 std::optional<std::pair<TLSCryptInstance::Ptr, TLSCryptInstance::Ptr>> init_tls_crypt_v2(Buffer &pkt_buf)
518 {
521
523
524 if (ProtoContext::KeyContext::unwrap_tls_crypt_wkc(pkt_buf, pcfg_, *tls_crypt_server) != Error::SUCCESS)
525 return std::nullopt;
526
527 const unsigned int key_dir = pcfg_.ssl_factory->mode().is_server()
530
533
534 send->init(pcfg_.ssl_factory->libctx(),
537
538 recv->init(pcfg_.ssl_factory->libctx(),
541
542 return std::pair{send, recv};
543 }
544
546
549 const Time::Duration &handwindow_;
550
553
554 // the psid cookie specific hmac object
555 SSLLib::CryptoAPI::HMACContext hmac_ctx_;
556
559};
560
561} // namespace openvpn
const T * c_data() const
Returns a const pointer to the start of the buffer.
Definition buffer.hpp:1193
T * prepend_alloc(const size_t size)
Allocate space for prepending data to the buffer.
Definition buffer.hpp:1594
T * write_alloc(const size_t size)
Allocate space for writing data to the buffer.
Definition buffer.hpp:1584
void prepend(const T *data, const size_t size)
Prepend data to the buffer.
Definition buffer.hpp:1572
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1241
T * data()
Get a mutable pointer to the start of the array.
Definition buffer.hpp:1447
void advance(const size_t delta)
Advances the buffer by the specified delta.
Definition buffer.hpp:1276
bool empty() const
Returns true if the buffer is empty.
Definition buffer.hpp:1235
void push_front(const T &value)
Append a T object to the array, with possible resize.
Definition buffer.hpp:1487
void read(NCT *data, const size_t size)
Read data from the buffer into the specified memory location.
Definition buffer.hpp:1330
size_t prepare(const unsigned int context, Buffer &buf) const
Definition frame.hpp:263
bool is_server() const
Definition mode.hpp:36
StaticKey slice(unsigned int key_specifier) const
virtual OvpnHMACInstance::Ptr new_obj()=0
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
virtual size_t output_size() const =0
void write_next(Buffer &buf, const bool prepend, const PacketIDControl::time_t now)
static Error::Type unwrap_tls_crypt_wkc(Buffer &recv, ProtoConfig &proto_config, TLSCryptInstance &tls_crypt_server, TLSCryptMetadata::Ptr tls_crypt_metadata=nullptr)
Extract and process the TLS crypt WKc information.
Definition proto.hpp:2371
SSLFactoryAPI::Ptr ssl_factory
Definition proto.hpp:342
TLSCryptContext::Ptr tls_crypt_context
Definition proto.hpp:424
OpenVPNStaticKey tls_auth_key
leave this undefined to disable tls_auth
Definition proto.hpp:399
OpenVPNStaticKey wrapped_tls_crypt_key
For TLS crypt V2, this (if defined()) is the wrapped WKc client key.
Definition proto.hpp:405
OvpnHMACContext::Ptr tls_auth_context
Definition proto.hpp:420
bool is_clients_handshake_ack_tls_auth() const
Returns true if this could be the third packet of the 3-way handshake (tls-auth/none).
Definition proto.hpp:3645
static unsigned char get_server_hard_reset_opfield()
Definition proto.hpp:3675
bool is_clients_handshake_ack_tls_crypt_v2() const
Returns true if this could be the third packet of the 3-way handshake (tls-crypt-v2).
Definition proto.hpp:3651
bool supports_early_negotiation(const PacketIDControl &pidc) const noexcept
Returns true if the peer supports early negotiation (i.e. is able to reply with CONTROL_WKC_V1).
Definition proto.hpp:3639
bool is_ack_v1() const
Returns true if the packet is a P_ACK_V1 (no own message-id field on the wire).
Definition proto.hpp:3657
static void prepend_TLV(Buffer &payload)
Adds an {EARLY_NEG_FLAGS, 2, EARLY_NEG_FLAG_RESEND_WKC} TLV to a payload buffer (use with TLS crypt V...
Definition proto.hpp:3663
bool is_tls_crypt_v2() const noexcept
Returns true if this is a TLS crypt V2 protocol packet.
Definition proto.hpp:3633
bool match(const ProtoSessionID &other) const
Definition psid.hpp:90
const Buffer get_buf() const
Definition psid.hpp:76
void read(BufType &buf)
Definition psid.hpp:59
void prepend(Buffer &buf) const
Definition psid.hpp:70
Interface to communicate the server's address semantics.
virtual const unsigned char * get_abstract_cli_addrport(size_t &slab_size) const =0
Implements the PsidCookie interface.
static StaticKey create_key()
SSLLib::CryptoAPI::HMACContext hmac_ctx_
OvpnHMACInstance::Ptr ta_hmac_recv_
ProtoSessionID get_cookie_psid() override
Get the cookie psid from client's 2nd packet.
static const StaticKey & get_key()
const Time::Duration & handwindow_
static bool read_id_is_early_handshake(Buf &buf)
bool check_session_id_hmac(const ProtoSessionID &srv_psid, const ProtoSessionID &cli_psid, const PsidCookieAddrInfoBase &pcaib)
PsidCookieTransportBase::Ptr pctb_
Intercept process_clients_initial_reset_tls_crypt(Buffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib, const CookieHelper &ch)
Intercept process_clients_server_reset_ack_tls_auth(ConstBuffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib, bool is_ack_v1)
static constexpr int SID_SIZE
ProtoContext::ProtoConfig & pcfg_
Intercept intercept(Buffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) override
Called when a potential new client session packet is received.
ProtoSessionID calculate_session_id_hmac(const ProtoSessionID &cli_psid, const PsidCookieAddrInfoBase &pcaib, unsigned int offset)
Calculate the psid cookie, the ProtoSessionID hmac.
Intercept process_clients_initial_reset_tls_auth(ConstBuffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib)
static constexpr CryptoAlgs::Type digest_
std::optional< std::pair< TLSCryptInstance::Ptr, TLSCryptInstance::Ptr > > init_tls_crypt_v2(Buffer &pkt_buf)
Set up a couple of TLSCryptInstance (send, recv) from a TLS crypt V2 packet's WKc.
bool validate_3whs_ack_payload(Buf &buf, const ProtoSessionID &cli_psid, const PsidCookieAddrInfoBase &pcaib, bool has_own_pktid=true)
Intercept process_clients_server_reset_ack_tls_crypt(Buffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib)
static constexpr int OPCODE_SIZE
void provide_psid_cookie_transport(PsidCookieTransportBase::Ptr pctb) override
Give this component the transport needed to send the server's HARD_RESET.
PsidCookieImpl(ServerProto::Factory *psfp)
OvpnHMACInstance::Ptr ta_hmac_send_
virtual bool psid_cookie_send_const(Buffer &send_buf, const PsidCookieAddrInfoBase &pcaib)=0
Interface to integrate this component into the server implementation.
Intercept
Values returned by the intercept() function.
virtual SSLLib::Ctx libctx()=0
virtual const Mode & mode() const =0
void init_from_rng(StrongRandomAPI &rng, const size_t key_size)
const unsigned char * data() const
size_t size() const
virtual TLSCryptInstance::Ptr new_obj_send()=0
virtual TLSCryptInstance::Ptr new_obj_recv()=0
constexpr static const size_t hmac_offset
virtual size_t digest_size() const =0
virtual void init(SSLLib::Ctx libctx, const StaticKey &key_hmac, const StaticKey &key_crypt)=0
T raw() const
Definition time.hpp:404
base_type seconds_since_epoch() const
Definition time.hpp:289
void work(openvpn_io::io_context &io_context, ThreadCommon &tc, MyRunContext &runctx, const unsigned int unit)
const Alg & get(const Type type)
static constexpr std::size_t id_size
Definition relcommon.hpp:23
std::uint32_t id_t
Definition relcommon.hpp:22
static constexpr size_t size()
static constexpr size_t idsize