src/corosio/src/tls/context.cpp

97.3% Lines (108/111) 100.0% List of functions (27/27) 66.7% Branches (28/42)
context.cpp
f(x) Functions (27)
Function Calls Lines Branches Blocks
boost::corosio::(anonymous namespace)::read_file_contents(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) :26 32x 100.0% 57.1% 66.0% boost::corosio::tls_context::tls_context() :40 6280x 100.0% 100.0% boost::corosio::tls_context::use_certificate(std::__1::basic_string_view<char, std::__1::char_traits<char>>, boost::corosio::tls_file_format) :47 1546x 100.0% 100.0% boost::corosio::tls_context::use_certificate_file(std::__1::basic_string_view<char, std::__1::char_traits<char>>, boost::corosio::tls_file_format) :56 6x 100.0% 100.0% 100.0% boost::corosio::tls_context::use_certificate_chain(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :66 3x 100.0% 100.0% boost::corosio::tls_context::use_certificate_chain_file(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :73 6x 100.0% 100.0% boost::corosio::tls_context::use_private_key(std::__1::basic_string_view<char, std::__1::char_traits<char>>, boost::corosio::tls_file_format) :79 1547x 100.0% 100.0% boost::corosio::tls_context::use_private_key_file(std::__1::basic_string_view<char, std::__1::char_traits<char>>, boost::corosio::tls_file_format) :88 7x 100.0% 100.0% 100.0% boost::corosio::tls_context::use_pkcs12(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::basic_string_view<char, std::__1::char_traits<char>>) :98 7x 100.0% 100.0% boost::corosio::tls_context::use_pkcs12_file(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::basic_string_view<char, std::__1::char_traits<char>>) :110 3x 66.7% 50.0% 75.0% boost::corosio::tls_context::add_certificate_authority(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :126 1560x 100.0% 100.0% boost::corosio::tls_context::load_verify_file(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :133 5x 100.0% 66.7% 75.0% boost::corosio::tls_context::add_verify_path(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :143 5x 100.0% 100.0% boost::corosio::tls_context::set_default_verify_paths() :150 8x 100.0% 100.0% boost::corosio::tls_context::set_min_protocol_version(boost::corosio::tls_version) :161 14x 100.0% 100.0% boost::corosio::tls_context::set_max_protocol_version(boost::corosio::tls_version) :168 8x 100.0% 100.0% boost::corosio::tls_context::set_ciphersuites(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :175 10x 100.0% 100.0% boost::corosio::tls_context::set_ciphersuites_tls13(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :182 7x 100.0% 100.0% boost::corosio::tls_context::set_alpn(std::initializer_list<std::__1::basic_string_view<char, std::__1::char_traits<char>>>) :189 9x 90.0% 70.0% 92.0% boost::corosio::tls_context::set_verify_mode(boost::corosio::tls_verify_mode) :211 3102x 100.0% 100.0% boost::corosio::tls_context::set_verify_depth(int) :218 3x 100.0% 100.0% boost::corosio::tls_context::set_servername_callback_impl(std::__1::function<bool (std::__1::basic_string_view<char, std::__1::char_traits<char>>)>) :225 9x 100.0% 100.0% boost::corosio::tls_context::set_password_callback_impl(std::__1::function<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> (unsigned long, boost::corosio::tls_password_purpose)>) :232 6x 100.0% 100.0% boost::corosio::tls_context::set_verify_callback_impl(std::__1::function<bool (bool, boost::corosio::verify_context&)>) :239 7x 100.0% 100.0% boost::corosio::tls_context::add_crl(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :250 6x 100.0% 100.0% boost::corosio::tls_context::add_crl_file(std::__1::basic_string_view<char, std::__1::char_traits<char>>) :257 5x 100.0% 66.7% 75.0% boost::corosio::tls_context::set_revocation_policy(boost::corosio::tls_revocation_policy) :267 12x 100.0% 100.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco ([email protected])
3 // Copyright (c) 2026 Steve Gerbino
4 // Copyright (c) 2026 Michael Vandeberg
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // Official repository: https://github.com/cppalliance/corosio
10 //
11
12 #include <boost/corosio/tls_context.hpp>
13 #include "detail/context_impl.hpp"
14
15 #include <cerrno>
16 #include <fstream>
17 #include <sstream>
18
19 namespace boost::corosio {
20
21 namespace {
22
23 // Read an entire file in binary mode into `out`, returning ENOENT if it
24 // cannot be opened. Shared by the file-based credential/trust loaders.
25 std::error_code
26 32x read_file_contents(std::string_view filename, std::string& out)
27 {
28
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32x std::ifstream file(std::string(filename), std::ios::binary);
29
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 27 times.
32x if (!file)
30 27x return std::error_code(ENOENT, std::generic_category());
31
32
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5x std::ostringstream ss;
33
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5x ss << file.rdbuf();
34
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5x out = ss.str();
35 5x return {};
36 32x }
37
38 } // namespace
39
40 6280x tls_context::tls_context() : impl_(std::make_shared<implementation>()) {}
41
42 //
43 // Credential Loading
44 //
45
46 std::error_code
47 1546x tls_context::use_certificate(
48 std::string_view certificate, tls_file_format format)
49 {
50 1546x impl_->entity_certificate = std::string(certificate);
51 1546x impl_->entity_cert_format = format;
52 1546x return {};
53 }
54
55 std::error_code
56 6x tls_context::use_certificate_file(
57 std::string_view filename, tls_file_format format)
58 {
59
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 time.
6x if (auto ec = read_file_contents(filename, impl_->entity_certificate); ec)
60 5x return ec;
61 1x impl_->entity_cert_format = format;
62 1x return {};
63 6x }
64
65 std::error_code
66 3x tls_context::use_certificate_chain(std::string_view chain)
67 {
68 3x impl_->certificate_chain = std::string(chain);
69 3x return {};
70 }
71
72 std::error_code
73 6x tls_context::use_certificate_chain_file(std::string_view filename)
74 {
75 6x return read_file_contents(filename, impl_->certificate_chain);
76 }
77
78 std::error_code
79 1547x tls_context::use_private_key(
80 std::string_view private_key, tls_file_format format)
81 {
82 1547x impl_->private_key = std::string(private_key);
83 1547x impl_->private_key_format = format;
84 1547x return {};
85 }
86
87 std::error_code
88 7x tls_context::use_private_key_file(
89 std::string_view filename, tls_file_format format)
90 {
91
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 time.
7x if (auto ec = read_file_contents(filename, impl_->private_key); ec)
92 6x return ec;
93 1x impl_->private_key_format = format;
94 1x return {};
95 7x }
96
97 std::error_code
98 7x tls_context::use_pkcs12(std::string_view data, std::string_view passphrase)
99 {
100 // assign(ptr, len) rather than std::string(string_view): libstdc++'s
101 // basic_string(const char*, size_t) computes std::distance(s, s + n),
102 // whose one-past-the-end pointer ASan's detect_invalid_pointer_pairs
103 // rejects for a global buffer. assign copies without that subtraction.
104 7x impl_->pkcs12_data.assign(data.data(), data.size());
105 7x impl_->pkcs12_password.assign(passphrase.data(), passphrase.size());
106 7x return {};
107 }
108
109 std::error_code
110 3x tls_context::use_pkcs12_file(
111 std::string_view filename, std::string_view passphrase)
112 {
113
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3x if (auto ec = read_file_contents(filename, impl_->pkcs12_data); ec)
114 3x return ec;
115 // assign(ptr, len), not std::string(passphrase): see the note in
116 // use_pkcs12.
117 impl_->pkcs12_password.assign(passphrase.data(), passphrase.size());
118 return {};
119 3x }
120
121 //
122 // Trust Anchors
123 //
124
125 std::error_code
126 1560x tls_context::add_certificate_authority(std::string_view ca)
127 {
128 1560x impl_->ca_certificates.emplace_back(ca);
129 1560x return {};
130 }
131
132 std::error_code
133 5x tls_context::load_verify_file(std::string_view filename)
134 {
135 5x std::string contents;
136
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 4 times.
5x if (auto ec = read_file_contents(filename, contents); ec)
137 4x return ec;
138
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1x impl_->ca_certificates.push_back(std::move(contents));
139 1x return {};
140 5x }
141
142 std::error_code
143 5x tls_context::add_verify_path(std::string_view path)
144 {
145 5x impl_->verify_paths.emplace_back(path);
146 5x return {};
147 }
148
149 std::error_code
150 8x tls_context::set_default_verify_paths()
151 {
152 8x impl_->use_default_verify_paths = true;
153 8x return {};
154 }
155
156 //
157 // Protocol Configuration
158 //
159
160 std::error_code
161 14x tls_context::set_min_protocol_version(tls_version v)
162 {
163 14x impl_->min_version = v;
164 14x return {};
165 }
166
167 std::error_code
168 8x tls_context::set_max_protocol_version(tls_version v)
169 {
170 8x impl_->max_version = v;
171 8x return {};
172 }
173
174 std::error_code
175 10x tls_context::set_ciphersuites(std::string_view ciphers)
176 {
177 10x impl_->ciphersuites = std::string(ciphers);
178 10x return {};
179 }
180
181 std::error_code
182 7x tls_context::set_ciphersuites_tls13(std::string_view ciphers)
183 {
184 7x impl_->ciphersuites_tls13 = std::string(ciphers);
185 7x return {};
186 }
187
188 std::error_code
189 9x tls_context::set_alpn(std::initializer_list<std::string_view> protocols)
190 {
191 // Validate before mutating so a bad entry doesn't silently drop part of
192 // the list (or wipe a prior valid configuration). A name must be a
193 // non-empty token no longer than 255 bytes (the ALPN wire length field)
194 // and must not contain a comma (WolfSSL's list separator).
195
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9 times.
21x for (auto const& p : protocols)
196
3/6
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
12x if (p.empty() || p.size() > 255 ||
197 12x p.find(',') != std::string_view::npos)
198 return std::make_error_code(std::errc::invalid_argument);
199
200 9x impl_->alpn_protocols.clear();
201
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9 times.
21x for (auto const& p : protocols)
202 12x impl_->alpn_protocols.emplace_back(p);
203 9x return {};
204 9x }
205
206 //
207 // Certificate Verification
208 //
209
210 std::error_code
211 3102x tls_context::set_verify_mode(tls_verify_mode mode)
212 {
213 3102x impl_->verification_mode = mode;
214 3102x return {};
215 }
216
217 std::error_code
218 3x tls_context::set_verify_depth(int depth)
219 {
220 3x impl_->verify_depth = depth;
221 3x return {};
222 }
223
224 void
225 9x tls_context::set_servername_callback_impl(
226 std::function<bool(std::string_view)> callback)
227 {
228 9x impl_->servername_callback = std::move(callback);
229 9x }
230
231 void
232 6x tls_context::set_password_callback_impl(
233 std::function<std::string(std::size_t, tls_password_purpose)> callback)
234 {
235 6x impl_->password_callback = std::move(callback);
236 6x }
237
238 void
239 7x tls_context::set_verify_callback_impl(
240 std::function<bool(bool, verify_context&)> callback)
241 {
242 7x impl_->verify_callback = std::move(callback);
243 7x }
244
245 //
246 // Revocation Checking
247 //
248
249 std::error_code
250 6x tls_context::add_crl(std::string_view crl)
251 {
252 6x impl_->crls.emplace_back(crl);
253 6x return {};
254 }
255
256 std::error_code
257 5x tls_context::add_crl_file(std::string_view filename)
258 {
259 5x std::string contents;
260
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 4 times.
5x if (auto ec = read_file_contents(filename, contents); ec)
261 4x return ec;
262
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1x impl_->crls.push_back(std::move(contents));
263 1x return {};
264 5x }
265
266 void
267 12x tls_context::set_revocation_policy(tls_revocation_policy policy)
268 {
269 12x impl_->revocation = policy;
270 12x }
271
272 } // namespace boost::corosio
273