Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/tls/context_impl.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/common/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/common/tls/cert_validator/factory.h"
30
#include "source/common/tls/stats.h"
31
#include "source/common/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 {
44
45
0
void logSslErrorChain() {
46
0
  while (uint64_t err = ERR_get_error()) {
47
0
    ENVOY_LOG_MISC(debug, "SSL error: {}:{}:{}:{}", err,
48
0
                   absl::NullSafeStringView(ERR_lib_error_string(err)),
49
0
                   absl::NullSafeStringView(ERR_func_error_string(err)), ERR_GET_REASON(err),
50
0
                   absl::NullSafeStringView(ERR_reason_error_string(err)));
51
0
  }
52
0
}
53
54
} // namespace
55
56
namespace Extensions {
57
namespace TransportSockets {
58
namespace Tls {
59
60
0
int ContextImpl::sslExtendedSocketInfoIndex() {
61
0
  CONSTRUCT_ON_FIRST_USE(int, []() -> int {
62
0
    int ssl_context_index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
63
0
    RELEASE_ASSERT(ssl_context_index >= 0, "");
64
0
    return ssl_context_index;
65
0
  }());
66
0
}
67
68
ContextImpl::ContextImpl(Stats::Scope& scope, const Envoy::Ssl::ContextConfig& config,
69
                         Server::Configuration::CommonFactoryContext& factory_context,
70
                         Ssl::ContextAdditionalInitFunc additional_init,
71
                         absl::Status& creation_status)
72
    : scope_(scope), stats_(generateSslStats(scope)), factory_context_(factory_context),
73
      tls_max_version_(config.maxProtocolVersion()),
74
      stat_name_set_(scope.symbolTable().makeSet("TransportSockets::Tls")),
75
      unknown_ssl_cipher_(stat_name_set_->add("unknown_ssl_cipher")),
76
      unknown_ssl_curve_(stat_name_set_->add("unknown_ssl_curve")),
77
      unknown_ssl_algorithm_(stat_name_set_->add("unknown_ssl_algorithm")),
78
      unknown_ssl_version_(stat_name_set_->add("unknown_ssl_version")),
79
      ssl_ciphers_(stat_name_set_->add("ssl.ciphers")),
80
      ssl_versions_(stat_name_set_->add("ssl.versions")),
81
      ssl_curves_(stat_name_set_->add("ssl.curves")),
82
      ssl_sigalgs_(stat_name_set_->add("ssl.sigalgs")), capabilities_(config.capabilities()),
83
0
      tls_keylog_local_(config.tlsKeyLogLocal()), tls_keylog_remote_(config.tlsKeyLogRemote()) {
84
85
0
  auto cert_validator_name = getCertValidatorName(config.certificateValidationContext());
86
0
  auto cert_validator_factory =
87
0
      Registry::FactoryRegistry<CertValidatorFactory>::getFactory(cert_validator_name);
88
89
0
  if (!cert_validator_factory) {
90
0
    creation_status = absl::InvalidArgumentError(
91
0
        absl::StrCat("Failed to get certificate validator factory for ", cert_validator_name));
92
0
    return;
93
0
  }
94
95
0
  cert_validator_ = cert_validator_factory->createCertValidator(
96
0
      config.certificateValidationContext(), stats_, factory_context_);
97
98
0
  const auto tls_certificates = config.tlsCertificates();
99
0
  tls_contexts_.resize(std::max(static_cast<size_t>(1), tls_certificates.size()));
100
101
0
  std::vector<SSL_CTX*> ssl_contexts(tls_contexts_.size());
102
0
  for (size_t i = 0; i < tls_contexts_.size(); i++) {
103
0
    auto& ctx = tls_contexts_[i];
104
0
    ctx.ssl_ctx_.reset(SSL_CTX_new(TLS_method()));
105
0
    ssl_contexts[i] = ctx.ssl_ctx_.get();
106
107
0
    int rc = SSL_CTX_set_app_data(ctx.ssl_ctx_.get(), this);
108
0
    RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
109
110
0
    rc = SSL_CTX_set_min_proto_version(ctx.ssl_ctx_.get(), config.minProtocolVersion());
111
0
    RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
112
113
0
    rc = SSL_CTX_set_max_proto_version(ctx.ssl_ctx_.get(), config.maxProtocolVersion());
114
0
    RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
115
116
0
    if (!capabilities_.provides_ciphers_and_curves &&
117
0
        !SSL_CTX_set_strict_cipher_list(ctx.ssl_ctx_.get(), config.cipherSuites().c_str())) {
118
      // Break up a set of ciphers into each individual cipher and try them each individually in
119
      // order to attempt to log which specific one failed. Example of config.cipherSuites():
120
      // "-ALL:[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]:ECDHE-ECDSA-AES128-SHA".
121
      //
122
      // "-" is both an operator when in the leading position of a token (-ALL: don't allow this
123
      // cipher), and the common separator in names (ECDHE-ECDSA-AES128-GCM-SHA256). Don't split on
124
      // it because it will separate pieces of the same cipher. When it is a leading character, it
125
      // is removed below.
126
0
      std::vector<absl::string_view> ciphers =
127
0
          StringUtil::splitToken(config.cipherSuites(), ":+![|]", false);
128
0
      std::vector<std::string> bad_ciphers;
129
0
      for (const auto& cipher : ciphers) {
130
0
        std::string cipher_str(cipher);
131
132
0
        if (absl::StartsWith(cipher_str, "-")) {
133
0
          cipher_str.erase(cipher_str.begin());
134
0
        }
135
136
0
        if (!SSL_CTX_set_strict_cipher_list(ctx.ssl_ctx_.get(), cipher_str.c_str())) {
137
0
          bad_ciphers.push_back(cipher_str);
138
0
        }
139
0
      }
140
0
      creation_status = absl::InvalidArgumentError(
141
0
          fmt::format("Failed to initialize cipher suites {}. The following "
142
0
                      "ciphers were rejected when tried individually: {}",
143
0
                      config.cipherSuites(), absl::StrJoin(bad_ciphers, ", ")));
144
0
      return;
145
0
    }
146
147
0
    if (!capabilities_.provides_ciphers_and_curves &&
148
0
        !SSL_CTX_set1_curves_list(ctx.ssl_ctx_.get(), config.ecdhCurves().c_str())) {
149
0
      creation_status = absl::InvalidArgumentError(
150
0
          absl::StrCat("Failed to initialize ECDH curves ", config.ecdhCurves()));
151
0
      return;
152
0
    }
153
154
    // Set signature algorithms if given, otherwise fall back to BoringSSL defaults.
155
0
    if (!capabilities_.provides_sigalgs && !config.signatureAlgorithms().empty()) {
156
0
      if (!SSL_CTX_set1_sigalgs_list(ctx.ssl_ctx_.get(), config.signatureAlgorithms().c_str())) {
157
0
        creation_status = absl::InvalidArgumentError(absl::StrCat(
158
0
            "Failed to initialize TLS signature algorithms ", config.signatureAlgorithms()));
159
0
        return;
160
0
      }
161
0
    }
162
0
  }
163
164
0
  auto verify_mode_or_error = cert_validator_->initializeSslContexts(
165
0
      ssl_contexts, config.capabilities().provides_certificates);
166
0
  SET_AND_RETURN_IF_NOT_OK(verify_mode_or_error.status(), creation_status);
167
0
  auto verify_mode = verify_mode_or_error.value();
168
169
0
  if (!capabilities_.verifies_peer_certificates) {
170
0
    for (auto ctx : ssl_contexts) {
171
0
      if (verify_mode != SSL_VERIFY_NONE) {
172
        // TODO(danzh) Envoy's use of SSL_VERIFY_NONE does not quite match the actual semantics as
173
        // a client. As a client, SSL_VERIFY_NONE means to verify the certificate (which will fail
174
        // without trust anchors), save the result in the session ticket, but otherwise continue
175
        // with the handshake. But Envoy actually wants it to accept all certificates. The
176
        // disadvantage of using SSL_VERIFY_NONE is that it records the verify_result, which Envoy
177
        // never queries but gets saved in session tickets, and tries to find an anchor that isn't
178
        // there. And also it differs from server side behavior of SSL_VERIFY_NONE which won't
179
        // even request client certs. So, instead, we should configure a callback to skip
180
        // validation and always supply the callback to boring SSL.
181
0
        SSL_CTX_set_custom_verify(ctx, verify_mode, customVerifyCallback);
182
0
        SSL_CTX_set_reverify_on_resume(ctx, /*reverify_on_resume_enabled)=*/1);
183
0
      }
184
0
    }
185
0
  }
186
187
#ifdef BORINGSSL_FIPS
188
  if (!capabilities_.is_fips_compliant) {
189
    creation_status = absl::InvalidArgumentError(
190
        "Can't load a FIPS noncompliant custom handshaker while running in FIPS compliant mode.");
191
    return;
192
  }
193
#endif
194
195
0
  if (!capabilities_.provides_certificates) {
196
0
    for (uint32_t i = 0; i < tls_certificates.size(); ++i) {
197
0
      auto& ctx = tls_contexts_[i];
198
      // Load certificate chain.
199
0
      const auto& tls_certificate = tls_certificates[i].get();
200
0
      if (!tls_certificate.pkcs12().empty()) {
201
0
        creation_status = ctx.loadPkcs12(tls_certificate.pkcs12(), tls_certificate.pkcs12Path(),
202
0
                                         tls_certificate.password());
203
0
      } else {
204
0
        creation_status = ctx.loadCertificateChain(tls_certificate.certificateChain(),
205
0
                                                   tls_certificate.certificateChainPath());
206
0
      }
207
0
      if (!creation_status.ok()) {
208
0
        return;
209
0
      }
210
      // The must staple extension means the certificate promises to carry
211
      // with it an OCSP staple. https://tools.ietf.org/html/rfc7633#section-6
212
0
      constexpr absl::string_view tls_feature_ext = "1.3.6.1.5.5.7.1.24";
213
0
      constexpr absl::string_view must_staple_ext_value = "\x30\x3\x02\x01\x05";
214
0
      auto must_staple = Utility::getCertificateExtensionValue(*ctx.cert_chain_, tls_feature_ext);
215
0
      if (must_staple == must_staple_ext_value) {
216
0
        ctx.is_must_staple_ = true;
217
0
      }
218
219
0
      bssl::UniquePtr<EVP_PKEY> public_key(X509_get_pubkey(ctx.cert_chain_.get()));
220
0
      const int pkey_id = EVP_PKEY_id(public_key.get());
221
0
      ctx.is_ecdsa_ = pkey_id == EVP_PKEY_EC;
222
0
      switch (pkey_id) {
223
0
      case EVP_PKEY_EC: {
224
        // We only support P-256 ECDSA today.
225
0
        const EC_KEY* ecdsa_public_key = EVP_PKEY_get0_EC_KEY(public_key.get());
226
        // Since we checked the key type above, this should be valid.
227
0
        ASSERT(ecdsa_public_key != nullptr);
228
0
        const EC_GROUP* ecdsa_group = EC_KEY_get0_group(ecdsa_public_key);
229
0
        if (ecdsa_group == nullptr ||
230
0
            EC_GROUP_get_curve_name(ecdsa_group) != NID_X9_62_prime256v1) {
231
0
          creation_status = absl::InvalidArgumentError(
232
0
              fmt::format("Failed to load certificate chain from {}, only P-256 "
233
0
                          "ECDSA certificates are supported",
234
0
                          ctx.cert_chain_file_path_));
235
0
          return;
236
0
        }
237
0
        ctx.is_ecdsa_ = true;
238
0
      } break;
239
0
      case EVP_PKEY_RSA: {
240
        // We require RSA certificates with 2048-bit or larger keys.
241
0
        const RSA* rsa_public_key = EVP_PKEY_get0_RSA(public_key.get());
242
        // Since we checked the key type above, this should be valid.
243
0
        ASSERT(rsa_public_key != nullptr);
244
0
        const unsigned rsa_key_length = RSA_bits(rsa_public_key);
245
#ifdef BORINGSSL_FIPS
246
        if (rsa_key_length != 2048 && rsa_key_length != 3072 && rsa_key_length != 4096) {
247
          creation_status = absl::InvalidArgumentError(
248
              fmt::format("Failed to load certificate chain from {}, only RSA certificates with "
249
                          "2048-bit, 3072-bit or 4096-bit keys are supported in FIPS mode",
250
                          ctx.cert_chain_file_path_));
251
          return;
252
        }
253
#else
254
0
        if (rsa_key_length < 2048) {
255
0
          creation_status = absl::InvalidArgumentError(
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
          return;
260
0
        }
261
0
#endif
262
0
      } break;
263
#ifdef BORINGSSL_FIPS
264
      default:
265
        creation_status = absl::InvalidArgumentError(
266
            fmt::format("Failed to load certificate chain from {}, only RSA and "
267
                        "ECDSA certificates are supported in FIPS mode",
268
                        ctx.cert_chain_file_path_));
269
        return;
270
#endif
271
0
      }
272
273
0
      Envoy::Ssl::PrivateKeyMethodProviderSharedPtr private_key_method_provider =
274
0
          tls_certificate.privateKeyMethod();
275
      // We either have a private key or a BoringSSL private key method provider.
276
0
      if (private_key_method_provider) {
277
0
        ctx.private_key_method_provider_ = private_key_method_provider;
278
        // The provider has a reference to the private key method for the context lifetime.
279
0
        Ssl::BoringSslPrivateKeyMethodSharedPtr private_key_method =
280
0
            private_key_method_provider->getBoringSslPrivateKeyMethod();
281
0
        if (private_key_method == nullptr) {
282
0
          creation_status = absl::InvalidArgumentError(
283
0
              fmt::format("Failed to get BoringSSL private key method from provider"));
284
0
          return;
285
0
        }
286
#ifdef BORINGSSL_FIPS
287
        if (!ctx.private_key_method_provider_->checkFips()) {
288
          creation_status = absl::InvalidArgumentError(
289
              fmt::format("Private key method doesn't support FIPS mode with current parameters"));
290
          return;
291
        }
292
#endif
293
0
        SSL_CTX_set_private_key_method(ctx.ssl_ctx_.get(), private_key_method.get());
294
0
      } else if (!tls_certificate.privateKey().empty()) {
295
        // Load private key.
296
0
        creation_status =
297
0
            ctx.loadPrivateKey(tls_certificate.privateKey(), tls_certificate.privateKeyPath(),
298
0
                               tls_certificate.password());
299
0
        if (!creation_status.ok()) {
300
0
          return;
301
0
        }
302
0
      }
303
304
0
      if (additional_init != nullptr) {
305
0
        absl::Status init_status = additional_init(ctx, tls_certificate);
306
0
        SET_AND_RETURN_IF_NOT_OK(creation_status, init_status);
307
0
      }
308
0
    }
309
0
  }
310
311
0
  parsed_alpn_protocols_ = parseAlpnProtocols(config.alpnProtocols(), creation_status);
312
0
  SET_AND_RETURN_IF_NOT_OK(creation_status, creation_status);
313
314
0
#if BORINGSSL_API_VERSION >= 21
315
  // Register stat names based on lists reported by BoringSSL.
316
0
  std::vector<const char*> list(SSL_get_all_cipher_names(nullptr, 0));
317
0
  SSL_get_all_cipher_names(list.data(), list.size());
318
0
  stat_name_set_->rememberBuiltins(list);
319
320
0
  list.resize(SSL_get_all_curve_names(nullptr, 0));
321
0
  SSL_get_all_curve_names(list.data(), list.size());
322
0
  stat_name_set_->rememberBuiltins(list);
323
324
0
  list.resize(SSL_get_all_signature_algorithm_names(nullptr, 0));
325
0
  SSL_get_all_signature_algorithm_names(list.data(), list.size());
326
0
  stat_name_set_->rememberBuiltins(list);
327
328
0
  list.resize(SSL_get_all_version_names(nullptr, 0));
329
0
  SSL_get_all_version_names(list.data(), list.size());
330
0
  stat_name_set_->rememberBuiltins(list);
331
#else
332
  // Use the SSL library to iterate over the configured ciphers.
333
  //
334
  // Note that if a negotiated cipher suite is outside of this set, we'll issue an ENVOY_BUG.
335
  for (Ssl::TlsContext& tls_context : tls_contexts_) {
336
    for (const SSL_CIPHER* cipher : SSL_CTX_get_ciphers(tls_context.ssl_ctx_.get())) {
337
      stat_name_set_->rememberBuiltin(SSL_CIPHER_get_name(cipher));
338
    }
339
  }
340
341
  // Add supported cipher suites from the TLS 1.3 spec:
342
  // https://tools.ietf.org/html/rfc8446#appendix-B.4
343
  // AES-CCM cipher suites are removed (no BoringSSL support).
344
  //
345
  // Note that if a negotiated cipher suite is outside of this set, we'll issue an ENVOY_BUG.
346
  stat_name_set_->rememberBuiltins(
347
      {"TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256"});
348
349
  // All supported curves. Source:
350
  // https://github.com/google/boringssl/blob/3743aafdacff2f7b083615a043a37101f740fa53/ssl/ssl_key_share.cc#L302-L309
351
  //
352
  // Note that if a negotiated curve is outside of this set, we'll issue an ENVOY_BUG.
353
  stat_name_set_->rememberBuiltins({"P-224", "P-256", "P-384", "P-521", "X25519", "CECPQ2"});
354
355
  // All supported signature algorithms. Source:
356
  // https://github.com/google/boringssl/blob/3743aafdacff2f7b083615a043a37101f740fa53/ssl/ssl_privkey.cc#L436-L453
357
  //
358
  // Note that if a negotiated algorithm is outside of this set, we'll issue an ENVOY_BUG.
359
  stat_name_set_->rememberBuiltins({
360
      "rsa_pkcs1_md5_sha1",
361
      "rsa_pkcs1_sha1",
362
      "rsa_pkcs1_sha256",
363
      "rsa_pkcs1_sha384",
364
      "rsa_pkcs1_sha512",
365
      "ecdsa_sha1",
366
      "ecdsa_secp256r1_sha256",
367
      "ecdsa_secp384r1_sha384",
368
      "ecdsa_secp521r1_sha512",
369
      "rsa_pss_rsae_sha256",
370
      "rsa_pss_rsae_sha384",
371
      "rsa_pss_rsae_sha512",
372
      "ed25519",
373
  });
374
375
  // All supported protocol versions.
376
  //
377
  // Note that if a negotiated version is outside of this set, we'll issue an ENVOY_BUG.
378
  stat_name_set_->rememberBuiltins({"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"});
379
#endif
380
381
  // As late as possible, run the custom SSL_CTX configuration callback on each
382
  // SSL_CTX, if set.
383
0
  if (auto sslctx_cb = config.sslctxCb(); sslctx_cb) {
384
0
    for (Ssl::TlsContext& ctx : tls_contexts_) {
385
0
      sslctx_cb(ctx.ssl_ctx_.get());
386
0
    }
387
0
  }
388
389
0
  if (!config.tlsKeyLogPath().empty()) {
390
0
    ENVOY_LOG(debug, "Enable tls key log");
391
0
    auto file_or_error = config.accessLogManager().createAccessLog(
392
0
        Filesystem::FilePathAndType{Filesystem::DestinationType::File, config.tlsKeyLogPath()});
393
0
    SET_AND_RETURN_IF_NOT_OK(file_or_error.status(), creation_status);
394
0
    tls_keylog_file_ = file_or_error.value();
395
0
    for (auto& context : tls_contexts_) {
396
0
      SSL_CTX* ctx = context.ssl_ctx_.get();
397
0
      ASSERT(ctx != nullptr);
398
0
      SSL_CTX_set_keylog_callback(ctx, keylogCallback);
399
0
    }
400
0
  }
401
0
}
Unexecuted instantiation: Envoy::Extensions::TransportSockets::Tls::ContextImpl::ContextImpl(Envoy::Stats::Scope&, Envoy::Ssl::ContextConfig const&, Envoy::Server::Configuration::CommonFactoryContext&, std::__1::function<absl::lts_20230802::Status (Envoy::Ssl::TlsContext&, Envoy::Ssl::TlsCertificateConfig const&)>, absl::lts_20230802::Status&)
Unexecuted instantiation: Envoy::Extensions::TransportSockets::Tls::ContextImpl::ContextImpl(Envoy::Stats::Scope&, Envoy::Ssl::ContextConfig const&, Envoy::Server::Configuration::CommonFactoryContext&, std::__1::function<absl::lts_20230802::Status (Envoy::Ssl::TlsContext&, Envoy::Ssl::TlsCertificateConfig const&)>, absl::lts_20230802::Status&)
402
403
0
void ContextImpl::keylogCallback(const SSL* ssl, const char* line) {
404
0
  ASSERT(ssl != nullptr);
405
0
  auto callbacks =
406
0
      static_cast<Network::TransportSocketCallbacks*>(SSL_get_ex_data(ssl, sslSocketIndex()));
407
0
  auto ctx = static_cast<ContextImpl*>(SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)));
408
0
  ASSERT(callbacks != nullptr);
409
0
  ASSERT(ctx != nullptr);
410
411
0
  if ((ctx->tls_keylog_local_.getIpListSize() == 0 ||
412
0
       ctx->tls_keylog_local_.contains(
413
0
           *(callbacks->connection().connectionInfoProvider().localAddress()))) &&
414
0
      (ctx->tls_keylog_remote_.getIpListSize() == 0 ||
415
0
       ctx->tls_keylog_remote_.contains(
416
0
           *(callbacks->connection().connectionInfoProvider().remoteAddress())))) {
417
0
    ctx->tls_keylog_file_->write(absl::StrCat(line, "\n"));
418
0
  }
419
0
}
420
421
0
int ContextImpl::sslSocketIndex() {
422
0
  CONSTRUCT_ON_FIRST_USE(int, []() -> int {
423
0
    int ssl_socket_index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
424
0
    RELEASE_ASSERT(ssl_socket_index >= 0, "");
425
0
    return ssl_socket_index;
426
0
  }());
427
0
}
428
429
std::vector<uint8_t> ContextImpl::parseAlpnProtocols(const std::string& alpn_protocols,
430
0
                                                     absl::Status& parse_status) {
431
0
  if (alpn_protocols.empty()) {
432
0
    return {};
433
0
  }
434
435
0
  if (alpn_protocols.size() >= 65535) {
436
0
    parse_status = absl::InvalidArgumentError("Invalid ALPN protocol string");
437
0
    return {};
438
0
  }
439
440
0
  std::vector<uint8_t> out(alpn_protocols.size() + 1);
441
0
  size_t start = 0;
442
0
  for (size_t i = 0; i <= alpn_protocols.size(); i++) {
443
0
    if (i == alpn_protocols.size() || alpn_protocols[i] == ',') {
444
0
      if (i - start > 255) {
445
0
        parse_status = absl::InvalidArgumentError("Invalid ALPN protocol string");
446
0
        return {};
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
absl::StatusOr<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(), factory_context_.timeSource());
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
                                              factory_context_.timeSource());
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
bool ContextImpl::parseAndSetAlpn(const std::vector<std::string>& alpn, SSL& ssl,
655
0
                                  absl::Status& parse_status) {
656
0
  std::vector<uint8_t> parsed_alpn = parseAlpnProtocols(absl::StrJoin(alpn, ","), parse_status);
657
0
  if (!parse_status.ok()) {
658
0
    return false;
659
0
  }
660
0
  if (!parsed_alpn.empty()) {
661
0
    const int rc = SSL_set_alpn_protos(&ssl, parsed_alpn.data(), parsed_alpn.size());
662
    // This should only if memory allocation fails, e.g. OOM.
663
0
    RELEASE_ASSERT(rc == 0, Utility::getLastCryptoError().value_or(""));
664
0
    return true;
665
0
  }
666
667
0
  return false;
668
0
}
669
670
ValidationResults ContextImpl::customVerifyCertChainForQuic(
671
    STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server,
672
    const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options,
673
0
    const CertValidator::ExtraValidationContext& validation_context, const std::string& host_name) {
674
0
  ASSERT(!tls_contexts_.empty());
675
  // It doesn't matter which SSL context is used, because they share the same cert validation
676
  // config.
677
0
  SSL_CTX* ssl_ctx = tls_contexts_[0].ssl_ctx_.get();
678
0
  if (SSL_CTX_get_verify_mode(ssl_ctx) == SSL_VERIFY_NONE) {
679
    // Skip validation if the TLS is configured SSL_VERIFY_NONE.
680
0
    return {ValidationResults::ValidationStatus::Successful,
681
0
            Envoy::Ssl::ClientValidationStatus::NotValidated, absl::nullopt, absl::nullopt};
682
0
  }
683
0
  ValidationResults result =
684
0
      cert_validator_->doVerifyCertChain(cert_chain, std::move(callback), transport_socket_options,
685
0
                                         *ssl_ctx, validation_context, is_server, host_name);
686
0
  return result;
687
0
}
688
689
} // namespace Tls
690
} // namespace TransportSockets
691
} // namespace Extensions
692
693
namespace Ssl {
694
695
0
bool TlsContext::isCipherEnabled(uint16_t cipher_id, uint16_t client_version) const {
696
0
  const SSL_CIPHER* c = SSL_get_cipher_by_value(cipher_id);
697
0
  if (c == nullptr) {
698
0
    return false;
699
0
  }
700
  // Skip TLS 1.2 only ciphersuites unless the client supports it.
701
0
  if (SSL_CIPHER_get_min_version(c) > client_version) {
702
0
    return false;
703
0
  }
704
0
  if (SSL_CIPHER_get_auth_nid(c) != NID_auth_ecdsa) {
705
0
    return false;
706
0
  }
707
0
  for (const SSL_CIPHER* our_c : SSL_CTX_get_ciphers(ssl_ctx_.get())) {
708
0
    if (SSL_CIPHER_get_id(our_c) == SSL_CIPHER_get_id(c)) {
709
0
      return true;
710
0
    }
711
0
  }
712
0
  return false;
713
0
}
714
715
absl::Status TlsContext::loadCertificateChain(const std::string& data,
716
0
                                              const std::string& data_path) {
717
0
  cert_chain_file_path_ = data_path;
718
0
  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
719
0
  RELEASE_ASSERT(bio != nullptr, "");
720
0
  cert_chain_.reset(PEM_read_bio_X509_AUX(bio.get(), nullptr, nullptr, nullptr));
721
0
  if (cert_chain_ == nullptr || !SSL_CTX_use_certificate(ssl_ctx_.get(), cert_chain_.get())) {
722
0
    logSslErrorChain();
723
0
    return absl::InvalidArgumentError(
724
0
        absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
725
0
  }
726
  // Read rest of the certificate chain.
727
0
  while (true) {
728
0
    bssl::UniquePtr<X509> cert(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
729
0
    if (cert == nullptr) {
730
0
      break;
731
0
    }
732
0
    if (!SSL_CTX_add_extra_chain_cert(ssl_ctx_.get(), cert.get())) {
733
0
      return absl::InvalidArgumentError(
734
0
          absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
735
0
    }
736
    // SSL_CTX_add_extra_chain_cert() takes ownership.
737
0
    cert.release();
738
0
  }
739
  // Check for EOF.
740
0
  const uint32_t err = ERR_peek_last_error();
741
0
  if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
742
0
    ERR_clear_error();
743
0
  } else {
744
0
    return absl::InvalidArgumentError(
745
0
        absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
746
0
  }
747
0
  return absl::OkStatus();
748
0
}
749
750
absl::Status TlsContext::loadPrivateKey(const std::string& data, const std::string& data_path,
751
0
                                        const std::string& password) {
752
0
  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
753
0
  RELEASE_ASSERT(bio != nullptr, "");
754
0
  bssl::UniquePtr<EVP_PKEY> pkey(
755
0
      PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr,
756
0
                              !password.empty() ? const_cast<char*>(password.c_str()) : nullptr));
757
758
0
  if (pkey == nullptr || !SSL_CTX_use_PrivateKey(ssl_ctx_.get(), pkey.get())) {
759
0
    return absl::InvalidArgumentError(fmt::format(
760
0
        "Failed to load private key from {}, Cause: {}", data_path,
761
0
        Extensions::TransportSockets::Tls::Utility::getLastCryptoError().value_or("unknown")));
762
0
  }
763
764
0
  return checkPrivateKey(pkey, data_path);
765
0
}
766
767
absl::Status TlsContext::loadPkcs12(const std::string& data, const std::string& data_path,
768
0
                                    const std::string& password) {
769
0
  cert_chain_file_path_ = data_path;
770
0
  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
771
0
  RELEASE_ASSERT(bio != nullptr, "");
772
0
  bssl::UniquePtr<PKCS12> pkcs12(d2i_PKCS12_bio(bio.get(), nullptr));
773
774
0
  EVP_PKEY* temp_private_key = nullptr;
775
0
  X509* temp_cert = nullptr;
776
0
  STACK_OF(X509)* temp_ca_certs = nullptr;
777
0
  if (pkcs12 == nullptr ||
778
0
      !PKCS12_parse(pkcs12.get(), !password.empty() ? const_cast<char*>(password.c_str()) : nullptr,
779
0
                    &temp_private_key, &temp_cert, &temp_ca_certs)) {
780
0
    logSslErrorChain();
781
0
    return absl::InvalidArgumentError(absl::StrCat("Failed to load pkcs12 from ", data_path));
782
0
  }
783
0
  cert_chain_.reset(temp_cert);
784
0
  bssl::UniquePtr<EVP_PKEY> pkey(temp_private_key);
785
0
  bssl::UniquePtr<STACK_OF(X509)> ca_certificates(temp_ca_certs);
786
0
  if (ca_certificates != nullptr) {
787
0
    X509* ca_cert = nullptr;
788
0
    while ((ca_cert = sk_X509_pop(ca_certificates.get())) != nullptr) {
789
      // This transfers ownership to ssl_ctx therefore ca_cert does not need to be freed.
790
0
      SSL_CTX_add_extra_chain_cert(ssl_ctx_.get(), ca_cert);
791
0
    }
792
0
  }
793
0
  if (!SSL_CTX_use_certificate(ssl_ctx_.get(), cert_chain_.get())) {
794
0
    logSslErrorChain();
795
0
    return absl::InvalidArgumentError(absl::StrCat("Failed to load certificate from ", data_path));
796
0
  }
797
0
  if (temp_private_key == nullptr || !SSL_CTX_use_PrivateKey(ssl_ctx_.get(), pkey.get())) {
798
0
    return absl::InvalidArgumentError(fmt::format(
799
0
        "Failed to load private key from {}, Cause: {}", data_path,
800
0
        Extensions::TransportSockets::Tls::Utility::getLastCryptoError().value_or("unknown")));
801
0
  }
802
803
0
  return checkPrivateKey(pkey, data_path);
804
0
}
805
806
absl::Status TlsContext::checkPrivateKey(const bssl::UniquePtr<EVP_PKEY>& pkey,
807
0
                                         const std::string& key_path) {
808
#ifdef BORINGSSL_FIPS
809
  // Verify that private keys are passing FIPS pairwise consistency tests.
810
  switch (EVP_PKEY_id(pkey.get())) {
811
  case EVP_PKEY_EC: {
812
    const EC_KEY* ecdsa_private_key = EVP_PKEY_get0_EC_KEY(pkey.get());
813
    if (!EC_KEY_check_fips(ecdsa_private_key)) {
814
      return absl::InvalidArgumentError(
815
          fmt::format("Failed to load private key from {}, ECDSA key failed "
816
                      "pairwise consistency test required in FIPS mode",
817
                      key_path));
818
    }
819
  } break;
820
  case EVP_PKEY_RSA: {
821
    RSA* rsa_private_key = EVP_PKEY_get0_RSA(pkey.get());
822
    if (!RSA_check_fips(rsa_private_key)) {
823
      return absl::InvalidArgumentError(
824
          fmt::format("Failed to load private key from {}, RSA key failed "
825
                      "pairwise consistency test required in FIPS mode",
826
                      key_path));
827
    }
828
  } break;
829
  }
830
#else
831
0
  UNREFERENCED_PARAMETER(pkey);
832
0
  UNREFERENCED_PARAMETER(key_path);
833
0
#endif
834
0
  return absl::OkStatus();
835
0
}
836
837
} // namespace Ssl
838
} // namespace Envoy