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_compression.h"
30
#include "source/common/tls/cert_validator/factory.h"
31
#include "source/common/tls/stats.h"
32
#include "source/common/tls/utility.h"
33

            
34
#include "absl/container/node_hash_set.h"
35
#include "absl/strings/match.h"
36
#include "absl/strings/str_join.h"
37
#include "cert_validator/cert_validator.h"
38
#include "openssl/crypto.h"
39
#include "openssl/evp.h"
40
#include "openssl/hmac.h"
41
#include "openssl/pkcs12.h"
42
#include "openssl/rand.h"
43

            
44
namespace Envoy {
45
namespace {
46

            
47
8
void logSslErrorChain() {
48
18
  while (uint64_t err = ERR_get_error()) {
49
10
    ENVOY_LOG_MISC(debug, "SSL error: {}:{}:{}:{}", err,
50
10
                   absl::NullSafeStringView(ERR_lib_error_string(err)),
51
10
                   absl::NullSafeStringView(ERR_func_error_string(err)), ERR_GET_REASON(err),
52
10
                   absl::NullSafeStringView(ERR_reason_error_string(err)));
53
10
  }
54
8
}
55

            
56
} // namespace
57

            
58
namespace Extensions {
59
namespace TransportSockets {
60
namespace Tls {
61

            
62
5191
int ContextImpl::sslExtendedSocketInfoIndex() {
63
5191
  CONSTRUCT_ON_FIRST_USE(int, []() -> int {
64
5191
    int ssl_context_index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
65
5191
    RELEASE_ASSERT(ssl_context_index >= 0, "");
66
5191
    return ssl_context_index;
67
5191
  }());
68
5191
}
69

            
70
ContextImpl::ContextImpl(
71
    Stats::Scope& scope, const Envoy::Ssl::ContextConfig& config,
72
    const std::vector<std::reference_wrapper<const Ssl::TlsCertificateConfig>>& tls_certificates,
73
    Server::Configuration::CommonFactoryContext& factory_context,
74
    Ssl::ContextAdditionalInitFunc additional_init, absl::Status& creation_status)
75
7030
    : scope_(scope), stats_(generateSslStats(scope)), factory_context_(factory_context),
76
7030
      tls_max_version_(config.maxProtocolVersion()),
77
7030
      stat_name_set_(scope.symbolTable().makeSet("TransportSockets::Tls")),
78
7030
      unknown_ssl_cipher_(stat_name_set_->add("unknown_ssl_cipher")),
79
7030
      unknown_ssl_curve_(stat_name_set_->add("unknown_ssl_curve")),
80
7030
      unknown_ssl_algorithm_(stat_name_set_->add("unknown_ssl_algorithm")),
81
7030
      unknown_ssl_version_(stat_name_set_->add("unknown_ssl_version")),
82
7030
      ssl_ciphers_(stat_name_set_->add("ssl.ciphers")),
83
7030
      ssl_versions_(stat_name_set_->add("ssl.versions")),
84
7030
      ssl_curves_(stat_name_set_->add("ssl.curves")),
85
7030
      ssl_sigalgs_(stat_name_set_->add("ssl.sigalgs")), capabilities_(config.capabilities()),
86
7030
      tls_keylog_local_(config.tlsKeyLogLocal()), tls_keylog_remote_(config.tlsKeyLogRemote()) {
87

            
88
7030
  auto cert_validator_name = getCertValidatorName(config.certificateValidationContext());
89
7030
  auto cert_validator_factory =
90
7030
      Registry::FactoryRegistry<CertValidatorFactory>::getFactory(cert_validator_name);
91

            
92
7030
  if (!cert_validator_factory) {
93
1
    creation_status = absl::InvalidArgumentError(
94
1
        absl::StrCat("Failed to get certificate validator factory for ", cert_validator_name));
95
1
    return;
96
1
  }
97

            
98
7029
  auto validator_or_error = cert_validator_factory->createCertValidator(
99
7029
      config.certificateValidationContext(), stats_, factory_context_, scope);
100
7029
  SET_AND_RETURN_IF_NOT_OK(validator_or_error.status(), creation_status);
101
7029
  cert_validator_ = std::move(*validator_or_error);
102

            
103
7029
  tls_contexts_.resize(std::max(static_cast<size_t>(1), tls_certificates.size()));
104

            
105
7029
  std::vector<SSL_CTX*> ssl_contexts(tls_contexts_.size());
106
14128
  for (size_t i = 0; i < tls_contexts_.size(); i++) {
107
7103
    auto& ctx = tls_contexts_[i];
108
7103
    ctx.ssl_ctx_.reset(SSL_CTX_new(TLS_method()));
109
7103
    ssl_contexts[i] = ctx.ssl_ctx_.get();
110

            
111
7103
    int rc = SSL_CTX_set_app_data(ctx.ssl_ctx_.get(), this);
112
7103
    RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
113

            
114
7103
    rc = SSL_CTX_set_min_proto_version(ctx.ssl_ctx_.get(), config.minProtocolVersion());
115
7103
    RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
116

            
117
7103
    rc = SSL_CTX_set_max_proto_version(ctx.ssl_ctx_.get(), config.maxProtocolVersion());
118
7103
    RELEASE_ASSERT(rc == 1, Utility::getLastCryptoError().value_or(""));
119

            
120
7103
    if (!capabilities_.provides_ciphers_and_curves &&
121
7103
        !SSL_CTX_set_strict_cipher_list(ctx.ssl_ctx_.get(), config.cipherSuites().c_str())) {
122
      // Break up a set of ciphers into each individual cipher and try them each individually in
123
      // order to attempt to log which specific one failed. Example of config.cipherSuites():
124
      // "-ALL:[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]:ECDHE-ECDSA-AES128-SHA".
125
      //
126
      // "-" is both an operator when in the leading position of a token (-ALL: don't allow this
127
      // cipher), and the common separator in names (ECDHE-ECDSA-AES128-GCM-SHA256). Don't split on
128
      // it because it will separate pieces of the same cipher. When it is a leading character, it
129
      // is removed below.
130
1
      std::vector<absl::string_view> ciphers =
131
1
          StringUtil::splitToken(config.cipherSuites(), ":+![|]", false);
132
1
      std::vector<std::string> bad_ciphers;
133
5
      for (const auto& cipher : ciphers) {
134
5
        std::string cipher_str(cipher);
135

            
136
5
        if (absl::StartsWith(cipher_str, "-")) {
137
1
          cipher_str.erase(cipher_str.begin());
138
1
        }
139

            
140
5
        if (!SSL_CTX_set_strict_cipher_list(ctx.ssl_ctx_.get(), cipher_str.c_str())) {
141
2
          bad_ciphers.push_back(cipher_str);
142
2
        }
143
5
      }
144
1
      creation_status = absl::InvalidArgumentError(
145
1
          fmt::format("Failed to initialize cipher suites {}. The following "
146
1
                      "ciphers were rejected when tried individually: {}",
147
1
                      config.cipherSuites(), absl::StrJoin(bad_ciphers, ", ")));
148
1
      return;
149
1
    }
150

            
151
7102
    if (!capabilities_.provides_ciphers_and_curves &&
152
7102
        !SSL_CTX_set1_curves_list(ctx.ssl_ctx_.get(), config.ecdhCurves().c_str())) {
153
1
      creation_status = absl::InvalidArgumentError(
154
1
          absl::StrCat("Failed to initialize ECDH curves ", config.ecdhCurves()));
155
1
      return;
156
1
    }
157

            
158
    // Set signature algorithms if given, otherwise fall back to BoringSSL defaults.
159
7101
    if (!capabilities_.provides_sigalgs && !config.signatureAlgorithms().empty()) {
160
27
      if (!SSL_CTX_set1_sigalgs_list(ctx.ssl_ctx_.get(), config.signatureAlgorithms().c_str())) {
161
2
        creation_status = absl::InvalidArgumentError(absl::StrCat(
162
2
            "Failed to initialize TLS signature algorithms ", config.signatureAlgorithms()));
163
2
        return;
164
2
      }
165
27
    }
166

            
167
    // Register certificate compression algorithms to reduce TLS handshake size (RFC 8879).
168
    // Priority: brotli > zlib (brotli generally provides best compression for certs).
169
7099
    if (Runtime::runtimeFeatureEnabled(
170
7099
            "envoy.reloadable_features.tls_certificate_compression_brotli")) {
171
7097
      CertCompression::registerBrotli(ctx.ssl_ctx_.get());
172
7097
      CertCompression::registerZlib(ctx.ssl_ctx_.get());
173
7097
    }
174
7099
  }
175

            
176
7025
  auto verify_mode_or_error = cert_validator_->initializeSslContexts(
177
7025
      ssl_contexts, config.capabilities().provides_certificates, scope);
178
7025
  SET_AND_RETURN_IF_NOT_OK(verify_mode_or_error.status(), creation_status);
179
7016
  auto verify_mode = verify_mode_or_error.value();
180

            
181
7016
  if (!capabilities_.verifies_peer_certificates) {
182
7090
    for (auto ctx : ssl_contexts) {
183
7090
      if (verify_mode != SSL_VERIFY_NONE) {
184
        // TODO(danzh) Envoy's use of SSL_VERIFY_NONE does not quite match the actual semantics as
185
        // a client. As a client, SSL_VERIFY_NONE means to verify the certificate (which will fail
186
        // without trust anchors), save the result in the session ticket, but otherwise continue
187
        // with the handshake. But Envoy actually wants it to accept all certificates. The
188
        // disadvantage of using SSL_VERIFY_NONE is that it records the verify_result, which Envoy
189
        // never queries but gets saved in session tickets, and tries to find an anchor that isn't
190
        // there. And also it differs from server side behavior of SSL_VERIFY_NONE which won't
191
        // even request client certs. So, instead, we should configure a callback to skip
192
        // validation and always supply the callback to boring SSL.
193
6026
        SSL_CTX_set_custom_verify(ctx, verify_mode, customVerifyCallback);
194
6026
        SSL_CTX_set_reverify_on_resume(ctx, /*reverify_on_resume_enabled)=*/1);
195
6026
      }
196
7090
    }
197
7016
  }
198

            
199
7016
  const bool fips_mode = FIPS_mode();
200

            
201
7016
  if (fips_mode) {
202
    if (!capabilities_.is_fips_compliant) {
203
      creation_status = absl::InvalidArgumentError(
204
          "Can't load a FIPS noncompliant custom handshaker while running in FIPS compliant mode.");
205
      return;
206
    }
207
  }
208

            
209
7016
  if (!capabilities_.provides_certificates) {
210
12178
    for (uint32_t i = 0; i < tls_certificates.size(); ++i) {
211
5183
      auto& ctx = tls_contexts_[i];
212
      // Load certificate chain.
213
5183
      const auto& tls_certificate = tls_certificates[i].get();
214
5183
      if (!tls_certificate.pkcs12().empty()) {
215
12
        creation_status = ctx.loadPkcs12(tls_certificate.pkcs12(), tls_certificate.pkcs12Path(),
216
12
                                         tls_certificate.password(), fips_mode);
217
5171
      } else {
218
5171
        creation_status = ctx.loadCertificateChain(tls_certificate.certificateChain(),
219
5171
                                                   tls_certificate.certificateChainPath());
220
5171
      }
221
5183
      if (!creation_status.ok()) {
222
10
        return;
223
10
      }
224

            
225
      // Create and set the certificate expiration gauge.
226
5173
      Stats::Gauge& expiration_gauge =
227
5173
          Extensions::TransportSockets::Tls::createCertificateExpirationGauge(
228
5173
              scope, tls_certificate.certificateName());
229
5173
      expiration_gauge.set(Utility::getExpirationUnixTime(ctx.cert_chain_.get()).count());
230

            
231
      // The must staple extension means the certificate promises to carry
232
      // with it an OCSP staple. https://tools.ietf.org/html/rfc7633#section-6
233
5173
      constexpr absl::string_view tls_feature_ext = "1.3.6.1.5.5.7.1.24";
234
5173
      constexpr absl::string_view must_staple_ext_value = "\x30\x3\x02\x01\x05";
235
5173
      auto must_staple = Utility::getCertificateExtensionValue(*ctx.cert_chain_, tls_feature_ext);
236
5173
      if (must_staple == must_staple_ext_value) {
237
4
        ctx.is_must_staple_ = true;
238
4
      }
239

            
240
5173
      bssl::UniquePtr<EVP_PKEY> public_key(X509_get_pubkey(ctx.cert_chain_.get()));
241
5173
      const int pkey_id = EVP_PKEY_id(public_key.get());
242
5173
      switch (pkey_id) {
243
106
      case EVP_PKEY_EC: {
244
        // We only support P-256, P-384 or P-521 ECDSA today.
245
106
        const EC_KEY* ecdsa_public_key = EVP_PKEY_get0_EC_KEY(public_key.get());
246
        // Since we checked the key type above, this should be valid.
247
106
        ASSERT(ecdsa_public_key != nullptr);
248
106
        const EC_GROUP* ecdsa_group = EC_KEY_get0_group(ecdsa_public_key);
249
106
        const int ec_group_curve_name = EC_GROUP_get_curve_name(ecdsa_group);
250
106
        if (ecdsa_group == nullptr ||
251
106
            (ec_group_curve_name != NID_X9_62_prime256v1 && ec_group_curve_name != NID_secp384r1 &&
252
106
             ec_group_curve_name != NID_secp521r1)) {
253
          creation_status = absl::InvalidArgumentError(
254
              fmt::format("Failed to load certificate chain from {}, only P-256, "
255
                          "P-384 or P-521 ECDSA certificates are supported",
256
                          ctx.cert_chain_file_path_));
257
          return;
258
        }
259
106
        ctx.ec_group_curve_name_ = ec_group_curve_name;
260
106
      } break;
261
5067
      case EVP_PKEY_RSA: {
262
        // We require RSA certificates with 2048-bit or larger keys.
263
5067
        const RSA* rsa_public_key = EVP_PKEY_get0_RSA(public_key.get());
264
        // Since we checked the key type above, this should be valid.
265
5067
        ASSERT(rsa_public_key != nullptr);
266
5067
        const unsigned rsa_key_length = RSA_bits(rsa_public_key);
267
5067
        if (fips_mode) {
268
          if (rsa_key_length != 2048 && rsa_key_length != 3072 && rsa_key_length != 4096) {
269
            creation_status = absl::InvalidArgumentError(
270
                fmt::format("Failed to load certificate chain from {}, only RSA certificates with "
271
                            "2048-bit, 3072-bit or 4096-bit keys are supported in FIPS mode",
272
                            ctx.cert_chain_file_path_));
273
            return;
274
          }
275
5067
        } else {
276
5067
          if (rsa_key_length < 2048) {
277
3
            creation_status = absl::InvalidArgumentError(
278
3
                fmt::format("Failed to load certificate chain from {}, only RSA "
279
3
                            "certificates with 2048-bit or larger keys are supported",
280
3
                            ctx.cert_chain_file_path_));
281
3
            return;
282
3
          }
283
5067
        }
284
5067
      } break;
285
5064
      default:
286
        if (fips_mode) {
287
          creation_status = absl::InvalidArgumentError(
288
              fmt::format("Failed to load certificate chain from {}, only RSA and "
289
                          "ECDSA certificates are supported in FIPS mode",
290
                          ctx.cert_chain_file_path_));
291
          return;
292
        }
293
5173
      }
294

            
295
5170
      Envoy::Ssl::PrivateKeyMethodProviderSharedPtr private_key_method_provider =
296
5170
          tls_certificate.privateKeyMethod();
297
      // We either have a private key or a BoringSSL private key method provider.
298
5170
      if (private_key_method_provider) {
299
22
        ctx.private_key_method_provider_ = private_key_method_provider;
300
        // The provider has a reference to the private key method for the context lifetime.
301
22
        Ssl::BoringSslPrivateKeyMethodSharedPtr private_key_method =
302
22
            private_key_method_provider->getBoringSslPrivateKeyMethod();
303
22
        if (private_key_method == nullptr) {
304
1
          creation_status = absl::InvalidArgumentError(
305
1
              fmt::format("Failed to get BoringSSL private key method from provider"));
306
1
          return;
307
1
        }
308
21
        if (fips_mode) {
309
          if (!ctx.private_key_method_provider_->checkFips()) {
310
            creation_status = absl::InvalidArgumentError(fmt::format(
311
                "Private key method doesn't support FIPS mode with current parameters"));
312
            return;
313
          }
314
        }
315
21
        SSL_CTX_set_private_key_method(ctx.ssl_ctx_.get(), private_key_method.get());
316
5148
      } else if (!tls_certificate.privateKey().empty()) {
317
        // Load private key.
318
5140
        creation_status =
319
5140
            ctx.loadPrivateKey(tls_certificate.privateKey(), tls_certificate.privateKeyPath(),
320
5140
                               tls_certificate.password(), fips_mode);
321
5140
        if (!creation_status.ok()) {
322
6
          return;
323
6
        }
324
5140
      }
325

            
326
5163
      if (additional_init != nullptr) {
327
2136
        absl::Status init_status = additional_init(ctx, tls_certificate);
328
2136
        SET_AND_RETURN_IF_NOT_OK(creation_status, init_status);
329
2136
      }
330
5163
    }
331
7015
  }
332

            
333
6996
  parsed_alpn_protocols_ = parseAlpnProtocols(config.alpnProtocols(), creation_status);
334
6996
  SET_AND_RETURN_IF_NOT_OK(creation_status, creation_status);
335

            
336
  // Register stat names based on lists reported by BoringSSL.
337
6994
  std::vector<const char*> list(SSL_get_all_cipher_names(nullptr, 0));
338
6994
  SSL_get_all_cipher_names(list.data(), list.size());
339
6994
  stat_name_set_->rememberBuiltins(list);
340

            
341
6994
  list.resize(SSL_get_all_curve_names(nullptr, 0));
342
6994
  SSL_get_all_curve_names(list.data(), list.size());
343
6994
  stat_name_set_->rememberBuiltins(list);
344

            
345
6994
  list.resize(SSL_get_all_signature_algorithm_names(nullptr, 0));
346
6994
  SSL_get_all_signature_algorithm_names(list.data(), list.size());
347
6994
  stat_name_set_->rememberBuiltins(list);
348

            
349
6994
  list.resize(SSL_get_all_version_names(nullptr, 0));
350
6994
  SSL_get_all_version_names(list.data(), list.size());
351
6994
  stat_name_set_->rememberBuiltins(list);
352

            
353
  // As late as possible, run the custom SSL_CTX configuration callback on each
354
  // SSL_CTX, if set.
355
6994
  if (auto sslctx_cb = config.sslctxCb(); sslctx_cb) {
356
4
    for (Ssl::TlsContext& ctx : tls_contexts_) {
357
4
      sslctx_cb(ctx.ssl_ctx_.get());
358
4
    }
359
4
  }
360

            
361
6994
  if (!config.tlsKeyLogPath().empty()) {
362
9
    ENVOY_LOG(debug, "Enable tls key log");
363
9
    auto file_or_error = config.accessLogManager().createAccessLog(
364
9
        Filesystem::FilePathAndType{Filesystem::DestinationType::File, config.tlsKeyLogPath()});
365
9
    SET_AND_RETURN_IF_NOT_OK(file_or_error.status(), creation_status);
366
8
    tls_keylog_file_ = file_or_error.value();
367
8
    for (auto& context : tls_contexts_) {
368
8
      SSL_CTX* ctx = context.ssl_ctx_.get();
369
8
      ASSERT(ctx != nullptr);
370
8
      SSL_CTX_set_keylog_callback(ctx, keylogCallback);
371
8
    }
372
8
  }
373

            
374
  // Compliance policy must be applied last to have a defined behavior.
375
6993
  if (const auto policy = config.compliancePolicy(); policy.has_value()) {
376
1
    switch (policy.value()) {
377
      using ProtoPolicy = envoy::extensions::transport_sockets::tls::v3::TlsParameters;
378
1
    case ProtoPolicy::FIPS_202205:
379
1
      if (!fips_mode) {
380
1
        ENVOY_LOG(warn, "FIPS conformance policy applied on a non-FIPS build");
381
1
      }
382
1
      for (auto& tls_context : tls_contexts_) {
383
1
        int rc = SSL_CTX_set_compliance_policy(tls_context.ssl_ctx_.get(),
384
1
                                               ssl_compliance_policy_fips_202205);
385
1
        if (rc != 1) {
386
          creation_status = absl::InvalidArgumentError(
387
              absl::StrCat("Failed to apply FIPS_202205 compliance policy: ",
388
                           Utility::getLastCryptoError().value_or("")));
389
          return;
390
        }
391
1
      }
392
1
      break;
393
1
    default:
394
      creation_status = absl::InvalidArgumentError("Unknown compliance policy");
395
      return;
396
1
    }
397
1
  }
398
6993
}
399

            
400
8
void ContextImpl::keylogCallback(const SSL* ssl, const char* line) {
401
8
  ASSERT(ssl != nullptr);
402
8
  auto callbacks =
403
8
      static_cast<Network::TransportSocketCallbacks*>(SSL_get_ex_data(ssl, sslSocketIndex()));
404
8
  auto ctx = static_cast<ContextImpl*>(SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)));
405
8
  ASSERT(callbacks != nullptr);
406
8
  ASSERT(ctx != nullptr);
407

            
408
8
  if ((ctx->tls_keylog_local_.getIpListSize() == 0 ||
409
8
       ctx->tls_keylog_local_.contains(
410
6
           *(callbacks->connection().connectionInfoProvider().localAddress()))) &&
411
8
      (ctx->tls_keylog_remote_.getIpListSize() == 0 ||
412
6
       ctx->tls_keylog_remote_.contains(
413
5
           *(callbacks->connection().connectionInfoProvider().remoteAddress())))) {
414
5
    ctx->tls_keylog_file_->write(absl::StrCat(line, "\n"));
415
5
  }
416
8
}
417

            
418
3704
int ContextImpl::sslSocketIndex() {
419
3704
  CONSTRUCT_ON_FIRST_USE(int, []() -> int {
420
3704
    int ssl_socket_index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
421
3704
    RELEASE_ASSERT(ssl_socket_index >= 0, "");
422
3704
    return ssl_socket_index;
423
3704
  }());
424
3704
}
425

            
426
std::vector<uint8_t> ContextImpl::parseAlpnProtocols(const std::string& alpn_protocols,
427
8309
                                                     absl::Status& parse_status) {
428
8309
  if (alpn_protocols.empty()) {
429
5583
    return {};
430
5583
  }
431

            
432
2726
  if (alpn_protocols.size() >= 65535) {
433
2
    parse_status = absl::InvalidArgumentError("Invalid ALPN protocol string");
434
2
    return {};
435
2
  }
436

            
437
2724
  std::vector<uint8_t> out(alpn_protocols.size() + 1);
438
2724
  size_t start = 0;
439
28637
  for (size_t i = 0; i <= alpn_protocols.size(); i++) {
440
25913
    if (i == alpn_protocols.size() || alpn_protocols[i] == ',') {
441
5170
      if (i - start > 255) {
442
        parse_status = absl::InvalidArgumentError("Invalid ALPN protocol string");
443
        return {};
444
      }
445

            
446
5170
      out[start] = i - start;
447
5170
      start = i + 1;
448
20743
    } else {
449
20743
      out[i + 1] = alpn_protocols[i];
450
20743
    }
451
25913
  }
452

            
453
2724
  return out;
454
2724
}
455

            
456
absl::StatusOr<bssl::UniquePtr<SSL>>
457
ContextImpl::newSsl(const Network::TransportSocketOptionsConstSharedPtr& options,
458
2587
                    Upstream::HostDescriptionConstSharedPtr) {
459
  // We use the first certificate for a new SSL object, later in the
460
  // SSL_CTX_set_select_certificate_cb() callback following ClientHello, we replace with the
461
  // selected certificate via SSL_set_SSL_CTX().
462
2587
  auto ssl_con = bssl::UniquePtr<SSL>(SSL_new(tls_contexts_[0].ssl_ctx_.get()));
463
2587
  SSL_set_app_data(ssl_con.get(), &options);
464
2587
  return ssl_con;
465
2587
}
466

            
467
1209
enum ssl_verify_result_t ContextImpl::customVerifyCallback(SSL* ssl, uint8_t* out_alert) {
468
1209
  auto* extended_socket_info = reinterpret_cast<Envoy::Ssl::SslExtendedSocketInfo*>(
469
1209
      SSL_get_ex_data(ssl, ContextImpl::sslExtendedSocketInfoIndex()));
470
1209
  if (extended_socket_info->certificateValidationResult() != Ssl::ValidateStatus::NotStarted) {
471
16
    if (extended_socket_info->certificateValidationResult() == Ssl::ValidateStatus::Pending) {
472
11
      return ssl_verify_retry;
473
11
    }
474
5
    ENVOY_LOG(trace, "Already has a result: {}",
475
5
              static_cast<int>(extended_socket_info->certificateValidationStatus()));
476
    // Already has a binary result, return immediately.
477
5
    *out_alert = extended_socket_info->certificateValidationAlert();
478
5
    return extended_socket_info->certificateValidationResult() == Ssl::ValidateStatus::Successful
479
5
               ? ssl_verify_ok
480
5
               : ssl_verify_invalid;
481
16
  }
482
  // Hasn't kicked off any validation for this connection yet.
483
1193
  SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
484
1193
  ContextImpl* context_impl = static_cast<ContextImpl*>(SSL_CTX_get_app_data(ssl_ctx));
485
1193
  auto transport_socket_options_shared_ptr_ptr =
486
1193
      static_cast<const Network::TransportSocketOptionsConstSharedPtr*>(SSL_get_app_data(ssl));
487
1193
  ASSERT(transport_socket_options_shared_ptr_ptr);
488
1193
  ValidationResults result = context_impl->customVerifyCertChain(
489
1193
      extended_socket_info, *transport_socket_options_shared_ptr_ptr, ssl);
490
1193
  switch (result.status) {
491
1131
  case ValidationResults::ValidationStatus::Successful:
492
1131
    return ssl_verify_ok;
493
7
  case ValidationResults::ValidationStatus::Pending:
494
7
    return ssl_verify_retry;
495
55
  case ValidationResults::ValidationStatus::Failed: {
496
55
    if (result.tls_alert.has_value() && out_alert) {
497
41
      *out_alert = result.tls_alert.value();
498
41
    }
499
    // Store detailed error information for access log reporting.
500
55
    if (result.error_details.has_value()) {
501
55
      extended_socket_info->setCertificateValidationError(result.error_details.value());
502
55
    }
503
55
    return ssl_verify_invalid;
504
  }
505
1193
  }
506
  PANIC("not reached");
507
}
508

            
509
ValidationResults ContextImpl::customVerifyCertChain(
510
    Envoy::Ssl::SslExtendedSocketInfo* extended_socket_info,
511
1193
    const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, SSL* ssl) {
512
1193
  ASSERT(extended_socket_info);
513
1193
  STACK_OF(X509)* cert_chain = SSL_get_peer_full_cert_chain(ssl);
514
1193
  if (cert_chain == nullptr) {
515
    extended_socket_info->setCertificateValidationStatus(Ssl::ClientValidationStatus::NotValidated);
516
    stats_.fail_verify_error_.inc();
517
    ENVOY_LOG(debug, "verify cert failed: no cert chain");
518
    return {ValidationResults::ValidationStatus::Failed, Ssl::ClientValidationStatus::NotValidated,
519
            SSL_AD_INTERNAL_ERROR, absl::nullopt};
520
  }
521
1193
  ASSERT(cert_validator_);
522
1193
  const char* host_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
523

            
524
1193
  CertValidator::ExtraValidationContext validation_ctx;
525
1193
  validation_ctx.callbacks =
526
1193
      static_cast<Network::TransportSocketCallbacks*>(SSL_get_ex_data(ssl, sslSocketIndex()));
527

            
528
1193
  ValidationResults result = cert_validator_->doVerifyCertChain(
529
1193
      *cert_chain, extended_socket_info->createValidateResultCallback(), transport_socket_options,
530
1193
      *SSL_get_SSL_CTX(ssl), validation_ctx, SSL_is_server(ssl),
531
1193
      absl::NullSafeStringView(host_name));
532
1193
  if (result.status != ValidationResults::ValidationStatus::Pending) {
533
1186
    extended_socket_info->setCertificateValidationStatus(result.detailed_status);
534
1186
    extended_socket_info->onCertificateValidationCompleted(
535
1186
        result.status == ValidationResults::ValidationStatus::Successful, false);
536
1186
  }
537
1193
  return result;
538
1193
}
539

            
540
void ContextImpl::incCounter(const Stats::StatName name, absl::string_view value,
541
7680
                             const Stats::StatName fallback) const {
542
7680
  const Stats::StatName value_stat_name = stat_name_set_->getBuiltin(value, fallback);
543
7680
  ENVOY_BUG(value_stat_name != fallback,
544
7680
            absl::StrCat("Unexpected ", scope_.symbolTable().toString(name), " value: ", value));
545
7680
  Stats::Utility::counterFromElements(scope_, {name, value_stat_name}).inc();
546
7680
}
547

            
548
2127
void ContextImpl::logHandshake(SSL* ssl) const {
549
2127
  stats_.handshake_.inc();
550

            
551
2127
  if (SSL_session_reused(ssl)) {
552
215
    stats_.session_reused_.inc();
553
215
  }
554

            
555
2127
  incCounter(ssl_ciphers_, SSL_get_cipher_name(ssl), unknown_ssl_cipher_);
556
2127
  incCounter(ssl_versions_, SSL_get_version(ssl), unknown_ssl_version_);
557

            
558
2127
  const uint16_t curve_id = SSL_get_curve_id(ssl);
559
2127
  if (curve_id) {
560
2111
    incCounter(ssl_curves_, SSL_get_curve_name(curve_id), unknown_ssl_curve_);
561
2111
  }
562

            
563
2127
  const uint16_t sigalg_id = SSL_get_peer_signature_algorithm(ssl);
564
2127
  if (sigalg_id) {
565
1311
    const char* sigalg = SSL_get_signature_algorithm_name(sigalg_id, 1 /* include curve */);
566
1311
    incCounter(ssl_sigalgs_, sigalg, unknown_ssl_algorithm_);
567
1311
  }
568

            
569
2127
  bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl));
570
2127
  if (!cert.get()) {
571
806
    stats_.no_certificate_.inc();
572
806
  }
573

            
574
  // Increment the `was_key_usage_invalid_` stats to indicate the given cert would have triggered an
575
  // error but is allowed because the enforcement that rsa key usage and tls usage need to be
576
  // matched has been disabled.
577
2127
  if (SSL_was_key_usage_invalid(ssl)) {
578
1
    stats_.was_key_usage_invalid_.inc();
579
1
  }
580
2127
}
581

            
582
5005
std::vector<Ssl::PrivateKeyMethodProviderSharedPtr> ContextImpl::getPrivateKeyMethodProviders() {
583
5005
  std::vector<Envoy::Ssl::PrivateKeyMethodProviderSharedPtr> providers;
584

            
585
5133
  for (auto& tls_context : tls_contexts_) {
586
5133
    Envoy::Ssl::PrivateKeyMethodProviderSharedPtr provider =
587
5133
        tls_context.getPrivateKeyMethodProvider();
588
5133
    if (provider) {
589
38
      providers.push_back(provider);
590
38
    }
591
5133
  }
592
5005
  return providers;
593
5005
}
594

            
595
6177
absl::optional<uint32_t> ContextImpl::daysUntilFirstCertExpires() const {
596
6177
  absl::optional<uint32_t> daysUntilExpiration = cert_validator_->daysUntilFirstCertExpires();
597
6177
  if (!daysUntilExpiration.has_value()) {
598
    return absl::nullopt;
599
  }
600
6257
  for (auto& ctx : tls_contexts_) {
601
6257
    const absl::optional<uint32_t> tmp =
602
6257
        Utility::getDaysUntilExpiration(ctx.cert_chain_.get(), factory_context_.timeSource());
603
6257
    if (!tmp.has_value()) {
604
6
      return absl::nullopt;
605
6
    }
606
6251
    daysUntilExpiration = std::min<uint32_t>(tmp.value(), daysUntilExpiration.value());
607
6251
  }
608
6171
  return daysUntilExpiration;
609
6177
}
610

            
611
6170
absl::optional<uint64_t> ContextImpl::secondsUntilFirstOcspResponseExpires() const {
612
6170
  absl::optional<uint64_t> secs_until_expiration;
613
6250
  for (auto& ctx : tls_contexts_) {
614
6250
    if (ctx.ocsp_response_) {
615
2401
      uint64_t next_expiration = ctx.ocsp_response_->secondsUntilExpiration();
616
2401
      secs_until_expiration = std::min<uint64_t>(
617
2401
          next_expiration, secs_until_expiration.value_or(std::numeric_limits<uint64_t>::max()));
618
2401
    }
619
6250
  }
620

            
621
6170
  return secs_until_expiration;
622
6170
}
623

            
624
9
Envoy::Ssl::CertificateDetailsPtr ContextImpl::getCaCertInformation() const {
625
9
  return cert_validator_->getCaCertInformation();
626
9
}
627

            
628
8
std::vector<Envoy::Ssl::CertificateDetailsPtr> ContextImpl::getCertChainInformation() const {
629
8
  std::vector<Envoy::Ssl::CertificateDetailsPtr> cert_details;
630
8
  for (const auto& ctx : tls_contexts_) {
631
8
    if (ctx.cert_chain_ == nullptr) {
632
3
      continue;
633
3
    }
634

            
635
5
    auto detail = Utility::certificateDetails(ctx.cert_chain_.get(), ctx.getCertChainFileName(),
636
5
                                              factory_context_.timeSource());
637
5
    auto ocsp_resp = ctx.ocsp_response_.get();
638
5
    if (ocsp_resp) {
639
1
      auto* ocsp_details = detail->mutable_ocsp_details();
640
1
      Protobuf::Timestamp* valid_from = ocsp_details->mutable_valid_from();
641
1
      TimestampUtil::systemClockToTimestamp(ocsp_resp->getThisUpdate(), *valid_from);
642
1
      Protobuf::Timestamp* expiration = ocsp_details->mutable_expiration();
643
1
      TimestampUtil::systemClockToTimestamp(ocsp_resp->getNextUpdate(), *expiration);
644
1
    }
645
5
    cert_details.push_back(std::move(detail));
646
5
  }
647
8
  return cert_details;
648
8
}
649

            
650
bool ContextImpl::parseAndSetAlpn(const std::vector<std::string>& alpn, SSL& ssl,
651
1313
                                  absl::Status& parse_status) {
652
1313
  std::vector<uint8_t> parsed_alpn = parseAlpnProtocols(absl::StrJoin(alpn, ","), parse_status);
653
1313
  if (!parse_status.ok()) {
654
    return false;
655
  }
656
1313
  if (!parsed_alpn.empty()) {
657
663
    const int rc = SSL_set_alpn_protos(&ssl, parsed_alpn.data(), parsed_alpn.size());
658
    // This should only if memory allocation fails, e.g. OOM.
659
663
    RELEASE_ASSERT(rc == 0, Utility::getLastCryptoError().value_or(""));
660
663
    return true;
661
663
  }
662

            
663
650
  return false;
664
1313
}
665

            
666
ValidationResults ContextImpl::customVerifyCertChainForQuic(
667
    STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server,
668
    const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options,
669
2955
    const CertValidator::ExtraValidationContext& validation_context, const std::string& host_name) {
670
2955
  ASSERT(!tls_contexts_.empty());
671
  // It doesn't matter which SSL context is used, because they share the same cert validation
672
  // config.
673
2955
  SSL_CTX* ssl_ctx = tls_contexts_[0].ssl_ctx_.get();
674
2955
  if (SSL_CTX_get_verify_mode(ssl_ctx) == SSL_VERIFY_NONE) {
675
    // Skip validation if the TLS is configured SSL_VERIFY_NONE.
676
4
    return {ValidationResults::ValidationStatus::Successful,
677
4
            Envoy::Ssl::ClientValidationStatus::NotValidated, absl::nullopt, absl::nullopt};
678
4
  }
679
2951
  ValidationResults result =
680
2951
      cert_validator_->doVerifyCertChain(cert_chain, std::move(callback), transport_socket_options,
681
2951
                                         *ssl_ctx, validation_context, is_server, host_name);
682
2951
  return result;
683
2955
}
684

            
685
} // namespace Tls
686
} // namespace TransportSockets
687
} // namespace Extensions
688

            
689
namespace Ssl {
690

            
691
1047
bool TlsContext::isCipherEnabled(uint16_t cipher_id, uint16_t client_version) const {
692
1047
  const SSL_CIPHER* c = SSL_get_cipher_by_value(cipher_id);
693
1047
  if (c == nullptr) {
694
    return false;
695
  }
696
  // Skip TLS 1.2 only ciphersuites unless the client supports it.
697
1047
  if (SSL_CIPHER_get_min_version(c) > client_version) {
698
9
    return false;
699
9
  }
700
1038
  if (SSL_CIPHER_get_auth_nid(c) != NID_auth_ecdsa) {
701
77
    return false;
702
77
  }
703
961
  for (const SSL_CIPHER* our_c : SSL_CTX_get_ciphers(ssl_ctx_.get())) {
704
961
    if (SSL_CIPHER_get_id(our_c) == SSL_CIPHER_get_id(c)) {
705
954
      return true;
706
954
    }
707
961
  }
708
7
  return false;
709
961
}
710

            
711
absl::Status TlsContext::loadCertificateChain(const std::string& data,
712
5171
                                              const std::string& data_path) {
713
5171
  cert_chain_file_path_ = data_path;
714
5171
  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
715
5171
  RELEASE_ASSERT(bio != nullptr, "");
716
5171
  cert_chain_.reset(PEM_read_bio_X509_AUX(bio.get(), nullptr, nullptr, nullptr));
717
5171
  if (cert_chain_ == nullptr || !SSL_CTX_use_certificate(ssl_ctx_.get(), cert_chain_.get())) {
718
5
    logSslErrorChain();
719
5
    return absl::InvalidArgumentError(
720
5
        absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
721
5
  }
722
  // Read rest of the certificate chain.
723
5220
  while (true) {
724
5220
    bssl::UniquePtr<X509> cert(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
725
5220
    if (cert == nullptr) {
726
5166
      break;
727
5166
    }
728
54
    if (!SSL_CTX_add_extra_chain_cert(ssl_ctx_.get(), cert.get())) {
729
      return absl::InvalidArgumentError(
730
          absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
731
    }
732
    // SSL_CTX_add_extra_chain_cert() takes ownership.
733
54
    cert.release();
734
54
  }
735
  // Check for EOF.
736
5166
  const uint32_t err = ERR_peek_last_error();
737
5166
  if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
738
5164
    ERR_clear_error();
739
5164
  } else {
740
2
    return absl::InvalidArgumentError(
741
2
        absl::StrCat("Failed to load certificate chain from ", cert_chain_file_path_));
742
2
  }
743
5164
  return absl::OkStatus();
744
5166
}
745

            
746
absl::Status TlsContext::loadPrivateKey(const std::string& data, const std::string& data_path,
747
5140
                                        const std::string& password, bool fips_mode) {
748
5140
  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
749
5140
  RELEASE_ASSERT(bio != nullptr, "");
750
5140
  bssl::UniquePtr<EVP_PKEY> pkey(
751
5140
      PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr,
752
5140
                              !password.empty() ? const_cast<char*>(password.c_str()) : nullptr));
753

            
754
5140
  if (pkey == nullptr || !SSL_CTX_use_PrivateKey(ssl_ctx_.get(), pkey.get())) {
755
6
    return absl::InvalidArgumentError(fmt::format(
756
6
        "Failed to load private key from {}, Cause: {}", data_path,
757
6
        Extensions::TransportSockets::Tls::Utility::getLastCryptoError().value_or("unknown")));
758
6
  }
759

            
760
5134
  return checkPrivateKey(pkey, data_path, fips_mode);
761
5140
}
762

            
763
absl::Status TlsContext::loadPkcs12(const std::string& data, const std::string& data_path,
764
12
                                    const std::string& password, bool fips_mode) {
765
12
  cert_chain_file_path_ = data_path;
766
12
  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), data.size()));
767
12
  RELEASE_ASSERT(bio != nullptr, "");
768
12
  bssl::UniquePtr<PKCS12> pkcs12(d2i_PKCS12_bio(bio.get(), nullptr));
769

            
770
12
  EVP_PKEY* temp_private_key = nullptr;
771
12
  X509* temp_cert = nullptr;
772
12
  STACK_OF(X509)* temp_ca_certs = nullptr;
773
12
  if (pkcs12 == nullptr ||
774
12
      !PKCS12_parse(pkcs12.get(), !password.empty() ? const_cast<char*>(password.c_str()) : nullptr,
775
12
                    &temp_private_key, &temp_cert, &temp_ca_certs)) {
776
3
    logSslErrorChain();
777
3
    return absl::InvalidArgumentError(absl::StrCat("Failed to load pkcs12 from ", data_path));
778
3
  }
779
9
  cert_chain_.reset(temp_cert);
780
9
  bssl::UniquePtr<EVP_PKEY> pkey(temp_private_key);
781
9
  bssl::UniquePtr<STACK_OF(X509)> ca_certificates(temp_ca_certs);
782
9
  if (ca_certificates != nullptr) {
783
9
    X509* ca_cert = nullptr;
784
17
    while ((ca_cert = sk_X509_pop(ca_certificates.get())) != nullptr) {
785
      // This transfers ownership to ssl_ctx therefore ca_cert does not need to be freed.
786
8
      SSL_CTX_add_extra_chain_cert(ssl_ctx_.get(), ca_cert);
787
8
    }
788
9
  }
789
9
  if (!SSL_CTX_use_certificate(ssl_ctx_.get(), cert_chain_.get())) {
790
    logSslErrorChain();
791
    return absl::InvalidArgumentError(absl::StrCat("Failed to load certificate from ", data_path));
792
  }
793
9
  if (temp_private_key == nullptr || !SSL_CTX_use_PrivateKey(ssl_ctx_.get(), pkey.get())) {
794
    return absl::InvalidArgumentError(fmt::format(
795
        "Failed to load private key from {}, Cause: {}", data_path,
796
        Extensions::TransportSockets::Tls::Utility::getLastCryptoError().value_or("unknown")));
797
  }
798

            
799
9
  return checkPrivateKey(pkey, data_path, fips_mode);
800
9
}
801

            
802
absl::Status TlsContext::checkPrivateKey(const bssl::UniquePtr<EVP_PKEY>& pkey,
803
5143
                                         const std::string& key_path, bool fips_mode) {
804
5143
  if (fips_mode) {
805
    // Verify that private keys are passing FIPS pairwise consistency tests.
806
    switch (EVP_PKEY_id(pkey.get())) {
807
    case EVP_PKEY_EC: {
808
      const EC_KEY* ecdsa_private_key = EVP_PKEY_get0_EC_KEY(pkey.get());
809
      if (!EC_KEY_check_fips(ecdsa_private_key)) {
810
        return absl::InvalidArgumentError(
811
            fmt::format("Failed to load private key from {}, ECDSA key failed "
812
                        "pairwise consistency test required in FIPS mode",
813
                        key_path));
814
      }
815
    } break;
816
    case EVP_PKEY_RSA: {
817
      RSA* rsa_private_key = EVP_PKEY_get0_RSA(pkey.get());
818
      if (!RSA_check_fips(rsa_private_key)) {
819
        return absl::InvalidArgumentError(
820
            fmt::format("Failed to load private key from {}, RSA key failed "
821
                        "pairwise consistency test required in FIPS mode",
822
                        key_path));
823
      }
824
    } break;
825
    }
826
  }
827
5143
  return absl::OkStatus();
828
5143
}
829

            
830
} // namespace Ssl
831
} // namespace Envoy