OpenVPN 3 Core Library
Loading...
Searching...
No Matches
sess_ticket.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#pragma once
13
14#include <cstring>
15#include <memory>
16
23
24namespace openvpn {
25
26class OpenSSLContext;
27class MbedTLSContext;
28
29// Abstract base class used to provide an interface for TLS
30// Session Ticket keying originally described by RFC 5077.
32{
33 public:
34 using UPtr = std::unique_ptr<TLSSessionTicketBase>;
35
36 OPENVPN_EXCEPTION(sess_ticket_error);
37
44
45 class Name
46 {
47 public:
48 static constexpr size_t SIZE = 16;
49
50 explicit Name(StrongRandomAPI &rng)
51 {
53 }
54
55 explicit Name(const std::string &name_b64)
56 {
57 b64_to_key(name_b64, "key name", value_, SIZE);
58 }
59
60 explicit Name(const unsigned char name[SIZE])
61 {
62 std::memcpy(value_, name, SIZE);
63 }
64
65 bool operator==(const Name &rhs) const
66 {
67 return std::memcmp(value_, rhs.value_, SIZE) == 0;
68 }
69
70 bool operator!=(const Name &rhs) const
71 {
72 return std::memcmp(value_, rhs.value_, SIZE) != 0;
73 }
74
75 bool operator<(const Name &rhs) const
76 {
77 return std::memcmp(value_, rhs.value_, SIZE) < 0;
78 }
79
80 std::string to_string() const
81 {
82 return "TLSTicketName[" + b64() + ']';
83 }
84
85 std::string b64() const
86 {
87 return base64->encode(value_, SIZE);
88 }
89
90 template <typename HASH>
91 void hash(HASH &h) const
92 {
93 h(value_, SIZE);
94 }
95
96#ifdef USE_OPENVPN_HASH
97 std::uint64_t hashval() const
98 {
99 Hash64 h;
100 hash(h);
101 return h.value();
102 }
103#endif
104
105 private:
106 // we need to friend SSL implementation classes
107 friend class OpenSSLContext;
108 friend class MbedTLSContext;
109
110 // note that default constructor leaves object in an undefined state
111 Name() = default;
112
113 unsigned char value_[SIZE];
114 };
115
116 class Key
117 {
118 public:
119 static constexpr size_t CIPHER_KEY_SIZE = 32;
120 static constexpr size_t HMAC_KEY_SIZE = 16;
121
127
128 explicit Key(const std::string &cipher_key_b64, const std::string &hmac_key_b64)
129 {
130 b64_to_key(cipher_key_b64, "cipher key", cipher_value_, CIPHER_KEY_SIZE);
131 b64_to_key(hmac_key_b64, "hmac key", hmac_value_, HMAC_KEY_SIZE);
132 }
133
135 {
136 // wipe keys
137 std::memset(cipher_value_, 0, CIPHER_KEY_SIZE);
138 std::memset(hmac_value_, 0, HMAC_KEY_SIZE);
139 }
140
141 std::string to_string() const
142 {
143 return "TLSTicketKey[cipher=" + cipher_b64() + " hmac=" + hmac_b64() + ']';
144 }
145
146 std::string cipher_b64() const
147 {
149 }
150
151 std::string hmac_b64() const
152 {
154 }
155
156 bool operator==(const Key &rhs) const
157 {
158 return std::memcmp(cipher_value_, rhs.cipher_value_, CIPHER_KEY_SIZE) == 0 && std::memcmp(hmac_value_, rhs.hmac_value_, HMAC_KEY_SIZE) == 0;
159 }
160
161 bool operator!=(const Key &rhs) const
162 {
163 return !operator==(rhs);
164 }
165
166 template <typename KEY_TRANSFORM>
167 void key_transform(KEY_TRANSFORM &t)
168 {
169 unsigned char out[KEY_TRANSFORM::MAX_HMAC_SIZE];
170
171 // cipher
172 {
173 t.cipher_transform.reset();
174 t.cipher_transform.update(cipher_value_, CIPHER_KEY_SIZE);
175 const size_t size = t.cipher_transform.final(out);
176 if (size < CIPHER_KEY_SIZE)
177 throw sess_ticket_error("insufficient key material for cipher transform");
178 std::memcpy(cipher_value_, out, CIPHER_KEY_SIZE);
179 }
180
181 // hmac
182 {
183 t.hmac_transform.reset();
184 t.hmac_transform.update(hmac_value_, HMAC_KEY_SIZE);
185 const size_t size = t.hmac_transform.final(out);
186 if (size < HMAC_KEY_SIZE)
187 throw sess_ticket_error("insufficient key material for hmac transform");
188 std::memcpy(hmac_value_, out, HMAC_KEY_SIZE);
189 }
190 }
191
192 private:
193 // we need to friend SSL implementation classes
194 friend class OpenSSLContext;
195 friend class MbedTLSContext;
196
197 // note that default constructor leaves object in an undefined state
198 Key() = default;
199
202 };
203
204 // method returns name and key
205 virtual Status create_session_ticket_key(Name &name, Key &key) const = 0;
206
207 // method is given name and returns key
208 virtual Status lookup_session_ticket_key(const Name &name, Key &key) const = 0;
209
210 // return string that identifies the app
211 virtual std::string session_id_context() const = 0;
212
213 virtual ~TLSSessionTicketBase() = default;
214
215 private:
216 static void b64_to_key(const std::string &b64, const char *title, unsigned char *out, const size_t outlen)
217 {
218 Buffer srcbuf(out, outlen, false);
219 try
220 {
221 base64->decode(srcbuf, b64);
222 }
223 catch (const std::exception &e)
224 {
225 throw sess_ticket_error(std::string("base64 decode for ") + title + ": " + std::string(e.what()));
226 }
227 if (srcbuf.size() != outlen)
228 throw sess_ticket_error(std::string("wrong input size for ") + title + ", actual=" + std::to_string(srcbuf.size()) + " expected=" + std::to_string(outlen));
229 }
230};
231} // namespace openvpn
232
233#ifdef USE_OPENVPN_HASH
235#endif
std::string encode(const V &data) const
Definition base64.hpp:139
size_t decode(void *data, size_t len, const std::string &str) const
Definition base64.hpp:186
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1241
virtual void rand_bytes(unsigned char *buf, size_t size)=0
Fill a buffer with random bytes.
Abstract base class for cryptographically strong random number generators.
Definition randapi.hpp:226
unsigned char hmac_value_[HMAC_KEY_SIZE]
unsigned char cipher_value_[CIPHER_KEY_SIZE]
bool operator!=(const Key &rhs) const
static constexpr size_t CIPHER_KEY_SIZE
bool operator==(const Key &rhs) const
void key_transform(KEY_TRANSFORM &t)
static constexpr size_t HMAC_KEY_SIZE
Key(const std::string &cipher_key_b64, const std::string &hmac_key_b64)
bool operator==(const Name &rhs) const
bool operator!=(const Name &rhs) const
Name(const unsigned char name[SIZE])
bool operator<(const Name &rhs) const
Name(const std::string &name_b64)
std::unique_ptr< TLSSessionTicketBase > UPtr
static void b64_to_key(const std::string &b64, const char *title, unsigned char *out, const size_t outlen)
virtual std::string session_id_context() const =0
virtual Status create_session_ticket_key(Name &name, Key &key) const =0
virtual ~TLSSessionTicketBase()=default
virtual Status lookup_session_ticket_key(const Name &name, Key &key) const =0
OPENVPN_EXCEPTION(sess_ticket_error)
#define OPENVPN_HASH_METHOD(T, meth)
Definition hash.hpp:30
const Base64 * base64
Definition base64.hpp:299
Implementation of the base classes for random number generators.
static std::stringstream out
Definition test_path.cpp:10