Skip to content

Commit 8aa211c

Browse files
committed
TCP input TLS - Add SslCtx, wrapper around SSL_CTX.
1 parent 378bea2 commit 8aa211c

File tree

1 file changed

+229
-0
lines changed

1 file changed

+229
-0
lines changed
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/**
2+
* \file
3+
* \author Jakub Antonín Štigler <[email protected]>
4+
* \brief Wrapper around SSL_CTX from OpenSSL. (header file)
5+
* \date 2025
6+
*
7+
* Copyright: (C) 2023 CESNET, z.s.p.o.
8+
* SPDX-License-Identifier: BSD-3-Clause
9+
*/
10+
11+
#pragma once
12+
13+
#include <array>
14+
#include <memory>
15+
#include <stdexcept>
16+
#include <string>
17+
18+
#include <openssl/err.h>
19+
#include <openssl/ssl.h>
20+
21+
#include "Ssl.hpp"
22+
#include "throw_ssl_err.hpp"
23+
24+
namespace tcp_in {
25+
namespace tls {
26+
27+
/** Wrapper around `SSL_CTX` from OpenSSL. */
28+
class SslCtx {
29+
public:
30+
/**
31+
* @brief Construct this with the given method.
32+
* @param method Method for creating `SSL_CTX`. Can be obtained for example with
33+
* `TLS_server_method()`.
34+
* @throws `std::runtime_error` on failure.
35+
*/
36+
SslCtx(const SSL_METHOD *method) : m_ctx(SSL_CTX_new(method)) {
37+
if (!m_ctx.get()) {
38+
throw_ssl_err("Failed to create ssl context.");
39+
}
40+
}
41+
42+
/**
43+
* @brief Set the verify mode. (What should be verified about peer)
44+
* @param mode Verify mode (e.g. SSL_VERIFY_NONE).
45+
* @param cb Verify callback.
46+
*/
47+
void set_verify(int mode, SSL_verify_cb cb = nullptr) noexcept {
48+
SSL_CTX_set_verify(m_ctx.get(), mode, cb);
49+
}
50+
51+
/**
52+
* @brief Sets the paths to trusted certificates to the default locations.
53+
*
54+
* This will try to set the paths from environment variables, and if that fails, it will use the
55+
* os defaults.
56+
* @throws `std::runtime_error` on failure.
57+
*/
58+
void set_default_verify_paths() {
59+
if (!SSL_CTX_set_default_verify_paths(m_ctx.get())) {
60+
throw_ssl_err("Failed to set default trusted certificate paths.");
61+
}
62+
}
63+
64+
/**
65+
* @brief Sets the path to trusted certificate file.
66+
*
67+
* This will try to set the path from environment variable `SSL_CERT_FILE`, and if that fails,
68+
* it will use the os defaults.
69+
* @throws `std::runtime_error` on failure.
70+
*/
71+
void set_default_verify_file() {
72+
if (!SSL_CTX_set_default_verify_file(m_ctx.get())) {
73+
throw_ssl_err("Failed to set default trusted certificate file.");
74+
}
75+
}
76+
77+
/**
78+
* @brief Sets the path to trusted certificate file.
79+
* @throws `std::runtime_error` on failure.
80+
*/
81+
void load_verify_file(const char *path) {
82+
if (!SSL_CTX_load_verify_file(m_ctx.get(), path)) {
83+
throw_ssl_err("Failed to set default trusted certificate file `", path, "`.");
84+
}
85+
}
86+
87+
/**
88+
* @brief Sets the path to trusted certificates directory.
89+
*
90+
* This will try to set the path from environment variable `SSL_CERT_DIR`, and if that fails, it
91+
* will use the os defaults.
92+
* @throws `std::runtime_error` on failure.
93+
*/
94+
void set_default_verify_dir() {
95+
if (!SSL_CTX_set_default_verify_dir(m_ctx.get())) {
96+
throw_ssl_err("Failed to set default trusted certificate directory.");
97+
}
98+
}
99+
100+
/**
101+
* @brief Sets the path to trusted certificates directory.
102+
* @throws `std::runtime_error` on failure.
103+
*/
104+
void load_verify_dir(const char *path) {
105+
if (!SSL_CTX_load_verify_dir(m_ctx.get(), path)) {
106+
throw_ssl_err("Failed to set default trusted certificate directory `", path, "`.");
107+
}
108+
}
109+
110+
/**
111+
* @brief Sets the path to trusted certificates store.
112+
*
113+
* It will use the OS defaults.
114+
* @throws `std::runtime_error` on failure.
115+
*/
116+
void set_default_verify_store() {
117+
if (!SSL_CTX_set_default_verify_store(m_ctx.get())) {
118+
throw_ssl_err("Failed to set default trusted certificate store.");
119+
}
120+
}
121+
122+
/**
123+
* @brief Sets the path to trusted certificates store.
124+
* @throws `std::runtime_error` on failure.
125+
*/
126+
void load_verify_store(const char *path) {
127+
if (!SSL_CTX_load_verify_store(m_ctx.get(), path)) {
128+
throw_ssl_err("Failed to set default trusted certificate store `", path, "`.");
129+
}
130+
}
131+
132+
/**
133+
* @brief Set the minimum allowed TLS version.
134+
* @param version Minimum allowed tls version. `TLS1_2_VERSION` and higher is recommended.
135+
* @throws `std::runtime_error` on failure.
136+
*/
137+
void set_min_proto_version(long version) {
138+
if (!SSL_CTX_set_min_proto_version(m_ctx.get(), version)) {
139+
throw_ssl_err("Failed to set minimum tls version.");
140+
}
141+
}
142+
143+
/**
144+
* @brief Set `SslCtx` flags.
145+
* @param opts Flags for `SSL_CTX`.
146+
*/
147+
void set_options(std::uint64_t opts) noexcept { SSL_CTX_set_options(m_ctx.get(), opts); }
148+
149+
/**
150+
* @brief Set file with certificate with which this will verify to peer.
151+
* @param file_path Path to file in PEM format with certificate (and parent certificate(s)).
152+
* @throws `std::runtime_error` on failure.
153+
*/
154+
void use_certificate_chain_file(const char *file_path) {
155+
if (SSL_CTX_use_certificate_chain_file(m_ctx.get(), file_path) <= 0) {
156+
throw_ssl_err("Failed to load certificate chain file.");
157+
}
158+
}
159+
160+
/**
161+
* @brief Set private key of used certificate.
162+
*
163+
* This may prompt the user for password for the private key.
164+
* @param file_path Path to file with the private key.
165+
* @param type Format of the file (e.g. `SSL_FILETYPE_PEM`).
166+
* @throws `std::runtime_error` on failure.
167+
*/
168+
void use_private_key_file(const char *file_path, int type) {
169+
if (SSL_CTX_use_PrivateKey_file(m_ctx.get(), file_path, type) <= 0) {
170+
throw_ssl_err("Failed to load private key file.");
171+
}
172+
}
173+
174+
/**
175+
* @brief Set cache id unique to aplication.
176+
* @param id_data Arbitrary cache id data.
177+
* @param id_len Length of `id_data`.
178+
*/
179+
void set_session_id_context(const char *id_data, unsigned id_len) noexcept {
180+
SSL_CTX_set_session_id_context(
181+
m_ctx.get(),
182+
reinterpret_cast<const unsigned char *>(id_data),
183+
id_len
184+
);
185+
}
186+
187+
/**
188+
* @brief Set the session caching mode. (Caching for connections from the same client.)
189+
* @param mode Caching mode (e.g. `SSL_SESS_CACHE_SERVER`).
190+
*/
191+
void set_session_cache_mode(long mode) noexcept {
192+
SSL_CTX_set_session_cache_mode(m_ctx.get(), mode);
193+
}
194+
195+
/**
196+
* @brief Sets the size of cache.
197+
* @param size Size of the cache.
198+
*/
199+
void sess_set_cache_size(long size) noexcept {
200+
SSL_CTX_sess_set_cache_size(m_ctx.get(), size);
201+
}
202+
203+
/**
204+
* @brief Set timeout for cached connection data.
205+
* @param seconds Timeout for cached connection data in seconds.
206+
*/
207+
void sess_set_timeout(long seconds) noexcept {
208+
SSL_CTX_set_timeout(m_ctx.get(), seconds);
209+
}
210+
211+
/**
212+
* @brief Uses this to create new `Ssl`.
213+
* @return Newly create ssl.
214+
* @throws `std::runtime_error` on failure.
215+
*/
216+
Ssl create_ssl() { return { m_ctx.get() }; }
217+
218+
private:
219+
/** Deleter for SSL_CTX. */
220+
class Deleter {
221+
public:
222+
void operator()(SSL_CTX *ptr) { SSL_CTX_free(ptr); }
223+
};
224+
225+
std::unique_ptr<SSL_CTX, Deleter> m_ctx;
226+
};
227+
228+
} // namespace tls
229+
} // namespace tcp_in

0 commit comments

Comments
 (0)