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 typedef std::unique_ptr<TLSSessionTicketBase> UPtr;
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
111 {
112 } // note that default constructor leaves object in an undefined state
113
114 unsigned char value_[SIZE];
115 };
116
117 class Key
118 {
119 public:
120 static constexpr size_t CIPHER_KEY_SIZE = 32;
121 static constexpr size_t HMAC_KEY_SIZE = 16;
122
128
129 explicit Key(const std::string &cipher_key_b64, const std::string &hmac_key_b64)
130 {
131 b64_to_key(cipher_key_b64, "cipher key", cipher_value_, CIPHER_KEY_SIZE);
132 b64_to_key(hmac_key_b64, "hmac key", hmac_value_, HMAC_KEY_SIZE);
133 }
134
136 {
137 // wipe keys
138 std::memset(cipher_value_, 0, CIPHER_KEY_SIZE);
139 std::memset(hmac_value_, 0, HMAC_KEY_SIZE);
140 }
141
142 std::string to_string() const
143 {
144 return "TLSTicketKey[cipher=" + cipher_b64() + " hmac=" + hmac_b64() + ']';
145 }
146
147 std::string cipher_b64() const
148 {
150 }
151
152 std::string hmac_b64() const
153 {
155 }
156
157 bool operator==(const Key &rhs) const
158 {
159 return std::memcmp(cipher_value_, rhs.cipher_value_, CIPHER_KEY_SIZE) == 0 && std::memcmp(hmac_value_, rhs.hmac_value_, HMAC_KEY_SIZE) == 0;
160 }
161
162 bool operator!=(const Key &rhs) const
163 {
164 return !operator==(rhs);
165 }
166
167 template <typename KEY_TRANSFORM>
168 void key_transform(KEY_TRANSFORM &t)
169 {
170 unsigned char out[KEY_TRANSFORM::MAX_HMAC_SIZE];
171
172 // cipher
173 {
174 t.cipher_transform.reset();
175 t.cipher_transform.update(cipher_value_, CIPHER_KEY_SIZE);
176 const size_t size = t.cipher_transform.final(out);
177 if (size < CIPHER_KEY_SIZE)
178 throw sess_ticket_error("insufficient key material for cipher transform");
179 std::memcpy(cipher_value_, out, CIPHER_KEY_SIZE);
180 }
181
182 // hmac
183 {
184 t.hmac_transform.reset();
185 t.hmac_transform.update(hmac_value_, HMAC_KEY_SIZE);
186 const size_t size = t.hmac_transform.final(out);
187 if (size < HMAC_KEY_SIZE)
188 throw sess_ticket_error("insufficient key material for hmac transform");
189 std::memcpy(hmac_value_, out, HMAC_KEY_SIZE);
190 }
191 }
192
193 private:
194 // we need to friend SSL implementation classes
195 friend class OpenSSLContext;
196 friend class MbedTLSContext;
197
199 {
200 } // note that default constructor leaves object in an undefined state
201
204 };
205
206 // method returns name and key
207 virtual Status create_session_ticket_key(Name &name, Key &key) const = 0;
208
209 // method is given name and returns key
210 virtual Status lookup_session_ticket_key(const Name &name, Key &key) const = 0;
211
212 // return string that identifies the app
213 virtual std::string session_id_context() const = 0;
214
215 virtual ~TLSSessionTicketBase() = default;
216
217 private:
218 static void b64_to_key(const std::string &b64, const char *title, unsigned char *out, const size_t outlen)
219 {
220 Buffer srcbuf(out, outlen, false);
221 try
222 {
223 base64->decode(srcbuf, b64);
224 }
225 catch (const std::exception &e)
226 {
227 throw sess_ticket_error(std::string("base64 decode for ") + title + ": " + std::string(e.what()));
228 }
229 if (srcbuf.size() != outlen)
230 throw sess_ticket_error(std::string("wrong input size for ") + title + ", actual=" + std::to_string(srcbuf.size()) + " expected=" + std::to_string(outlen));
231 }
232};
233} // namespace openvpn
234
235#ifdef USE_OPENVPN_HASH
237#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:1242
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:228
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)
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
std::unique_ptr< TLSSessionTicketBase > UPtr
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