Line data Source code
1 : #include "source/extensions/transport_sockets/tls/context_impl.h"
2 :
3 : #include <openssl/ssl.h>
4 :
5 : #include <algorithm>
6 : #include <cstddef>
7 : #include <cstdint>
8 : #include <memory>
9 : #include <string>
10 : #include <utility>
11 : #include <vector>
12 :
13 : #include "envoy/admin/v3/certs.pb.h"
14 : #include "envoy/common/exception.h"
15 : #include "envoy/common/platform.h"
16 : #include "envoy/ssl/ssl_socket_extended_info.h"
17 : #include "envoy/stats/scope.h"
18 : #include "envoy/type/matcher/v3/string.pb.h"
19 :
20 : #include "source/common/common/assert.h"
21 : #include "source/common/common/base64.h"
22 : #include "source/common/common/fmt.h"
23 : #include "source/common/common/hex.h"
24 : #include "source/common/common/utility.h"
25 : #include "source/common/network/address_impl.h"
26 : #include "source/common/protobuf/utility.h"
27 : #include "source/common/runtime/runtime_features.h"
28 : #include "source/common/stats/utility.h"
29 : #include "source/extensions/transport_sockets/tls/cert_validator/factory.h"
30 : #include "source/extensions/transport_sockets/tls/stats.h"
31 : #include "source/extensions/transport_sockets/tls/utility.h"
32 :
33 : #include "absl/container/node_hash_set.h"
34 : #include "absl/strings/match.h"
35 : #include "absl/strings/str_join.h"
36 : #include "cert_validator/cert_validator.h"
37 : #include "openssl/evp.h"
38 : #include "openssl/hmac.h"
39 : #include "openssl/pkcs12.h"
40 : #include "openssl/rand.h"
41 :
42 : namespace Envoy {
43 : namespace Extensions {
44 : namespace TransportSockets {
45 : namespace Tls {
46 :
47 : namespace {
48 :
49 0 : bool cbsContainsU16(CBS& cbs, uint16_t n) {
50 0 : while (CBS_len(&cbs) > 0) {
51 0 : uint16_t v;
52 0 : if (!CBS_get_u16(&cbs, &v)) {
53 0 : return false;
54 0 : }
55 0 : if (v == n) {
56 0 : return true;
57 0 : }
58 0 : }
59 :
60 0 : return false;
61 0 : }
62 :
63 0 : void logSslErrorChain() {
64 0 : while (uint64_t err = ERR_get_error()) {
65 0 : ENVOY_LOG_MISC(debug, "SSL error: {}:{}:{}:{}", err,
66 0 : absl::NullSafeStringView(ERR_lib_error_string(err)),
67 0 : absl::NullSafeStringView(ERR_func_error_string(err)), ERR_GET_REASON(err),
68 0 : absl::NullSafeStringView(ERR_reason_error_string(err)));
69 0 : }
70 0 : }
71 :
72 : } // namespace
73 :
74 0 : int ContextImpl::sslExtendedSocketInfoIndex() {
75 0 : CONSTRUCT_ON_FIRST_USE(int, []() -> int {
76 0 : int ssl_context_index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
77 0 : RELEASE_ASSERT(ssl_context_index >= 0, "");
78 0 : return ssl_context_index;
79 0 : }());
80 0 : }
81 :
82 : ContextImpl::ContextImpl(Stats::Scope& scope, const Envoy::Ssl::ContextConfig& config,
83 : TimeSource& time_source)
84 : : scope_(scope), stats_(generateSslStats(scope)), time_source_(time_source),
85 : tls_max_version_(config.maxProtocolVersion()),
86 : stat_name_set_(scope.symbolTable().makeSet("TransportSockets::Tls")),
87 : unknown_ssl_cipher_(stat_name_set_->add("unknown_ssl_cipher")),
88 : unknown_ssl_curve_(stat_name_set_->add("unknown_ssl_curve")),
89 : unknown_ssl_algorithm_(stat_name_set_->add("unknown_ssl_algorithm")),
90 : unknown_ssl_version_(stat_name_set_->add("unknown_ssl_version")),
91 : ssl_ciphers_(stat_name_set_->add("ssl.ciphers")),
92 : ssl_versions_(stat_name_set_->add("ssl.versions")),
93 : ssl_curves_(stat_name_set_->add("ssl.curves")),
94 : ssl_sigalgs_(stat_name_set_->add("ssl.sigalgs")), capabilities_(config.capabilities()),
95 0 : tls_keylog_local_(config.tlsKeyLogLocal()), tls_keylog_remote_(config.tlsKeyLogRemote()) {
96 :
97 0 : auto cert_validator_name = getCertValidatorName(config.certificateValidationContext());
98 0 : auto cert_validator_factory =
99 0 : Registry::FactoryRegistry<CertValidatorFactory>::getFactory(cert_validator_name);
100 :
101 0 : if (!cert_validator_factory) {
102 0 : throwEnvoyExceptionOrPanic(
103 0 : absl::StrCat("Failed to get certificate validator factory for ", cert_validator_name));
104 0 : }
105 :
106 0 : cert_validator_ = cert_validator_factory->createCertValidator(
107 0 : config.certificateValidationContext(), stats_, time_source_);
108 :
109 0 : const auto tls_certificates = config.tlsCertificates();
110 0 : tls_contexts_.resize(std::max(static_cast<size_t>(1), tls_certificates.size()));
111 :
112 0 : std::vector<SSL_CTX*> ssl_contexts(tls_contexts_.size());
113 0 : for (size_t i = 0; i < tls_contexts_.size(); i++) {
114 0 : auto& ctx = tls_contexts_[i];
115 0 : ctx.ssl_ctx_.reset(SSL_CTX_new(TLS_method()));
116 0 : ssl_contexts[i] = ctx.ssl_ctx_.get();
117 :
118 0 : int rc = SSL_CTX_set_app_data(ctx.ssl_ctx_.get(), this);
119 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
120 :
121 0 : rc = SSL_CTX_set_min_proto_version(ctx.ssl_ctx_.get(), config.minProtocolVersion());
122 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
123 :
124 0 : rc = SSL_CTX_set_max_proto_version(ctx.ssl_ctx_.get(), config.maxProtocolVersion());
125 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
126 :
127 0 : if (!capabilities_.provides_ciphers_and_curves &&
128 0 : !SSL_CTX_set_strict_cipher_list(ctx.ssl_ctx_.get(), config.cipherSuites().c_str())) {
129 : // Break up a set of ciphers into each individual cipher and try them each individually in
130 : // order to attempt to log which specific one failed. Example of config.cipherSuites():
131 : // "-ALL:[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]:ECDHE-ECDSA-AES128-SHA".
132 : //
133 : // "-" is both an operator when in the leading position of a token (-ALL: don't allow this
134 : // cipher), and the common separator in names (ECDHE-ECDSA-AES128-GCM-SHA256). Don't split on
135 : // it because it will separate pieces of the same cipher. When it is a leading character, it
136 : // is removed below.
137 0 : std::vector<absl::string_view> ciphers =
138 0 : StringUtil::splitToken(config.cipherSuites(), ":+![|]", false);
139 0 : std::vector<std::string> bad_ciphers;
140 0 : for (const auto& cipher : ciphers) {
141 0 : std::string cipher_str(cipher);
142 :
143 0 : if (absl::StartsWith(cipher_str, "-")) {
144 0 : cipher_str.erase(cipher_str.begin());
145 0 : }
146 :
147 0 : if (!SSL_CTX_set_strict_cipher_list(ctx.ssl_ctx_.get(), cipher_str.c_str())) {
148 0 : bad_ciphers.push_back(cipher_str);
149 0 : }
150 0 : }
151 0 : throwEnvoyExceptionOrPanic(fmt::format("Failed to initialize cipher suites {}. The following "
152 0 : "ciphers were rejected when tried individually: {}",
153 0 : config.cipherSuites(),
154 0 : absl::StrJoin(bad_ciphers, ", ")));
155 0 : }
156 :
157 0 : if (!capabilities_.provides_ciphers_and_curves &&
158 0 : !SSL_CTX_set1_curves_list(ctx.ssl_ctx_.get(), config.ecdhCurves().c_str())) {
159 0 : throwEnvoyExceptionOrPanic(
160 0 : absl::StrCat("Failed to initialize ECDH curves ", config.ecdhCurves()));
161 0 : }
162 :
163 : // Set signature algorithms if given, otherwise fall back to BoringSSL defaults.
164 0 : if (!capabilities_.provides_sigalgs && !config.signatureAlgorithms().empty()) {
165 0 : if (!SSL_CTX_set1_sigalgs_list(ctx.ssl_ctx_.get(), config.signatureAlgorithms().c_str())) {
166 0 : throwEnvoyExceptionOrPanic(absl::StrCat("Failed to initialize TLS signature algorithms ",
167 0 : config.signatureAlgorithms()));
168 0 : }
169 0 : }
170 0 : }
171 :
172 0 : auto verify_mode = cert_validator_->initializeSslContexts(
173 0 : ssl_contexts, config.capabilities().provides_certificates);
174 0 : if (!capabilities_.verifies_peer_certificates) {
175 0 : for (auto ctx : ssl_contexts) {
176 0 : if (verify_mode != SSL_VERIFY_NONE) {
177 : // TODO(danzh) Envoy's use of SSL_VERIFY_NONE does not quite match the actual semantics as
178 : // a client. As a client, SSL_VERIFY_NONE means to verify the certificate (which will fail
179 : // without trust anchors), save the result in the session ticket, but otherwise continue
180 : // with the handshake. But Envoy actually wants it to accept all certificates. The
181 : // disadvantage of using SSL_VERIFY_NONE is that it records the verify_result, which Envoy
182 : // never queries but gets saved in session tickets, and tries to find an anchor that isn't
183 : // there. And also it differs from server side behavior of SSL_VERIFY_NONE which won't
184 : // even request client certs. So, instead, we should configure a callback to skip
185 : // validation and always supply the callback to boring SSL.
186 0 : SSL_CTX_set_custom_verify(ctx, verify_mode, customVerifyCallback);
187 0 : SSL_CTX_set_reverify_on_resume(ctx, /*reverify_on_resume_enabled)=*/1);
188 0 : }
189 0 : }
190 0 : }
191 :
192 : #ifdef BORINGSSL_FIPS
193 : if (!capabilities_.is_fips_compliant) {
194 : throwEnvoyExceptionOrPanic(
195 : "Can't load a FIPS noncompliant custom handshaker while running in FIPS compliant mode.");
196 : }
197 : #endif
198 :
199 0 : if (!capabilities_.provides_certificates) {
200 0 : for (uint32_t i = 0; i < tls_certificates.size(); ++i) {
201 0 : auto& ctx = tls_contexts_[i];
202 : // Load certificate chain.
203 0 : const auto& tls_certificate = tls_certificates[i].get();
204 0 : if (!tls_certificate.pkcs12().empty()) {
205 0 : ctx.loadPkcs12(tls_certificate.pkcs12(), tls_certificate.pkcs12Path(),
206 0 : tls_certificate.password());
207 0 : } else {
208 0 : ctx.loadCertificateChain(tls_certificate.certificateChain(),
209 0 : tls_certificate.certificateChainPath());
210 0 : }
211 :
212 : // The must staple extension means the certificate promises to carry
213 : // with it an OCSP staple. https://tools.ietf.org/html/rfc7633#section-6
214 0 : constexpr absl::string_view tls_feature_ext = "1.3.6.1.5.5.7.1.24";
215 0 : constexpr absl::string_view must_staple_ext_value = "\x30\x3\x02\x01\x05";
216 0 : auto must_staple = Utility::getCertificateExtensionValue(*ctx.cert_chain_, tls_feature_ext);
217 0 : if (must_staple == must_staple_ext_value) {
218 0 : ctx.is_must_staple_ = true;
219 0 : }
220 :
221 0 : bssl::UniquePtr<EVP_PKEY> public_key(X509_get_pubkey(ctx.cert_chain_.get()));
222 0 : const int pkey_id = EVP_PKEY_id(public_key.get());
223 0 : ctx.is_ecdsa_ = pkey_id == EVP_PKEY_EC;
224 0 : switch (pkey_id) {
225 0 : case EVP_PKEY_EC: {
226 : // We only support P-256 ECDSA today.
227 0 : const EC_KEY* ecdsa_public_key = EVP_PKEY_get0_EC_KEY(public_key.get());
228 : // Since we checked the key type above, this should be valid.
229 0 : ASSERT(ecdsa_public_key != nullptr);
230 0 : const EC_GROUP* ecdsa_group = EC_KEY_get0_group(ecdsa_public_key);
231 0 : if (ecdsa_group == nullptr ||
232 0 : EC_GROUP_get_curve_name(ecdsa_group) != NID_X9_62_prime256v1) {
233 0 : throwEnvoyExceptionOrPanic(
234 0 : fmt::format("Failed to load certificate chain from {}, only P-256 "
235 0 : "ECDSA certificates are supported",
236 0 : ctx.cert_chain_file_path_));
237 0 : }
238 0 : ctx.is_ecdsa_ = true;
239 0 : } break;
240 0 : case EVP_PKEY_RSA: {
241 : // We require RSA certificates with 2048-bit or larger keys.
242 0 : const RSA* rsa_public_key = EVP_PKEY_get0_RSA(public_key.get());
243 : // Since we checked the key type above, this should be valid.
244 0 : ASSERT(rsa_public_key != nullptr);
245 0 : const unsigned rsa_key_length = RSA_bits(rsa_public_key);
246 : #ifdef BORINGSSL_FIPS
247 : if (rsa_key_length != 2048 && rsa_key_length != 3072 && rsa_key_length != 4096) {
248 : throwEnvoyExceptionOrPanic(
249 : fmt::format("Failed to load certificate chain from {}, only RSA certificates with "
250 : "2048-bit, 3072-bit or 4096-bit keys are supported in FIPS mode",
251 : ctx.cert_chain_file_path_));
252 : }
253 : #else
254 0 : if (rsa_key_length < 2048) {
255 0 : throwEnvoyExceptionOrPanic(
256 0 : fmt::format("Failed to load certificate chain from {}, only RSA "
257 0 : "certificates with 2048-bit or larger keys are supported",
258 0 : ctx.cert_chain_file_path_));
259 0 : }
260 0 : #endif
261 0 : } break;
262 : #ifdef BORINGSSL_FIPS
263 : default:
264 : throwEnvoyExceptionOrPanic(
265 : fmt::format("Failed to load certificate chain from {}, only RSA and "
266 : "ECDSA certificates are supported in FIPS mode",
267 : ctx.cert_chain_file_path_));
268 : #endif
269 0 : }
270 :
271 0 : Envoy::Ssl::PrivateKeyMethodProviderSharedPtr private_key_method_provider =
272 0 : tls_certificate.privateKeyMethod();
273 : // We either have a private key or a BoringSSL private key method provider.
274 0 : if (private_key_method_provider) {
275 0 : ctx.private_key_method_provider_ = private_key_method_provider;
276 : // The provider has a reference to the private key method for the context lifetime.
277 0 : Ssl::BoringSslPrivateKeyMethodSharedPtr private_key_method =
278 0 : private_key_method_provider->getBoringSslPrivateKeyMethod();
279 0 : if (private_key_method == nullptr) {
280 0 : throwEnvoyExceptionOrPanic(
281 0 : fmt::format("Failed to get BoringSSL private key method from provider"));
282 0 : }
283 : #ifdef BORINGSSL_FIPS
284 : if (!ctx.private_key_method_provider_->checkFips()) {
285 : throwEnvoyExceptionOrPanic(
286 : fmt::format("Private key method doesn't support FIPS mode with current parameters"));
287 : }
288 : #endif
289 0 : SSL_CTX_set_private_key_method(ctx.ssl_ctx_.get(), private_key_method.get());
290 0 : } else if (!tls_certificate.privateKey().empty()) {
291 : // Load private key.
292 0 : ctx.loadPrivateKey(tls_certificate.privateKey(), tls_certificate.privateKeyPath(),
293 0 : tls_certificate.password());
294 0 : }
295 0 : }
296 0 : }
297 :
298 : // use the server's cipher list preferences
299 0 : for (auto& ctx : tls_contexts_) {
300 0 : SSL_CTX_set_options(ctx.ssl_ctx_.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
301 0 : }
302 :
303 0 : parsed_alpn_protocols_ = parseAlpnProtocols(config.alpnProtocols());
304 :
305 0 : #if BORINGSSL_API_VERSION >= 21
306 : // Register stat names based on lists reported by BoringSSL.
307 0 : std::vector<const char*> list(SSL_get_all_cipher_names(nullptr, 0));
308 0 : SSL_get_all_cipher_names(list.data(), list.size());
309 0 : stat_name_set_->rememberBuiltins(list);
310 :
311 0 : list.resize(SSL_get_all_curve_names(nullptr, 0));
312 0 : SSL_get_all_curve_names(list.data(), list.size());
313 0 : stat_name_set_->rememberBuiltins(list);
314 :
315 0 : list.resize(SSL_get_all_signature_algorithm_names(nullptr, 0));
316 0 : SSL_get_all_signature_algorithm_names(list.data(), list.size());
317 0 : stat_name_set_->rememberBuiltins(list);
318 :
319 0 : list.resize(SSL_get_all_version_names(nullptr, 0));
320 0 : SSL_get_all_version_names(list.data(), list.size());
321 0 : stat_name_set_->rememberBuiltins(list);
322 : #else
323 : // Use the SSL library to iterate over the configured ciphers.
324 : //
325 : // Note that if a negotiated cipher suite is outside of this set, we'll issue an ENVOY_BUG.
326 : for (TlsContext& tls_context : tls_contexts_) {
327 : for (const SSL_CIPHER* cipher : SSL_CTX_get_ciphers(tls_context.ssl_ctx_.get())) {
328 : stat_name_set_->rememberBuiltin(SSL_CIPHER_get_name(cipher));
329 : }
330 : }
331 :
332 : // Add supported cipher suites from the TLS 1.3 spec:
333 : // https://tools.ietf.org/html/rfc8446#appendix-B.4
334 : // AES-CCM cipher suites are removed (no BoringSSL support).
335 : //
336 : // Note that if a negotiated cipher suite is outside of this set, we'll issue an ENVOY_BUG.
337 : stat_name_set_->rememberBuiltins(
338 : {"TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256"});
339 :
340 : // All supported curves. Source:
341 : // https://github.com/google/boringssl/blob/3743aafdacff2f7b083615a043a37101f740fa53/ssl/ssl_key_share.cc#L302-L309
342 : //
343 : // Note that if a negotiated curve is outside of this set, we'll issue an ENVOY_BUG.
344 : stat_name_set_->rememberBuiltins({"P-224", "P-256", "P-384", "P-521", "X25519", "CECPQ2"});
345 :
346 : // All supported signature algorithms. Source:
347 : // https://github.com/google/boringssl/blob/3743aafdacff2f7b083615a043a37101f740fa53/ssl/ssl_privkey.cc#L436-L453
348 : //
349 : // Note that if a negotiated algorithm is outside of this set, we'll issue an ENVOY_BUG.
350 : stat_name_set_->rememberBuiltins({
351 : "rsa_pkcs1_md5_sha1",
352 : "rsa_pkcs1_sha1",
353 : "rsa_pkcs1_sha256",
354 : "rsa_pkcs1_sha384",
355 : "rsa_pkcs1_sha512",
356 : "ecdsa_sha1",
357 : "ecdsa_secp256r1_sha256",
358 : "ecdsa_secp384r1_sha384",
359 : "ecdsa_secp521r1_sha512",
360 : "rsa_pss_rsae_sha256",
361 : "rsa_pss_rsae_sha384",
362 : "rsa_pss_rsae_sha512",
363 : "ed25519",
364 : });
365 :
366 : // All supported protocol versions.
367 : //
368 : // Note that if a negotiated version is outside of this set, we'll issue an ENVOY_BUG.
369 : stat_name_set_->rememberBuiltins({"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"});
370 : #endif
371 :
372 : // As late as possible, run the custom SSL_CTX configuration callback on each
373 : // SSL_CTX, if set.
374 0 : if (auto sslctx_cb = config.sslctxCb(); sslctx_cb) {
375 0 : for (TlsContext& ctx : tls_contexts_) {
376 0 : sslctx_cb(ctx.ssl_ctx_.get());
377 0 : }
378 0 : }
379 :
380 0 : if (!config.tlsKeyLogPath().empty()) {
381 0 : ENVOY_LOG(debug, "Enable tls key log");
382 0 : tls_keylog_file_ = config.accessLogManager().createAccessLog(
383 0 : Filesystem::FilePathAndType{Filesystem::DestinationType::File, config.tlsKeyLogPath()});
384 0 : for (auto& context : tls_contexts_) {
385 0 : SSL_CTX* ctx = context.ssl_ctx_.get();
386 0 : ASSERT(ctx != nullptr);
387 0 : SSL_CTX_set_keylog_callback(ctx, keylogCallback);
388 0 : }
389 0 : }
390 0 : }
391 :
392 0 : void ContextImpl::keylogCallback(const SSL* ssl, const char* line) {
393 0 : ASSERT(ssl != nullptr);
394 0 : auto callbacks =
395 0 : static_cast<Network::TransportSocketCallbacks*>(SSL_get_ex_data(ssl, sslSocketIndex()));
396 0 : auto ctx = static_cast<ContextImpl*>(SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)));
397 0 : ASSERT(callbacks != nullptr);
398 0 : ASSERT(ctx != nullptr);
399 :
400 0 : if ((ctx->tls_keylog_local_.getIpListSize() == 0 ||
401 0 : ctx->tls_keylog_local_.contains(
402 0 : *(callbacks->connection().connectionInfoProvider().localAddress()))) &&
403 0 : (ctx->tls_keylog_remote_.getIpListSize() == 0 ||
404 0 : ctx->tls_keylog_remote_.contains(
405 0 : *(callbacks->connection().connectionInfoProvider().remoteAddress())))) {
406 0 : ctx->tls_keylog_file_->write(absl::StrCat(line, "\n"));
407 0 : }
408 0 : }
409 :
410 0 : int ContextImpl::sslSocketIndex() {
411 0 : CONSTRUCT_ON_FIRST_USE(int, []() -> int {
412 0 : int ssl_socket_index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
413 0 : RELEASE_ASSERT(ssl_socket_index >= 0, "");
414 0 : return ssl_socket_index;
415 0 : }());
416 0 : }
417 :
418 : int ServerContextImpl::alpnSelectCallback(const unsigned char** out, unsigned char* outlen,
419 0 : const unsigned char* in, unsigned int inlen) {
420 : // Currently this uses the standard selection algorithm in priority order.
421 0 : const uint8_t* alpn_data = parsed_alpn_protocols_.data();
422 0 : size_t alpn_data_size = parsed_alpn_protocols_.size();
423 :
424 0 : if (SSL_select_next_proto(const_cast<unsigned char**>(out), outlen, alpn_data, alpn_data_size, in,
425 0 : inlen) != OPENSSL_NPN_NEGOTIATED) {
426 0 : return SSL_TLSEXT_ERR_NOACK;
427 0 : } else {
428 0 : return SSL_TLSEXT_ERR_OK;
429 0 : }
430 0 : }
431 :
432 0 : std::vector<uint8_t> ContextImpl::parseAlpnProtocols(const std::string& alpn_protocols) {
433 0 : if (alpn_protocols.empty()) {
434 0 : return {};
435 0 : }
436 :
437 0 : if (alpn_protocols.size() >= 65535) {
438 0 : throwEnvoyExceptionOrPanic("Invalid ALPN protocol string");
439 0 : }
440 :
441 0 : std::vector<uint8_t> out(alpn_protocols.size() + 1);
442 0 : size_t start = 0;
443 0 : for (size_t i = 0; i <= alpn_protocols.size(); i++) {
444 0 : if (i == alpn_protocols.size() || alpn_protocols[i] == ',') {
445 0 : if (i - start > 255) {
446 0 : throwEnvoyExceptionOrPanic("Invalid ALPN protocol string");
447 0 : }
448 :
449 0 : out[start] = i - start;
450 0 : start = i + 1;
451 0 : } else {
452 0 : out[i + 1] = alpn_protocols[i];
453 0 : }
454 0 : }
455 :
456 0 : return out;
457 0 : }
458 :
459 : bssl::UniquePtr<SSL>
460 0 : ContextImpl::newSsl(const Network::TransportSocketOptionsConstSharedPtr& options) {
461 : // We use the first certificate for a new SSL object, later in the
462 : // SSL_CTX_set_select_certificate_cb() callback following ClientHello, we replace with the
463 : // selected certificate via SSL_set_SSL_CTX().
464 0 : auto ssl_con = bssl::UniquePtr<SSL>(SSL_new(tls_contexts_[0].ssl_ctx_.get()));
465 0 : SSL_set_app_data(ssl_con.get(), &options);
466 0 : return ssl_con;
467 0 : }
468 :
469 0 : enum ssl_verify_result_t ContextImpl::customVerifyCallback(SSL* ssl, uint8_t* out_alert) {
470 0 : auto* extended_socket_info = reinterpret_cast<Envoy::Ssl::SslExtendedSocketInfo*>(
471 0 : SSL_get_ex_data(ssl, ContextImpl::sslExtendedSocketInfoIndex()));
472 0 : if (extended_socket_info->certificateValidationResult() != Ssl::ValidateStatus::NotStarted) {
473 0 : if (extended_socket_info->certificateValidationResult() == Ssl::ValidateStatus::Pending) {
474 0 : return ssl_verify_retry;
475 0 : }
476 0 : ENVOY_LOG(trace, "Already has a result: {}",
477 0 : static_cast<int>(extended_socket_info->certificateValidationStatus()));
478 : // Already has a binary result, return immediately.
479 0 : *out_alert = extended_socket_info->certificateValidationAlert();
480 0 : return extended_socket_info->certificateValidationResult() == Ssl::ValidateStatus::Successful
481 0 : ? ssl_verify_ok
482 0 : : ssl_verify_invalid;
483 0 : }
484 : // Hasn't kicked off any validation for this connection yet.
485 0 : SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
486 0 : ContextImpl* context_impl = static_cast<ContextImpl*>(SSL_CTX_get_app_data(ssl_ctx));
487 0 : auto transport_socket_options_shared_ptr_ptr =
488 0 : static_cast<const Network::TransportSocketOptionsConstSharedPtr*>(SSL_get_app_data(ssl));
489 0 : ASSERT(transport_socket_options_shared_ptr_ptr);
490 0 : ValidationResults result = context_impl->customVerifyCertChain(
491 0 : extended_socket_info, *transport_socket_options_shared_ptr_ptr, ssl);
492 0 : switch (result.status) {
493 0 : case ValidationResults::ValidationStatus::Successful:
494 0 : return ssl_verify_ok;
495 0 : case ValidationResults::ValidationStatus::Pending:
496 0 : return ssl_verify_retry;
497 0 : case ValidationResults::ValidationStatus::Failed: {
498 0 : if (result.tls_alert.has_value() && out_alert) {
499 0 : *out_alert = result.tls_alert.value();
500 0 : }
501 0 : return ssl_verify_invalid;
502 0 : }
503 0 : }
504 0 : PANIC("not reached");
505 0 : }
506 :
507 : ValidationResults ContextImpl::customVerifyCertChain(
508 : Envoy::Ssl::SslExtendedSocketInfo* extended_socket_info,
509 0 : const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, SSL* ssl) {
510 0 : ASSERT(extended_socket_info);
511 0 : STACK_OF(X509)* cert_chain = SSL_get_peer_full_cert_chain(ssl);
512 0 : if (cert_chain == nullptr) {
513 0 : extended_socket_info->setCertificateValidationStatus(Ssl::ClientValidationStatus::NotValidated);
514 0 : stats_.fail_verify_error_.inc();
515 0 : ENVOY_LOG(debug, "verify cert failed: no cert chain");
516 0 : return {ValidationResults::ValidationStatus::Failed, Ssl::ClientValidationStatus::NotValidated,
517 0 : SSL_AD_INTERNAL_ERROR, absl::nullopt};
518 0 : }
519 0 : ASSERT(cert_validator_);
520 0 : const char* host_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
521 :
522 0 : CertValidator::ExtraValidationContext validation_ctx;
523 0 : validation_ctx.callbacks =
524 0 : static_cast<Network::TransportSocketCallbacks*>(SSL_get_ex_data(ssl, sslSocketIndex()));
525 :
526 0 : ValidationResults result = cert_validator_->doVerifyCertChain(
527 0 : *cert_chain, extended_socket_info->createValidateResultCallback(), transport_socket_options,
528 0 : *SSL_get_SSL_CTX(ssl), validation_ctx, SSL_is_server(ssl),
529 0 : absl::NullSafeStringView(host_name));
530 0 : if (result.status != ValidationResults::ValidationStatus::Pending) {
531 0 : extended_socket_info->setCertificateValidationStatus(result.detailed_status);
532 0 : extended_socket_info->onCertificateValidationCompleted(
533 0 : result.status == ValidationResults::ValidationStatus::Successful, false);
534 0 : }
535 0 : return result;
536 0 : }
537 :
538 : void ContextImpl::incCounter(const Stats::StatName name, absl::string_view value,
539 0 : const Stats::StatName fallback) const {
540 0 : const Stats::StatName value_stat_name = stat_name_set_->getBuiltin(value, fallback);
541 0 : ENVOY_BUG(value_stat_name != fallback,
542 0 : absl::StrCat("Unexpected ", scope_.symbolTable().toString(name), " value: ", value));
543 0 : Stats::Utility::counterFromElements(scope_, {name, value_stat_name}).inc();
544 0 : }
545 :
546 0 : void ContextImpl::logHandshake(SSL* ssl) const {
547 0 : stats_.handshake_.inc();
548 :
549 0 : if (SSL_session_reused(ssl)) {
550 0 : stats_.session_reused_.inc();
551 0 : }
552 :
553 0 : incCounter(ssl_ciphers_, SSL_get_cipher_name(ssl), unknown_ssl_cipher_);
554 0 : incCounter(ssl_versions_, SSL_get_version(ssl), unknown_ssl_version_);
555 :
556 0 : const uint16_t curve_id = SSL_get_curve_id(ssl);
557 0 : if (curve_id) {
558 0 : incCounter(ssl_curves_, SSL_get_curve_name(curve_id), unknown_ssl_curve_);
559 0 : }
560 :
561 0 : const uint16_t sigalg_id = SSL_get_peer_signature_algorithm(ssl);
562 0 : if (sigalg_id) {
563 0 : const char* sigalg = SSL_get_signature_algorithm_name(sigalg_id, 1 /* include curve */);
564 0 : incCounter(ssl_sigalgs_, sigalg, unknown_ssl_algorithm_);
565 0 : }
566 :
567 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl));
568 0 : if (!cert.get()) {
569 0 : stats_.no_certificate_.inc();
570 0 : }
571 :
572 : #if defined(BORINGSSL_FIPS) && BORINGSSL_API_VERSION >= 18
573 : #error "Delete preprocessor check below; no longer needed"
574 : #endif
575 :
576 0 : #if BORINGSSL_API_VERSION >= 18
577 : // Increment the `was_key_usage_invalid_` stats to indicate the given cert would have triggered an
578 : // error but is allowed because the enforcement that rsa key usage and tls usage need to be
579 : // matched has been disabled.
580 0 : if (SSL_was_key_usage_invalid(ssl)) {
581 0 : stats_.was_key_usage_invalid_.inc();
582 0 : }
583 0 : #endif // BORINGSSL_API_VERSION
584 0 : }
585 :
586 0 : std::vector<Ssl::PrivateKeyMethodProviderSharedPtr> ContextImpl::getPrivateKeyMethodProviders() {
587 0 : std::vector<Envoy::Ssl::PrivateKeyMethodProviderSharedPtr> providers;
588 :
589 0 : for (auto& tls_context : tls_contexts_) {
590 0 : Envoy::Ssl::PrivateKeyMethodProviderSharedPtr provider =
591 0 : tls_context.getPrivateKeyMethodProvider();
592 0 : if (provider) {
593 0 : providers.push_back(provider);
594 0 : }
595 0 : }
596 0 : return providers;
597 0 : }
598 :
599 0 : absl::optional<uint32_t> ContextImpl::daysUntilFirstCertExpires() const {
600 0 : absl::optional<uint32_t> daysUntilExpiration = cert_validator_->daysUntilFirstCertExpires();
601 0 : if (!daysUntilExpiration.has_value()) {
602 0 : return absl::nullopt;
603 0 : }
604 0 : for (auto& ctx : tls_contexts_) {
605 0 : const absl::optional<uint32_t> tmp =
606 0 : Utility::getDaysUntilExpiration(ctx.cert_chain_.get(), time_source_);
607 0 : if (!tmp.has_value()) {
608 0 : return absl::nullopt;
609 0 : }
610 0 : daysUntilExpiration = std::min<uint32_t>(tmp.value(), daysUntilExpiration.value());
611 0 : }
612 0 : return daysUntilExpiration;
613 0 : }
614 :
615 0 : absl::optional<uint64_t> ContextImpl::secondsUntilFirstOcspResponseExpires() const {
616 0 : absl::optional<uint64_t> secs_until_expiration;
617 0 : for (auto& ctx : tls_contexts_) {
618 0 : if (ctx.ocsp_response_) {
619 0 : uint64_t next_expiration = ctx.ocsp_response_->secondsUntilExpiration();
620 0 : secs_until_expiration = std::min<uint64_t>(
621 0 : next_expiration, secs_until_expiration.value_or(std::numeric_limits<uint64_t>::max()));
622 0 : }
623 0 : }
624 :
625 0 : return secs_until_expiration;
626 0 : }
627 :
628 0 : Envoy::Ssl::CertificateDetailsPtr ContextImpl::getCaCertInformation() const {
629 0 : return cert_validator_->getCaCertInformation();
630 0 : }
631 :
632 0 : std::vector<Envoy::Ssl::CertificateDetailsPtr> ContextImpl::getCertChainInformation() const {
633 0 : std::vector<Envoy::Ssl::CertificateDetailsPtr> cert_details;
634 0 : for (const auto& ctx : tls_contexts_) {
635 0 : if (ctx.cert_chain_ == nullptr) {
636 0 : continue;
637 0 : }
638 :
639 0 : auto detail = Utility::certificateDetails(ctx.cert_chain_.get(), ctx.getCertChainFileName(),
640 0 : time_source_);
641 0 : auto ocsp_resp = ctx.ocsp_response_.get();
642 0 : if (ocsp_resp) {
643 0 : auto* ocsp_details = detail->mutable_ocsp_details();
644 0 : ProtobufWkt::Timestamp* valid_from = ocsp_details->mutable_valid_from();
645 0 : TimestampUtil::systemClockToTimestamp(ocsp_resp->getThisUpdate(), *valid_from);
646 0 : ProtobufWkt::Timestamp* expiration = ocsp_details->mutable_expiration();
647 0 : TimestampUtil::systemClockToTimestamp(ocsp_resp->getNextUpdate(), *expiration);
648 0 : }
649 0 : cert_details.push_back(std::move(detail));
650 0 : }
651 0 : return cert_details;
652 0 : }
653 :
654 : ClientContextImpl::ClientContextImpl(Stats::Scope& scope,
655 : const Envoy::Ssl::ClientContextConfig& config,
656 : TimeSource& time_source)
657 : : ContextImpl(scope, config, time_source),
658 : server_name_indication_(config.serverNameIndication()),
659 : allow_renegotiation_(config.allowRenegotiation()),
660 : enforce_rsa_key_usage_(config.enforceRsaKeyUsage()),
661 0 : max_session_keys_(config.maxSessionKeys()) {
662 : // This should be guaranteed during configuration ingestion for client contexts.
663 0 : ASSERT(tls_contexts_.size() == 1);
664 0 : if (!parsed_alpn_protocols_.empty()) {
665 0 : for (auto& ctx : tls_contexts_) {
666 0 : const int rc = SSL_CTX_set_alpn_protos(ctx.ssl_ctx_.get(), parsed_alpn_protocols_.data(),
667 0 : parsed_alpn_protocols_.size());
668 0 : RELEASE_ASSERT(rc == 0, Utility::getLastCryptoError().value_or(""));
669 0 : }
670 0 : }
671 :
672 0 : if (max_session_keys_ > 0) {
673 0 : SSL_CTX_set_session_cache_mode(tls_contexts_[0].ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT);
674 0 : SSL_CTX_sess_set_new_cb(
675 0 : tls_contexts_[0].ssl_ctx_.get(), [](SSL* ssl, SSL_SESSION* session) -> int {
676 0 : ContextImpl* context_impl =
677 0 : static_cast<ContextImpl*>(SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)));
678 0 : ClientContextImpl* client_context_impl = dynamic_cast<ClientContextImpl*>(context_impl);
679 0 : RELEASE_ASSERT(client_context_impl != nullptr, ""); // for Coverity
680 0 : return client_context_impl->newSessionKey(session);
681 0 : });
682 0 : }
683 0 : }
684 :
685 0 : bool ContextImpl::parseAndSetAlpn(const std::vector<std::string>& alpn, SSL& ssl) {
686 0 : std::vector<uint8_t> parsed_alpn = parseAlpnProtocols(absl::StrJoin(alpn, ","));
687 0 : if (!parsed_alpn.empty()) {
688 0 : const int rc = SSL_set_alpn_protos(&ssl, parsed_alpn.data(), parsed_alpn.size());
689 : // This should only if memory allocation fails, e.g. OOM.
690 0 : RELEASE_ASSERT(rc == 0, Utility::getLastCryptoError().value_or(""));
691 0 : return true;
692 0 : }
693 :
694 0 : return false;
695 0 : }
696 :
697 : bssl::UniquePtr<SSL>
698 0 : ClientContextImpl::newSsl(const Network::TransportSocketOptionsConstSharedPtr& options) {
699 0 : bssl::UniquePtr<SSL> ssl_con(ContextImpl::newSsl(options));
700 :
701 0 : const std::string server_name_indication = options && options->serverNameOverride().has_value()
702 0 : ? options->serverNameOverride().value()
703 0 : : server_name_indication_;
704 0 : if (!server_name_indication.empty()) {
705 0 : const int rc = SSL_set_tlsext_host_name(ssl_con.get(), server_name_indication.c_str());
706 0 : RELEASE_ASSERT(rc, Utility::getLastCryptoError().value_or(""));
707 0 : }
708 :
709 0 : if (options && !options->verifySubjectAltNameListOverride().empty()) {
710 0 : SSL_set_verify(ssl_con.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
711 0 : }
712 :
713 : // We determine what ALPN using the following precedence:
714 : // 1. Option-provided ALPN override.
715 : // 2. ALPN statically configured in the upstream TLS context.
716 : // 3. Option-provided ALPN fallback.
717 :
718 : // At this point in the code the ALPN has already been set (if present) to the value specified in
719 : // the TLS context. We've stored this value in parsed_alpn_protocols_ so we can check that to see
720 : // if it's already been set.
721 0 : bool has_alpn_defined = !parsed_alpn_protocols_.empty();
722 0 : if (options) {
723 : // ALPN override takes precedence over TLS context specified, so blindly overwrite it.
724 0 : has_alpn_defined |= parseAndSetAlpn(options->applicationProtocolListOverride(), *ssl_con);
725 0 : }
726 :
727 0 : if (options && !has_alpn_defined && !options->applicationProtocolFallback().empty()) {
728 : // If ALPN hasn't already been set (either through TLS context or override), use the fallback.
729 0 : parseAndSetAlpn(options->applicationProtocolFallback(), *ssl_con);
730 0 : }
731 :
732 0 : if (allow_renegotiation_) {
733 0 : SSL_set_renegotiate_mode(ssl_con.get(), ssl_renegotiate_freely);
734 0 : }
735 :
736 0 : SSL_set_enforce_rsa_key_usage(ssl_con.get(), enforce_rsa_key_usage_);
737 :
738 0 : if (max_session_keys_ > 0) {
739 0 : if (session_keys_single_use_) {
740 : // Stored single-use session keys, use write/write locks.
741 0 : absl::WriterMutexLock l(&session_keys_mu_);
742 0 : if (!session_keys_.empty()) {
743 : // Use the most recently stored session key, since it has the highest
744 : // probability of still being recognized/accepted by the server.
745 0 : SSL_SESSION* session = session_keys_.front().get();
746 0 : SSL_set_session(ssl_con.get(), session);
747 : // Remove single-use session key (TLS 1.3) after first use.
748 0 : if (SSL_SESSION_should_be_single_use(session)) {
749 0 : session_keys_.pop_front();
750 0 : }
751 0 : }
752 0 : } else {
753 : // Never stored single-use session keys, use read/write locks.
754 0 : absl::ReaderMutexLock l(&session_keys_mu_);
755 0 : if (!session_keys_.empty()) {
756 : // Use the most recently stored session key, since it has the highest
757 : // probability of still being recognized/accepted by the server.
758 0 : SSL_SESSION* session = session_keys_.front().get();
759 0 : SSL_set_session(ssl_con.get(), session);
760 0 : }
761 0 : }
762 0 : }
763 :
764 0 : return ssl_con;
765 0 : }
766 :
767 0 : int ClientContextImpl::newSessionKey(SSL_SESSION* session) {
768 : // In case we ever store single-use session key (TLS 1.3),
769 : // we need to switch to using write/write locks.
770 0 : if (SSL_SESSION_should_be_single_use(session)) {
771 0 : session_keys_single_use_ = true;
772 0 : }
773 0 : absl::WriterMutexLock l(&session_keys_mu_);
774 : // Evict oldest entries.
775 0 : while (session_keys_.size() >= max_session_keys_) {
776 0 : session_keys_.pop_back();
777 0 : }
778 : // Add new session key at the front of the queue, so that it's used first.
779 0 : session_keys_.push_front(bssl::UniquePtr<SSL_SESSION>(session));
780 0 : return 1; // Tell BoringSSL that we took ownership of the session.
781 0 : }
782 :
783 : ServerContextImpl::ServerContextImpl(Stats::Scope& scope,
784 : const Envoy::Ssl::ServerContextConfig& config,
785 : const std::vector<std::string>& server_names,
786 : TimeSource& time_source)
787 : : ContextImpl(scope, config, time_source), session_ticket_keys_(config.sessionTicketKeys()),
788 : ocsp_staple_policy_(config.ocspStaplePolicy()),
789 0 : full_scan_certs_on_sni_mismatch_(config.fullScanCertsOnSNIMismatch()) {
790 0 : if (config.tlsCertificates().empty() && !config.capabilities().provides_certificates) {
791 0 : throwEnvoyExceptionOrPanic("Server TlsCertificates must have a certificate specified");
792 0 : }
793 :
794 0 : for (auto& ctx : tls_contexts_) {
795 0 : if (ctx.cert_chain_ == nullptr) {
796 0 : continue;
797 0 : }
798 0 : bssl::UniquePtr<EVP_PKEY> public_key(X509_get_pubkey(ctx.cert_chain_.get()));
799 0 : const int pkey_id = EVP_PKEY_id(public_key.get());
800 : // Load DNS SAN entries and Subject Common Name as server name patterns after certificate
801 : // chain loaded, and populate ServerNamesMap which will be used to match SNI.
802 0 : has_rsa_ |= (pkey_id == EVP_PKEY_RSA);
803 0 : populateServerNamesMap(ctx, pkey_id);
804 0 : }
805 :
806 : // Compute the session context ID hash. We use all the certificate identities,
807 : // since we should have a common ID for session resumption no matter what cert
808 : // is used. We do this early because it can throw an EnvoyException.
809 0 : const SessionContextID session_id = generateHashForSessionContextId(server_names);
810 :
811 : // First, configure the base context for ClientHello interception.
812 : // TODO(htuch): replace with SSL_IDENTITY when we have this as a means to do multi-cert in
813 : // BoringSSL.
814 0 : if (!config.capabilities().provides_certificates) {
815 0 : SSL_CTX_set_select_certificate_cb(
816 0 : tls_contexts_[0].ssl_ctx_.get(),
817 0 : [](const SSL_CLIENT_HELLO* client_hello) -> ssl_select_cert_result_t {
818 0 : return static_cast<ServerContextImpl*>(
819 0 : SSL_CTX_get_app_data(SSL_get_SSL_CTX(client_hello->ssl)))
820 0 : ->selectTlsContext(client_hello);
821 0 : });
822 0 : }
823 :
824 0 : const auto tls_certificates = config.tlsCertificates();
825 :
826 0 : for (uint32_t i = 0; i < tls_certificates.size(); ++i) {
827 0 : auto& ctx = tls_contexts_[i];
828 0 : if (!config.capabilities().verifies_peer_certificates) {
829 0 : cert_validator_->addClientValidationContext(ctx.ssl_ctx_.get(),
830 0 : config.requireClientCertificate());
831 0 : }
832 :
833 0 : if (!parsed_alpn_protocols_.empty() && !config.capabilities().handles_alpn_selection) {
834 0 : SSL_CTX_set_alpn_select_cb(
835 0 : ctx.ssl_ctx_.get(),
836 0 : [](SSL*, const unsigned char** out, unsigned char* outlen, const unsigned char* in,
837 0 : unsigned int inlen, void* arg) -> int {
838 0 : return static_cast<ServerContextImpl*>(arg)->alpnSelectCallback(out, outlen, in, inlen);
839 0 : },
840 0 : this);
841 0 : }
842 :
843 : // If the handshaker handles session tickets natively, don't call
844 : // `SSL_CTX_set_tlsext_ticket_key_cb`.
845 0 : if (config.disableStatelessSessionResumption()) {
846 0 : SSL_CTX_set_options(ctx.ssl_ctx_.get(), SSL_OP_NO_TICKET);
847 0 : } else if (!session_ticket_keys_.empty() && !config.capabilities().handles_session_resumption) {
848 0 : SSL_CTX_set_tlsext_ticket_key_cb(
849 0 : ctx.ssl_ctx_.get(),
850 0 : [](SSL* ssl, uint8_t* key_name, uint8_t* iv, EVP_CIPHER_CTX* ctx, HMAC_CTX* hmac_ctx,
851 0 : int encrypt) -> int {
852 0 : ContextImpl* context_impl =
853 0 : static_cast<ContextImpl*>(SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)));
854 0 : ServerContextImpl* server_context_impl = dynamic_cast<ServerContextImpl*>(context_impl);
855 0 : RELEASE_ASSERT(server_context_impl != nullptr, ""); // for Coverity
856 0 : return server_context_impl->sessionTicketProcess(ssl, key_name, iv, ctx, hmac_ctx,
857 0 : encrypt);
858 0 : });
859 0 : }
860 :
861 0 : if (config.disableStatefulSessionResumption()) {
862 0 : SSL_CTX_set_session_cache_mode(ctx.ssl_ctx_.get(), SSL_SESS_CACHE_OFF);
863 0 : }
864 :
865 0 : if (config.sessionTimeout() && !config.capabilities().handles_session_resumption) {
866 0 : auto timeout = config.sessionTimeout().value().count();
867 0 : SSL_CTX_set_timeout(ctx.ssl_ctx_.get(), uint32_t(timeout));
868 0 : }
869 :
870 0 : int rc =
871 0 : SSL_CTX_set_session_id_context(ctx.ssl_ctx_.get(), session_id.data(), session_id.size());
872 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
873 :
874 0 : auto& ocsp_resp_bytes = tls_certificates[i].get().ocspStaple();
875 0 : if (ocsp_resp_bytes.empty()) {
876 0 : if (ctx.is_must_staple_) {
877 0 : throwEnvoyExceptionOrPanic("OCSP response is required for must-staple certificate");
878 0 : }
879 0 : if (ocsp_staple_policy_ == Ssl::ServerContextConfig::OcspStaplePolicy::MustStaple) {
880 0 : throwEnvoyExceptionOrPanic("Required OCSP response is missing from TLS context");
881 0 : }
882 0 : } else {
883 0 : auto response = std::make_unique<Ocsp::OcspResponseWrapper>(ocsp_resp_bytes, time_source_);
884 0 : if (!response->matchesCertificate(*ctx.cert_chain_)) {
885 0 : throwEnvoyExceptionOrPanic("OCSP response does not match its TLS certificate");
886 0 : }
887 0 : ctx.ocsp_response_ = std::move(response);
888 0 : }
889 0 : }
890 0 : }
891 :
892 0 : void ServerContextImpl::populateServerNamesMap(TlsContext& ctx, int pkey_id) {
893 0 : if (ctx.cert_chain_ == nullptr) {
894 0 : return;
895 0 : }
896 :
897 0 : auto populate = [&](const std::string& sn) {
898 0 : std::string sn_pattern = sn;
899 0 : if (absl::StartsWith(sn, "*.")) {
900 0 : sn_pattern = sn.substr(1);
901 0 : }
902 0 : PkeyTypesMap pkey_types_map;
903 : // Multiple certs with different key type are allowed for one server name pattern.
904 0 : auto sn_match = server_names_map_.try_emplace(sn_pattern, pkey_types_map).first;
905 0 : auto pt_match = sn_match->second.find(pkey_id);
906 0 : if (pt_match != sn_match->second.end()) {
907 : // When there are duplicate names, prefer the earlier one.
908 : //
909 : // If all of the SANs in a certificate are unused due to duplicates, it could be useful
910 : // to issue a warning, but that would require additional tracking that hasn't been
911 : // implemented.
912 0 : return;
913 0 : }
914 0 : sn_match->second.emplace(std::pair<int, std::reference_wrapper<TlsContext>>(pkey_id, ctx));
915 0 : };
916 :
917 0 : bssl::UniquePtr<GENERAL_NAMES> san_names(static_cast<GENERAL_NAMES*>(
918 0 : X509_get_ext_d2i(ctx.cert_chain_.get(), NID_subject_alt_name, nullptr, nullptr)));
919 0 : if (san_names != nullptr) {
920 0 : auto dns_sans = Utility::getSubjectAltNames(*ctx.cert_chain_, GEN_DNS);
921 : // https://www.rfc-editor.org/rfc/rfc6066#section-3
922 : // Currently, the only server names supported are DNS hostnames, so we
923 : // only save dns san entries to match SNI.
924 0 : for (const auto& san : dns_sans) {
925 0 : populate(san);
926 0 : }
927 0 : } else {
928 : // https://www.rfc-editor.org/rfc/rfc6125#section-6.4.4
929 : // As noted, a client MUST NOT seek a match for a reference identifier
930 : // of CN-ID if the presented identifiers include a DNS-ID, SRV-ID,
931 : // URI-ID, or any application-specific identifier types supported by the
932 : // client.
933 0 : X509_NAME* cert_subject = X509_get_subject_name(ctx.cert_chain_.get());
934 0 : const int cn_index = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, -1);
935 0 : if (cn_index >= 0) {
936 0 : X509_NAME_ENTRY* cn_entry = X509_NAME_get_entry(cert_subject, cn_index);
937 0 : if (cn_entry) {
938 0 : ASN1_STRING* cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry);
939 0 : if (ASN1_STRING_length(cn_asn1) > 0) {
940 0 : std::string subject_cn(reinterpret_cast<const char*>(ASN1_STRING_data(cn_asn1)),
941 0 : ASN1_STRING_length(cn_asn1));
942 0 : populate(subject_cn);
943 0 : }
944 0 : }
945 0 : }
946 0 : }
947 0 : }
948 :
949 : ServerContextImpl::SessionContextID
950 0 : ServerContextImpl::generateHashForSessionContextId(const std::vector<std::string>& server_names) {
951 0 : uint8_t hash_buffer[EVP_MAX_MD_SIZE];
952 0 : unsigned hash_length = 0;
953 :
954 0 : bssl::ScopedEVP_MD_CTX md;
955 :
956 0 : int rc = EVP_DigestInit(md.get(), EVP_sha256());
957 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
958 :
959 : // Hash the CommonName/SANs of all the server certificates. This makes sure that sessions can only
960 : // be resumed to certificate(s) for the same name(s), but allows resuming to unique certs in the
961 : // case that different Envoy instances each have their own certs. All certificates in a
962 : // ServerContextImpl context are hashed together, since they all constitute a match on a filter
963 : // chain for resumption purposes.
964 0 : if (!capabilities_.provides_certificates) {
965 0 : for (const auto& ctx : tls_contexts_) {
966 0 : X509* cert = SSL_CTX_get0_certificate(ctx.ssl_ctx_.get());
967 0 : RELEASE_ASSERT(cert != nullptr, "TLS context should have an active certificate");
968 0 : X509_NAME* cert_subject = X509_get_subject_name(cert);
969 0 : RELEASE_ASSERT(cert_subject != nullptr, "TLS certificate should have a subject");
970 :
971 0 : const int cn_index = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, -1);
972 0 : if (cn_index >= 0) {
973 0 : X509_NAME_ENTRY* cn_entry = X509_NAME_get_entry(cert_subject, cn_index);
974 0 : RELEASE_ASSERT(cn_entry != nullptr, "certificate subject CN should be present");
975 :
976 0 : ASN1_STRING* cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry);
977 0 : if (ASN1_STRING_length(cn_asn1) <= 0) {
978 0 : throwEnvoyExceptionOrPanic("Invalid TLS context has an empty subject CN");
979 0 : }
980 :
981 0 : rc = EVP_DigestUpdate(md.get(), ASN1_STRING_data(cn_asn1), ASN1_STRING_length(cn_asn1));
982 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
983 0 : }
984 :
985 0 : unsigned san_count = 0;
986 0 : bssl::UniquePtr<GENERAL_NAMES> san_names(static_cast<GENERAL_NAMES*>(
987 0 : X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)));
988 :
989 0 : if (san_names != nullptr) {
990 0 : for (const GENERAL_NAME* san : san_names.get()) {
991 0 : switch (san->type) {
992 0 : case GEN_IPADD:
993 0 : rc = EVP_DigestUpdate(md.get(), san->d.iPAddress->data, san->d.iPAddress->length);
994 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
995 0 : ++san_count;
996 0 : break;
997 0 : case GEN_DNS:
998 0 : rc = EVP_DigestUpdate(md.get(), ASN1_STRING_data(san->d.dNSName),
999 0 : ASN1_STRING_length(san->d.dNSName));
1000 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
1001 0 : ++san_count;
1002 0 : break;
1003 0 : case GEN_URI:
1004 0 : rc = EVP_DigestUpdate(md.get(), ASN1_STRING_data(san->d.uniformResourceIdentifier),
1005 0 : ASN1_STRING_length(san->d.uniformResourceIdentifier));
1006 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
1007 0 : ++san_count;
1008 0 : break;
1009 0 : }
1010 0 : }
1011 0 : }
1012 :
1013 : // It's possible that the certificate doesn't have a subject, but
1014 : // does have SANs. Make sure that we have one or the other.
1015 0 : if (cn_index < 0 && san_count == 0) {
1016 0 : throwEnvoyExceptionOrPanic("Invalid TLS context has neither subject CN nor SAN names");
1017 0 : }
1018 :
1019 0 : rc = X509_NAME_digest(X509_get_issuer_name(cert), EVP_sha256(), hash_buffer, &hash_length);
1020 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
1021 0 : RELEASE_ASSERT(hash_length == SHA256_DIGEST_LENGTH,
1022 0 : fmt::format("invalid SHA256 hash length {}", hash_length));
1023 :
1024 0 : rc = EVP_DigestUpdate(md.get(), hash_buffer, hash_length);
1025 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
1026 0 : }
1027 0 : }
1028 :
1029 0 : cert_validator_->updateDigestForSessionId(md, hash_buffer, hash_length);
1030 :
1031 : // Hash configured SNIs for this context, so that sessions cannot be resumed across different
1032 : // filter chains, even when using the same server certificate.
1033 0 : for (const auto& name : server_names) {
1034 0 : rc = EVP_DigestUpdate(md.get(), name.data(), name.size());
1035 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
1036 0 : }
1037 :
1038 0 : SessionContextID session_id;
1039 :
1040 : // Ensure that the output size of the hash we are using is no greater than
1041 : // TLS session ID length that we want to generate.
1042 0 : static_assert(session_id.size() == SHA256_DIGEST_LENGTH, "hash size mismatch");
1043 0 : static_assert(session_id.size() == SSL_MAX_SSL_SESSION_ID_LENGTH, "TLS session ID size mismatch");
1044 :
1045 0 : rc = EVP_DigestFinal(md.get(), session_id.data(), &hash_length);
1046 0 : RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
1047 0 : RELEASE_ASSERT(hash_length == session_id.size(),
1048 0 : "SHA256 hash length must match TLS Session ID size");
1049 :
1050 0 : return session_id;
1051 0 : }
1052 :
1053 : int ServerContextImpl::sessionTicketProcess(SSL*, uint8_t* key_name, uint8_t* iv,
1054 0 : EVP_CIPHER_CTX* ctx, HMAC_CTX* hmac_ctx, int encrypt) {
1055 0 : const EVP_MD* hmac = EVP_sha256();
1056 0 : const EVP_CIPHER* cipher = EVP_aes_256_cbc();
1057 :
1058 0 : if (encrypt == 1) {
1059 : // Encrypt
1060 0 : RELEASE_ASSERT(!session_ticket_keys_.empty(), "");
1061 : // TODO(ggreenway): validate in SDS that session_ticket_keys_ cannot be empty,
1062 : // or if we allow it to be emptied, reconfigure the context so this callback
1063 : // isn't set.
1064 :
1065 0 : const Envoy::Ssl::ServerContextConfig::SessionTicketKey& key = session_ticket_keys_.front();
1066 :
1067 0 : static_assert(std::tuple_size<decltype(key.name_)>::value == SSL_TICKET_KEY_NAME_LEN,
1068 0 : "Expected key.name length");
1069 0 : std::copy_n(key.name_.begin(), SSL_TICKET_KEY_NAME_LEN, key_name);
1070 :
1071 0 : const int rc = RAND_bytes(iv, EVP_CIPHER_iv_length(cipher));
1072 0 : ASSERT(rc);
1073 :
1074 : // This RELEASE_ASSERT is logically a static_assert, but we can't actually get
1075 : // EVP_CIPHER_key_length(cipher) at compile-time
1076 0 : RELEASE_ASSERT(key.aes_key_.size() == EVP_CIPHER_key_length(cipher), "");
1077 0 : if (!EVP_EncryptInit_ex(ctx, cipher, nullptr, key.aes_key_.data(), iv)) {
1078 0 : return -1;
1079 0 : }
1080 :
1081 0 : if (!HMAC_Init_ex(hmac_ctx, key.hmac_key_.data(), key.hmac_key_.size(), hmac, nullptr)) {
1082 0 : return -1;
1083 0 : }
1084 :
1085 0 : return 1; // success
1086 0 : } else {
1087 : // Decrypt
1088 0 : bool is_enc_key = true; // first element is the encryption key
1089 0 : for (const Envoy::Ssl::ServerContextConfig::SessionTicketKey& key : session_ticket_keys_) {
1090 0 : static_assert(std::tuple_size<decltype(key.name_)>::value == SSL_TICKET_KEY_NAME_LEN,
1091 0 : "Expected key.name length");
1092 0 : if (std::equal(key.name_.begin(), key.name_.end(), key_name)) {
1093 0 : if (!HMAC_Init_ex(hmac_ctx, key.hmac_key_.data(), key.hmac_key_.size(), hmac, nullptr)) {
1094 0 : return -1;
1095 0 : }
1096 :
1097 0 : RELEASE_ASSERT(key.aes_key_.size() == EVP_CIPHER_key_length(cipher), "");
1098 0 : if (!EVP_DecryptInit_ex(ctx, cipher, nullptr, key.aes_key_.data(), iv)) {
1099 0 : return -1;
1100 0 : }
1101 :
1102 : // If our current encryption was not the decryption key, renew
1103 0 : return is_enc_key ? 1 // success; do not renew
1104 0 : : 2; // success: renew key
1105 0 : }
1106 0 : is_enc_key = false;
1107 0 : }
1108 :
1109 0 : return 0; // decryption failed
1110 0 : }
1111 0 : }
1112 :
1113 0 : bool ServerContextImpl::isClientEcdsaCapable(const SSL_CLIENT_HELLO* ssl_client_hello) {
1114 0 : CBS client_hello;
1115 0 : CBS_init(&client_hello, ssl_client_hello->client_hello, ssl_client_hello->client_hello_len);
1116 :
1117 : // This is the TLSv1.3 case (TLSv1.2 on the wire and the supported_versions extensions present).
1118 : // We just need to look at signature algorithms.
1119 0 : const uint16_t client_version = ssl_client_hello->version;
1120 0 : if (client_version == TLS1_2_VERSION && tls_max_version_ == TLS1_3_VERSION) {
1121 : // If the supported_versions extension is found then we assume that the client is competent
1122 : // enough that just checking the signature_algorithms is sufficient.
1123 0 : const uint8_t* supported_versions_data;
1124 0 : size_t supported_versions_len;
1125 0 : if (SSL_early_callback_ctx_extension_get(ssl_client_hello, TLSEXT_TYPE_supported_versions,
1126 0 : &supported_versions_data, &supported_versions_len)) {
1127 0 : const uint8_t* signature_algorithms_data;
1128 0 : size_t signature_algorithms_len;
1129 0 : if (SSL_early_callback_ctx_extension_get(ssl_client_hello, TLSEXT_TYPE_signature_algorithms,
1130 0 : &signature_algorithms_data,
1131 0 : &signature_algorithms_len)) {
1132 0 : CBS signature_algorithms_ext, signature_algorithms;
1133 0 : CBS_init(&signature_algorithms_ext, signature_algorithms_data, signature_algorithms_len);
1134 0 : if (!CBS_get_u16_length_prefixed(&signature_algorithms_ext, &signature_algorithms) ||
1135 0 : CBS_len(&signature_algorithms_ext) != 0) {
1136 0 : return false;
1137 0 : }
1138 0 : if (cbsContainsU16(signature_algorithms, SSL_SIGN_ECDSA_SECP256R1_SHA256)) {
1139 0 : return true;
1140 0 : }
1141 0 : }
1142 :
1143 0 : return false;
1144 0 : }
1145 0 : }
1146 :
1147 : // Otherwise we are < TLSv1.3 and need to look at both the curves in the supported_groups for
1148 : // ECDSA and also for a compatible cipher suite. https://tools.ietf.org/html/rfc4492#section-5.1.1
1149 0 : const uint8_t* curvelist_data;
1150 0 : size_t curvelist_len;
1151 0 : if (!SSL_early_callback_ctx_extension_get(ssl_client_hello, TLSEXT_TYPE_supported_groups,
1152 0 : &curvelist_data, &curvelist_len)) {
1153 0 : return false;
1154 0 : }
1155 :
1156 0 : CBS curvelist;
1157 0 : CBS_init(&curvelist, curvelist_data, curvelist_len);
1158 :
1159 : // We only support P256 ECDSA curves today.
1160 0 : if (!cbsContainsU16(curvelist, SSL_CURVE_SECP256R1)) {
1161 0 : return false;
1162 0 : }
1163 :
1164 : // The client must have offered an ECDSA ciphersuite that we like.
1165 0 : CBS cipher_suites;
1166 0 : CBS_init(&cipher_suites, ssl_client_hello->cipher_suites, ssl_client_hello->cipher_suites_len);
1167 :
1168 0 : while (CBS_len(&cipher_suites) > 0) {
1169 0 : uint16_t cipher_id;
1170 0 : if (!CBS_get_u16(&cipher_suites, &cipher_id)) {
1171 0 : return false;
1172 0 : }
1173 : // All tls_context_ share the same set of enabled ciphers, so we can just look at the base
1174 : // context.
1175 0 : if (tls_contexts_[0].isCipherEnabled(cipher_id, client_version)) {
1176 0 : return true;
1177 0 : }
1178 0 : }
1179 :
1180 0 : return false;
1181 0 : }
1182 :
1183 0 : bool ServerContextImpl::isClientOcspCapable(const SSL_CLIENT_HELLO* ssl_client_hello) {
1184 0 : const uint8_t* status_request_data;
1185 0 : size_t status_request_len;
1186 0 : if (SSL_early_callback_ctx_extension_get(ssl_client_hello, TLSEXT_TYPE_status_request,
1187 0 : &status_request_data, &status_request_len)) {
1188 0 : return true;
1189 0 : }
1190 :
1191 0 : return false;
1192 0 : }
1193 :
1194 : OcspStapleAction ServerContextImpl::ocspStapleAction(const TlsContext& ctx,
1195 0 : bool client_ocsp_capable) {
1196 0 : if (!client_ocsp_capable) {
1197 0 : return OcspStapleAction::ClientNotCapable;
1198 0 : }
1199 :
1200 0 : auto& response = ctx.ocsp_response_;
1201 :
1202 0 : auto policy = ocsp_staple_policy_;
1203 0 : if (ctx.is_must_staple_) {
1204 : // The certificate has the must-staple extension, so upgrade the policy to match.
1205 0 : policy = Ssl::ServerContextConfig::OcspStaplePolicy::MustStaple;
1206 0 : }
1207 :
1208 0 : const bool valid_response = response && !response->isExpired();
1209 :
1210 0 : switch (policy) {
1211 0 : case Ssl::ServerContextConfig::OcspStaplePolicy::LenientStapling:
1212 0 : if (!valid_response) {
1213 0 : return OcspStapleAction::NoStaple;
1214 0 : }
1215 0 : return OcspStapleAction::Staple;
1216 :
1217 0 : case Ssl::ServerContextConfig::OcspStaplePolicy::StrictStapling:
1218 0 : if (valid_response) {
1219 0 : return OcspStapleAction::Staple;
1220 0 : }
1221 0 : if (response) {
1222 : // Expired response.
1223 0 : return OcspStapleAction::Fail;
1224 0 : }
1225 0 : return OcspStapleAction::NoStaple;
1226 :
1227 0 : case Ssl::ServerContextConfig::OcspStaplePolicy::MustStaple:
1228 0 : if (!valid_response) {
1229 0 : return OcspStapleAction::Fail;
1230 0 : }
1231 0 : return OcspStapleAction::Staple;
1232 0 : }
1233 0 : PANIC_DUE_TO_CORRUPT_ENUM;
1234 0 : }
1235 :
1236 : enum ssl_select_cert_result_t
1237 0 : ServerContextImpl::selectTlsContext(const SSL_CLIENT_HELLO* ssl_client_hello) {
1238 0 : const bool client_ecdsa_capable = isClientEcdsaCapable(ssl_client_hello);
1239 0 : const bool client_ocsp_capable = isClientOcspCapable(ssl_client_hello);
1240 0 : absl::string_view sni = absl::NullSafeStringView(
1241 0 : SSL_get_servername(ssl_client_hello->ssl, TLSEXT_NAMETYPE_host_name));
1242 :
1243 : // selected_ctx represents the final selected certificate, it should meet all requirements or pick
1244 : // a candidate
1245 0 : const TlsContext* selected_ctx = nullptr;
1246 0 : const TlsContext* candidate_ctx = nullptr;
1247 0 : OcspStapleAction ocsp_staple_action;
1248 :
1249 0 : auto selected = [&](const TlsContext& ctx) -> bool {
1250 0 : auto action = ocspStapleAction(ctx, client_ocsp_capable);
1251 0 : if (action == OcspStapleAction::Fail) {
1252 : // The selected ctx must adhere to OCSP policy
1253 0 : return false;
1254 0 : }
1255 :
1256 0 : if (client_ecdsa_capable == ctx.is_ecdsa_) {
1257 0 : selected_ctx = &ctx;
1258 0 : ocsp_staple_action = action;
1259 0 : return true;
1260 0 : }
1261 :
1262 0 : if (client_ecdsa_capable && !ctx.is_ecdsa_ && candidate_ctx == nullptr) {
1263 : // ECDSA cert is preferred if client is ECDSA capable, so RSA cert is marked as a candidate,
1264 : // searching will continue until exhausting all certs or find a exact match.
1265 0 : candidate_ctx = &ctx;
1266 0 : ocsp_staple_action = action;
1267 0 : return false;
1268 0 : }
1269 :
1270 0 : return false;
1271 0 : };
1272 :
1273 0 : auto select_from_map = [this, &selected](absl::string_view server_name) -> void {
1274 0 : auto it = server_names_map_.find(server_name);
1275 0 : if (it == server_names_map_.end()) {
1276 0 : return;
1277 0 : }
1278 0 : const auto& pkey_types_map = it->second;
1279 0 : for (const auto& entry : pkey_types_map) {
1280 0 : if (selected(entry.second.get())) {
1281 0 : break;
1282 0 : }
1283 0 : }
1284 0 : };
1285 :
1286 0 : auto tail_select = [&](bool go_to_next_phase) {
1287 0 : if (selected_ctx == nullptr) {
1288 0 : selected_ctx = candidate_ctx;
1289 0 : }
1290 :
1291 0 : if (selected_ctx == nullptr && !go_to_next_phase) {
1292 0 : selected_ctx = &tls_contexts_[0];
1293 0 : ocsp_staple_action = ocspStapleAction(*selected_ctx, client_ocsp_capable);
1294 0 : }
1295 0 : };
1296 :
1297 : // Select cert based on SNI if SNI is provided by client.
1298 0 : if (!sni.empty()) {
1299 : // Match on exact server name, i.e. "www.example.com" for "www.example.com".
1300 0 : select_from_map(sni);
1301 0 : tail_select(true);
1302 :
1303 0 : if (selected_ctx == nullptr) {
1304 : // Match on wildcard domain, i.e. ".example.com" for "www.example.com".
1305 : // https://datatracker.ietf.org/doc/html/rfc6125#section-6.4
1306 0 : size_t pos = sni.find('.', 1);
1307 0 : if (pos < sni.size() - 1 && pos != std::string::npos) {
1308 0 : absl::string_view wildcard = sni.substr(pos);
1309 0 : select_from_map(wildcard);
1310 0 : }
1311 0 : }
1312 0 : tail_select(full_scan_certs_on_sni_mismatch_);
1313 0 : }
1314 : // Full scan certs if SNI is not provided by client;
1315 : // Full scan certs if client provides SNI but no cert matches to it,
1316 : // it requires full_scan_certs_on_sni_mismatch is enabled.
1317 0 : if (selected_ctx == nullptr) {
1318 0 : candidate_ctx = nullptr;
1319 : // Skip loop when there is no cert compatible to key type
1320 0 : if (client_ecdsa_capable || (!client_ecdsa_capable && has_rsa_)) {
1321 0 : for (const auto& ctx : tls_contexts_) {
1322 0 : if (selected(ctx)) {
1323 0 : break;
1324 0 : }
1325 0 : }
1326 0 : }
1327 0 : tail_select(false);
1328 0 : }
1329 :
1330 : // Apply the selected context. This must be done before OCSP stapling below
1331 : // since applying the context can remove the previously-set OCSP response.
1332 : // This will only return NULL if memory allocation fails.
1333 0 : RELEASE_ASSERT(SSL_set_SSL_CTX(ssl_client_hello->ssl, selected_ctx->ssl_ctx_.get()) != nullptr,
1334 0 : "");
1335 :
1336 0 : if (client_ocsp_capable) {
1337 0 : stats_.ocsp_staple_requests_.inc();
1338 0 : }
1339 :
1340 0 : switch (ocsp_staple_action) {
1341 0 : case OcspStapleAction::Staple: {
1342 : // We avoid setting the OCSP response if the client didn't request it, but doing so is safe.
1343 0 : RELEASE_ASSERT(selected_ctx->ocsp_response_,
1344 0 : "OCSP response must be present under OcspStapleAction::Staple");
1345 0 : auto& resp_bytes = selected_ctx->ocsp_response_->rawBytes();
1346 0 : int rc = SSL_set_ocsp_response(ssl_client_hello->ssl, resp_bytes.data(), resp_bytes.size());
1347 0 : RELEASE_ASSERT(rc != 0, "");
1348 0 : stats_.ocsp_staple_responses_.inc();
1349 0 : } break;
1350 0 : case OcspStapleAction::NoStaple:
1351 0 : stats_.ocsp_staple_omitted_.inc();
1352 0 : break;
1353 0 : case OcspStapleAction::Fail:
1354 0 : stats_.ocsp_staple_failed_.inc();
1355 0 : return ssl_select_cert_error;
1356 0 : case OcspStapleAction::ClientNotCapable:
1357 0 : break;
1358 0 : }
1359 :
1360 0 : return ssl_select_cert_success;
1361 0 : }
1362 :
1363 0 : bool TlsContext::isCipherEnabled(uint16_t cipher_id, uint16_t client_version) {
1364 0 : const SSL_CIPHER* c = SSL_get_cipher_by_value(cipher_id);
1365 0 : if (c == nullptr) {
1366 0 : return false;
1367 0 : }
1368 : // Skip TLS 1.2 only ciphersuites unless the client supports it.
1369 0 : if (SSL_CIPHER_get_min_version(c) > client_version) {
1370 0 : return false;
1371 0 : }
1372 0 : if (SSL_CIPHER_get_auth_nid(c) != NID_auth_ecdsa) {
1373 0 : return false;
1374 0 : }
1375 0 : for (const SSL_CIPHER* our_c : SSL_CTX_get_ciphers(ssl_ctx_.get())) {
1376 0 : if (SSL_CIPHER_get_id(our_c) == SSL_CIPHER_get_id(c)) {
1377 0 : return true;
1378 0 : }
1379 0 : }
1380 0 : return false;
1381 0 : }
1382 :
1383 : ValidationResults ContextImpl::customVerifyCertChainForQuic(
1384 : STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server,
1385 : const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options,
1386 0 : const CertValidator::ExtraValidationContext& validation_context, const std::string& host_name) {
1387 0 : ASSERT(!tls_contexts_.empty());
1388 : // It doesn't matter which SSL context is used, because they share the same cert validation
1389 : // config.
1390 0 : SSL_CTX* ssl_ctx = tls_contexts_[0].ssl_ctx_.get();
1391 0 : if (SSL_CTX_get_verify_mode(ssl_ctx) == SSL_VERIFY_NONE) {
1392 : // Skip validation if the TLS is configured SSL_VERIFY_NONE.
1393 0 : return {ValidationResults::ValidationStatus::Successful,
1394 0 : Envoy::Ssl::ClientValidationStatus::NotValidated, absl::nullopt, absl::nullopt};
1395 0 : }
1396 0 : ValidationResults result =
1397 0 : cert_validator_->doVerifyCertChain(cert_chain, std::move(callback), transport_socket_options,
1398 0 : *ssl_ctx, validation_context, is_server, host_name);
1399 0 : return result;
1400 0 : }
1401 :
1402 0 : void TlsContext::loadCertificateChain(const std::string& data, const std::string& data_path) {
1403 0 : cert_chain_file_path_ = data_path;
1404 0 : bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
1405 0 : RELEASE_ASSERT(bio != nullptr, "");
1406 0 : cert_chain_.reset(PEM_read_bio_X509_AUX(bio.get(), nullptr, nullptr, nullptr));
1407 0 : if (cert_chain_ == nullptr || !SSL_CTX_use_certificate(ssl_ctx_.get(), cert_chain_.get())) {
1408 0 : logSslErrorChain();
1409 0 : throwEnvoyExceptionOrPanic(
1410 0 : absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
1411 0 : }
1412 : // Read rest of the certificate chain.
1413 0 : while (true) {
1414 0 : bssl::UniquePtr<X509> cert(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
1415 0 : if (cert == nullptr) {
1416 0 : break;
1417 0 : }
1418 0 : if (!SSL_CTX_add_extra_chain_cert(ssl_ctx_.get(), cert.get())) {
1419 0 : throwEnvoyExceptionOrPanic(
1420 0 : absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
1421 0 : }
1422 : // SSL_CTX_add_extra_chain_cert() takes ownership.
1423 0 : cert.release();
1424 0 : }
1425 : // Check for EOF.
1426 0 : const uint32_t err = ERR_peek_last_error();
1427 0 : if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
1428 0 : ERR_clear_error();
1429 0 : } else {
1430 0 : throwEnvoyExceptionOrPanic(
1431 0 : absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
1432 0 : }
1433 0 : }
1434 :
1435 : void TlsContext::loadPrivateKey(const std::string& data, const std::string& data_path,
1436 0 : const std::string& password) {
1437 0 : bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
1438 0 : RELEASE_ASSERT(bio != nullptr, "");
1439 0 : bssl::UniquePtr<EVP_PKEY> pkey(
1440 0 : PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr,
1441 0 : !password.empty() ? const_cast<char*>(password.c_str()) : nullptr));
1442 :
1443 0 : if (pkey == nullptr || !SSL_CTX_use_PrivateKey(ssl_ctx_.get(), pkey.get())) {
1444 0 : throwEnvoyExceptionOrPanic(fmt::format("Failed to load private key from {}, Cause: {}",
1445 0 : data_path,
1446 0 : Utility::getLastCryptoError().value_or("unknown")));
1447 0 : }
1448 :
1449 0 : checkPrivateKey(pkey, data_path);
1450 0 : }
1451 :
1452 : void TlsContext::loadPkcs12(const std::string& data, const std::string& data_path,
1453 0 : const std::string& password) {
1454 0 : cert_chain_file_path_ = data_path;
1455 0 : bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
1456 0 : RELEASE_ASSERT(bio != nullptr, "");
1457 0 : bssl::UniquePtr<PKCS12> pkcs12(d2i_PKCS12_bio(bio.get(), nullptr));
1458 :
1459 0 : EVP_PKEY* temp_private_key = nullptr;
1460 0 : X509* temp_cert = nullptr;
1461 0 : STACK_OF(X509)* temp_ca_certs = nullptr;
1462 0 : if (pkcs12 == nullptr ||
1463 0 : !PKCS12_parse(pkcs12.get(), !password.empty() ? const_cast<char*>(password.c_str()) : nullptr,
1464 0 : &temp_private_key, &temp_cert, &temp_ca_certs)) {
1465 0 : logSslErrorChain();
1466 0 : throwEnvoyExceptionOrPanic(absl::StrCat("Failed to load pkcs12 from ", data_path));
1467 0 : }
1468 0 : cert_chain_.reset(temp_cert);
1469 0 : bssl::UniquePtr<EVP_PKEY> pkey(temp_private_key);
1470 0 : bssl::UniquePtr<STACK_OF(X509)> ca_certificates(temp_ca_certs);
1471 0 : if (ca_certificates != nullptr) {
1472 0 : X509* ca_cert = nullptr;
1473 0 : while ((ca_cert = sk_X509_pop(ca_certificates.get())) != nullptr) {
1474 : // This transfers ownership to ssl_ctx therefore ca_cert does not need to be freed.
1475 0 : SSL_CTX_add_extra_chain_cert(ssl_ctx_.get(), ca_cert);
1476 0 : }
1477 0 : }
1478 0 : if (!SSL_CTX_use_certificate(ssl_ctx_.get(), cert_chain_.get())) {
1479 0 : logSslErrorChain();
1480 0 : throwEnvoyExceptionOrPanic(absl::StrCat("Failed to load certificate from ", data_path));
1481 0 : }
1482 0 : if (temp_private_key == nullptr || !SSL_CTX_use_PrivateKey(ssl_ctx_.get(), pkey.get())) {
1483 0 : throwEnvoyExceptionOrPanic(fmt::format("Failed to load private key from {}, Cause: {}",
1484 0 : data_path,
1485 0 : Utility::getLastCryptoError().value_or("unknown")));
1486 0 : }
1487 :
1488 0 : checkPrivateKey(pkey, data_path);
1489 0 : }
1490 :
1491 : void TlsContext::checkPrivateKey(const bssl::UniquePtr<EVP_PKEY>& pkey,
1492 0 : const std::string& key_path) {
1493 : #ifdef BORINGSSL_FIPS
1494 : // Verify that private keys are passing FIPS pairwise consistency tests.
1495 : switch (EVP_PKEY_id(pkey.get())) {
1496 : case EVP_PKEY_EC: {
1497 : const EC_KEY* ecdsa_private_key = EVP_PKEY_get0_EC_KEY(pkey.get());
1498 : if (!EC_KEY_check_fips(ecdsa_private_key)) {
1499 : throwEnvoyExceptionOrPanic(fmt::format("Failed to load private key from {}, ECDSA key failed "
1500 : "pairwise consistency test required in FIPS mode",
1501 : key_path));
1502 : }
1503 : } break;
1504 : case EVP_PKEY_RSA: {
1505 : RSA* rsa_private_key = EVP_PKEY_get0_RSA(pkey.get());
1506 : if (!RSA_check_fips(rsa_private_key)) {
1507 : throwEnvoyExceptionOrPanic(fmt::format("Failed to load private key from {}, RSA key failed "
1508 : "pairwise consistency test required in FIPS mode",
1509 : key_path));
1510 : }
1511 : } break;
1512 : }
1513 : #else
1514 0 : UNREFERENCED_PARAMETER(pkey);
1515 0 : UNREFERENCED_PARAMETER(key_path);
1516 0 : #endif
1517 0 : }
1518 :
1519 : } // namespace Tls
1520 : } // namespace TransportSockets
1521 : } // namespace Extensions
1522 : } // namespace Envoy
|