1
#include "source/common/tls/context_config_impl.h"
2

            
3
#include <memory>
4
#include <string>
5

            
6
#include "envoy/extensions/transport_sockets/tls/v3/cert.pb.h"
7

            
8
#include "source/common/common/assert.h"
9
#include "source/common/common/empty_string.h"
10
#include "source/common/config/datasource.h"
11
#include "source/common/crypto/utility.h"
12
#include "source/common/network/cidr_range.h"
13
#include "source/common/protobuf/message_validator_impl.h"
14
#include "source/common/protobuf/utility.h"
15
#include "source/common/secret/sds_api.h"
16
#include "source/common/ssl/certificate_validation_context_config_impl.h"
17
#include "source/common/tls/ssl_handshaker.h"
18

            
19
#include "openssl/crypto.h"
20
#include "openssl/ssl.h"
21

            
22
namespace Envoy {
23
namespace Extensions {
24
namespace TransportSockets {
25
namespace Tls {
26

            
27
namespace {
28

            
29
10980
std::string generateCertificateHash(const std::string& cert_data) {
30
10980
  Buffer::OwnedImpl buffer(cert_data);
31

            
32
  // Calculate SHA-256 hash of cert data and take first 8 chars
33
10980
  auto hash = Hex::encode(Envoy::Common::Crypto::UtilitySingleton::get().getSha256Digest(buffer));
34

            
35
10980
  return hash.substr(0, 8);
36
10980
}
37

            
38
std::vector<TlsCertificateConfigProviderSharedPtrWithName> getTlsCertificateConfigProviders(
39
    const envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& config,
40
    Server::Configuration::TransportSocketFactoryContext& factory_context,
41
7082
    absl::Status& creation_status) {
42
7082
  std::vector<TlsCertificateConfigProviderSharedPtrWithName> providers;
43
7082
  if (!config.tls_certificates().empty()) {
44
5147
    for (const auto& tls_certificate : config.tls_certificates()) {
45
5147
      if (!tls_certificate.has_private_key_provider() && !tls_certificate.has_certificate_chain() &&
46
5147
          !tls_certificate.has_private_key() && !tls_certificate.has_pkcs12()) {
47
1
        continue;
48
1
      }
49

            
50
5146
      std::string cert_id = "unnamed_cert_";
51
5146
      if (tls_certificate.has_certificate_chain()) {
52
5133
        const std::string hash_id =
53
5133
            generateCertificateHash(tls_certificate.certificate_chain().inline_bytes());
54
5133
        absl::StrAppend(&cert_id, hash_id);
55
5133
      }
56

            
57
5146
      providers.push_back(TlsCertificateConfigProviderSharedPtrWithName{
58
5146
          cert_id,
59
5146
          factory_context.serverFactoryContext().secretManager().createInlineTlsCertificateProvider(
60
5146
              tls_certificate)});
61
5146
    }
62
5085
    return providers;
63
5085
  }
64
1997
  if (!config.tls_certificate_sds_secret_configs().empty()) {
65
89
    for (const auto& sds_secret_config : config.tls_certificate_sds_secret_configs()) {
66
89
      if (sds_secret_config.has_sds_config()) {
67
        // Fetch dynamic secret.
68
76
        providers.push_back(TlsCertificateConfigProviderSharedPtrWithName{
69
76
            sds_secret_config.name(),
70
76
            factory_context.serverFactoryContext()
71
76
                .secretManager()
72
76
                .findOrCreateTlsCertificateProvider(
73
76
                    sds_secret_config.sds_config(), sds_secret_config.name(),
74
76
                    factory_context.serverFactoryContext(), factory_context.initManager(), true)});
75
87
      } else {
76
        // Load static secret.
77
13
        auto secret_provider =
78
13
            factory_context.serverFactoryContext().secretManager().findStaticTlsCertificateProvider(
79
13
                sds_secret_config.name());
80
13
        if (!secret_provider) {
81
1
          creation_status = absl::InvalidArgumentError(
82
1
              fmt::format("Unknown static secret: {}", sds_secret_config.name()));
83
1
          return {};
84
1
        }
85
12
        providers.push_back(TlsCertificateConfigProviderSharedPtrWithName{sds_secret_config.name(),
86
12
                                                                          secret_provider});
87
12
      }
88
89
    }
89
76
    return providers;
90
77
  }
91
1920
  return {};
92
1997
}
93

            
94
Secret::CertificateValidationContextConfigProviderSharedPtr getProviderFromSds(
95
    Server::Configuration::TransportSocketFactoryContext& factory_context,
96
    const envoy::extensions::transport_sockets::tls::v3::SdsSecretConfig& sds_secret_config,
97
52
    absl::Status& creation_status) {
98
52
  if (sds_secret_config.has_sds_config()) {
99
    // Fetch dynamic secret.
100
47
    return factory_context.serverFactoryContext()
101
47
        .secretManager()
102
47
        .findOrCreateCertificateValidationContextProvider(
103
47
            sds_secret_config.sds_config(), sds_secret_config.name(),
104
47
            factory_context.serverFactoryContext(), factory_context.initManager());
105
50
  } else {
106
    // Load static secret.
107
5
    auto secret_provider =
108
5
        factory_context.serverFactoryContext()
109
5
            .secretManager()
110
5
            .findStaticCertificateValidationContextProvider(sds_secret_config.name());
111
5
    if (secret_provider) {
112
4
      return secret_provider;
113
4
    }
114
1
    creation_status = absl::InvalidArgumentError(
115
1
        fmt::format("Unknown static certificate validation context: {}", sds_secret_config.name()));
116
1
  }
117
1
  return nullptr;
118
52
}
119

            
120
CertificateValidationContextConfigProviderSharedPtrWithName
121
getCertificateValidationContextConfigProvider(
122
    const envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& config,
123
    Server::Configuration::TransportSocketFactoryContext& factory_context,
124
    std::unique_ptr<envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext>*
125
        default_cvc,
126
7082
    absl::Status& creation_status) {
127
7082
  switch (config.validation_context_type_case()) {
128
5915
  case envoy::extensions::transport_sockets::tls::v3::CommonTlsContext::ValidationContextTypeCase::
129
5915
      kValidationContext: {
130
5915
    std::string ca_cert_id = "unnamed_ca_cert";
131
5915
    const auto& validation_context = config.validation_context();
132
5915
    if (validation_context.has_trusted_ca()) {
133
5847
      const std::string hash_id =
134
5847
          generateCertificateHash(validation_context.trusted_ca().inline_bytes());
135
5847
      if (!hash_id.empty()) {
136
5847
        ca_cert_id = absl::StrCat(ca_cert_id, "_", hash_id);
137
5847
      }
138
5847
    }
139
5915
    return CertificateValidationContextConfigProviderSharedPtrWithName{
140
5915
        ca_cert_id,
141
5915
        factory_context.serverFactoryContext()
142
5915
            .secretManager()
143
5915
            .createInlineCertificateValidationContextProvider(config.validation_context())};
144
  }
145
40
  case envoy::extensions::transport_sockets::tls::v3::CommonTlsContext::ValidationContextTypeCase::
146
40
      kValidationContextSdsSecretConfig: {
147
40
    const auto& sds_secret_config = config.validation_context_sds_secret_config();
148
40
    return CertificateValidationContextConfigProviderSharedPtrWithName{
149
40
        sds_secret_config.name(),
150
40
        getProviderFromSds(factory_context, sds_secret_config, creation_status)};
151
  }
152
12
  case envoy::extensions::transport_sockets::tls::v3::CommonTlsContext::ValidationContextTypeCase::
153
12
      kCombinedValidationContext: {
154
12
    *default_cvc = std::make_unique<
155
12
        envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext>(
156
12
        config.combined_validation_context().default_validation_context());
157
12
    const auto& sds_secret_config =
158
12
        config.combined_validation_context().validation_context_sds_secret_config();
159
12
    return CertificateValidationContextConfigProviderSharedPtrWithName{
160
12
        sds_secret_config.name(),
161
12
        getProviderFromSds(factory_context, sds_secret_config, creation_status)};
162
  }
163
1115
  default:
164
1115
    return {EMPTY_STRING, nullptr};
165
7082
  }
166
7082
}
167

            
168
absl::optional<envoy::extensions::transport_sockets::tls::v3::TlsParameters::CompliancePolicy>
169
compliancePolicyFromProto(
170
7082
    const envoy::extensions::transport_sockets::tls::v3::TlsParameters& params) {
171
7082
  switch (params.compliance_policies_size()) {
172
7081
  case 0:
173
7081
    return absl::nullopt;
174
1
  case 1:
175
1
    return params.compliance_policies(0);
176
  default:
177
    IS_ENVOY_BUG("more than one policies are not supported");
178
    return absl::nullopt;
179
7082
  }
180
7082
}
181

            
182
} // namespace
183

            
184
ContextConfigImpl::ContextConfigImpl(
185
    const envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& config,
186
    bool auto_sni_san_match, const unsigned default_min_protocol_version,
187
    const unsigned default_max_protocol_version, const std::string& default_cipher_suites,
188
    const std::string& default_curves,
189
    Server::Configuration::TransportSocketFactoryContext& factory_context,
190
    absl::Status& creation_status)
191
7082
    : api_(factory_context.serverFactoryContext().api()),
192
7082
      options_(factory_context.serverFactoryContext().options()),
193
7082
      singleton_manager_(factory_context.serverFactoryContext().singletonManager()),
194
7082
      lifecycle_notifier_(factory_context.serverFactoryContext().lifecycleNotifier()),
195
7082
      auto_sni_san_match_(auto_sni_san_match),
196
7082
      alpn_protocols_(RepeatedPtrUtil::join(config.alpn_protocols(), ",")),
197
7082
      cipher_suites_(StringUtil::nonEmptyStringOrDefault(
198
7082
          RepeatedPtrUtil::join(config.tls_params().cipher_suites(), ":"), default_cipher_suites)),
199
7082
      ecdh_curves_(StringUtil::nonEmptyStringOrDefault(
200
7082
          RepeatedPtrUtil::join(config.tls_params().ecdh_curves(), ":"), default_curves)),
201
7082
      signature_algorithms_(RepeatedPtrUtil::join(config.tls_params().signature_algorithms(), ":")),
202
      tls_certificate_providers_(
203
7082
          getTlsCertificateConfigProviders(config, factory_context, creation_status)),
204
7082
      certificate_validation_context_provider_(getCertificateValidationContextConfigProvider(
205
7082
          config, factory_context, &default_cvc_, creation_status)),
206
7082
      min_protocol_version_(tlsVersionFromProto(config.tls_params().tls_minimum_protocol_version(),
207
7082
                                                default_min_protocol_version)),
208
7082
      max_protocol_version_(tlsVersionFromProto(config.tls_params().tls_maximum_protocol_version(),
209
7082
                                                default_max_protocol_version)),
210
7082
      factory_context_(factory_context), tls_keylog_path_(config.key_log().path()),
211
7082
      compliance_policy_(compliancePolicyFromProto(config.tls_params())) {
212
7082
  SET_AND_RETURN_IF_NOT_OK(creation_status, creation_status);
213
7080
  auto list_or_error = Network::Address::IpList::create(config.key_log().local_address_range());
214
7080
  SET_AND_RETURN_IF_NOT_OK(list_or_error.status(), creation_status);
215
7080
  tls_keylog_local_ = std::move(list_or_error.value());
216
7080
  list_or_error = Network::Address::IpList::create(config.key_log().remote_address_range());
217
7080
  SET_AND_RETURN_IF_NOT_OK(list_or_error.status(), creation_status);
218
7080
  tls_keylog_remote_ = std::move(list_or_error.value());
219

            
220
7080
  if (certificate_validation_context_provider_.provider_ != nullptr) {
221
5966
    if (default_cvc_) {
222
      // We need to validate combined certificate validation context.
223
      // The default certificate validation context and dynamic certificate validation
224
      // context could only contain partial fields, which is okay to fail the validation.
225
      // But the combined certificate validation context should pass validation. If
226
      // validation of combined certificate validation context fails,
227
      // getCombinedValidationContextConfig() throws exception, validation_context_config_ will not
228
      // get updated.
229
12
      cvc_validation_callback_handle_ =
230
12
          certificate_validation_context_provider_.provider_->addValidationCallback(
231
12
              [this](
232
12
                  const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext&
233
12
                      dynamic_cvc) {
234
8
                return getCombinedValidationContextConfig(
235
8
                           dynamic_cvc, certificate_validation_context_provider_.certificate_name_)
236
8
                    .status();
237
8
              });
238
12
    }
239
    // Load inlined, static or dynamic secret that's already available.
240
5966
    if (certificate_validation_context_provider_.provider_->secret() != nullptr) {
241
5927
      if (default_cvc_) {
242
4
        auto context_or_error = getCombinedValidationContextConfig(
243
4
            *certificate_validation_context_provider_.provider_->secret(),
244
4
            certificate_validation_context_provider_.certificate_name_);
245
4
        SET_AND_RETURN_IF_NOT_OK(context_or_error.status(), creation_status);
246
4
        validation_context_config_ = std::move(*context_or_error);
247
5923
      } else {
248
5923
        auto config_or_status = Envoy::Ssl::CertificateValidationContextConfigImpl::create(
249
5923
            *certificate_validation_context_provider_.provider_->secret(), auto_sni_san_match, api_,
250
5923
            certificate_validation_context_provider_.certificate_name_);
251
5923
        SET_AND_RETURN_IF_NOT_OK(config_or_status.status(), creation_status);
252
5910
        validation_context_config_ = std::move(config_or_status.value());
253
5910
      }
254
5927
    }
255
5966
  }
256
  // Load inlined, static or dynamic secrets that are already available.
257
7067
  if (!tls_certificate_providers_.empty()) {
258
5220
    for (auto& provider : tls_certificate_providers_) {
259
5220
      if (provider.provider_->secret() != nullptr) {
260
5144
        auto config_or_error = Ssl::TlsCertificateConfigImpl::create(
261
5144
            *provider.provider_->secret(), factory_context, api_, provider.certificate_name_);
262
5144
        SET_AND_RETURN_IF_NOT_OK(config_or_error.status(), creation_status);
263
5132
        tls_certificate_configs_.emplace_back(std::move(*config_or_error));
264
5132
      }
265
5220
    }
266
5147
  }
267

            
268
7055
  HandshakerFactoryContextImpl handshaker_factory_context(api_, options_, alpn_protocols_,
269
7055
                                                          singleton_manager_, lifecycle_notifier_);
270
7055
  Ssl::HandshakerFactory* handshaker_factory;
271
7055
  if (config.has_custom_handshaker()) {
272
    // If a custom handshaker is configured, derive the factory from the config.
273
4
    const auto& handshaker_config = config.custom_handshaker();
274
4
    handshaker_factory =
275
4
        &Config::Utility::getAndCheckFactory<Ssl::HandshakerFactory>(handshaker_config);
276
4
    handshaker_factory_cb_ = handshaker_factory->createHandshakerCb(
277
4
        handshaker_config.typed_config(), handshaker_factory_context,
278
4
        factory_context.messageValidationVisitor());
279
7055
  } else {
280
    // Otherwise, derive the config from the default factory.
281
7051
    handshaker_factory = HandshakerFactoryImpl::getDefaultHandshakerFactory();
282
7051
    handshaker_factory_cb_ = handshaker_factory->createHandshakerCb(
283
7051
        *handshaker_factory->createEmptyConfigProto(), handshaker_factory_context,
284
7051
        factory_context.messageValidationVisitor());
285
7051
  }
286
7055
  capabilities_ = handshaker_factory->capabilities();
287
7055
  sslctx_cb_ = handshaker_factory->sslctxCb(handshaker_factory_context);
288
7055
}
289

            
290
absl::StatusOr<Ssl::CertificateValidationContextConfigPtr>
291
ContextConfigImpl::getCombinedValidationContextConfig(
292
    const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext& dynamic_cvc,
293
24
    const std::string& name) {
294
24
  envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext combined_cvc =
295
24
      *default_cvc_;
296
24
  combined_cvc.MergeFrom(dynamic_cvc);
297
24
  auto config_or_status = Envoy::Ssl::CertificateValidationContextConfigImpl::create(
298
24
      combined_cvc, auto_sni_san_match_, api_, name);
299
24
  RETURN_IF_NOT_OK(config_or_status.status());
300
24
  return std::move(config_or_status.value());
301
24
}
302

            
303
6941
void ContextConfigImpl::setSecretUpdateCallback(std::function<absl::Status()> callback) {
304
  // When any of tls_certificate_providers_ receives a new secret, this callback updates
305
  // ContextConfigImpl::tls_certificate_configs_ with new secret.
306
6980
  for (const auto& tls_certificate_provider : tls_certificate_providers_) {
307
5104
    tc_update_callback_handles_.push_back(
308
5104
        tls_certificate_provider.provider_->addUpdateCallback([this, callback]() {
309
76
          tls_certificate_configs_.clear();
310
108
          for (const auto& tls_certificate_provider : tls_certificate_providers_) {
311
108
            auto* secret = tls_certificate_provider.provider_->secret();
312
108
            if (secret != nullptr) {
313
92
              auto config_or_error = Ssl::TlsCertificateConfigImpl::create(
314
92
                  *secret, factory_context_, api_, tls_certificate_provider.certificate_name_);
315
92
              RETURN_IF_NOT_OK(config_or_error.status());
316
84
              tls_certificate_configs_.emplace_back(std::move(*config_or_error));
317
84
            }
318
108
          }
319
68
          return callback();
320
76
        }));
321
5104
  }
322
6941
  if (certificate_validation_context_provider_.provider_) {
323
5925
    if (default_cvc_) {
324
      // Once certificate_validation_context_provider_ receives new secret, this callback updates
325
      // ContextConfigImpl::validation_context_config_ with a combined certificate validation
326
      // context. The combined certificate validation context is created by merging new secret
327
      // into default_cvc_.
328
12
      cvc_update_callback_handle_ =
329
12
          certificate_validation_context_provider_.provider_->addUpdateCallback([this, callback]() {
330
12
            auto context_or_error = getCombinedValidationContextConfig(
331
12
                *certificate_validation_context_provider_.provider_->secret(),
332
12
                certificate_validation_context_provider_.certificate_name_);
333
12
            RETURN_IF_NOT_OK(context_or_error.status());
334
12
            validation_context_config_ = std::move(*context_or_error);
335
12
            return callback();
336
12
          });
337
5913
    } else {
338
      // Once certificate_validation_context_provider_ receives new secret, this callback updates
339
      // ContextConfigImpl::validation_context_config_ with new secret.
340
5913
      cvc_update_callback_handle_ =
341
5913
          certificate_validation_context_provider_.provider_->addUpdateCallback([this, callback]() {
342
36
            auto config_or_status = Envoy::Ssl::CertificateValidationContextConfigImpl::create(
343
36
                *certificate_validation_context_provider_.provider_->secret(), auto_sni_san_match_,
344
36
                api_, certificate_validation_context_provider_.certificate_name_);
345
36
            RETURN_IF_NOT_OK(config_or_status.status());
346
36
            validation_context_config_ = std::move(config_or_status.value());
347
36
            return callback();
348
36
          });
349
5913
    }
350
5925
  }
351
6941
}
352

            
353
2556
Ssl::HandshakerFactoryCb ContextConfigImpl::createHandshaker() const {
354
2556
  return handshaker_factory_cb_;
355
2556
}
356

            
357
unsigned ContextConfigImpl::tlsVersionFromProto(
358
    const envoy::extensions::transport_sockets::tls::v3::TlsParameters::TlsProtocol& version,
359
14164
    unsigned default_version) {
360
14164
  switch (version) {
361
    PANIC_ON_PROTO_ENUM_SENTINEL_VALUES;
362
12552
  case envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLS_AUTO:
363
12552
    return default_version;
364
19
  case envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_0:
365
19
    return TLS1_VERSION;
366
4
  case envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_1:
367
4
    return TLS1_1_VERSION;
368
361
  case envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2:
369
361
    return TLS1_2_VERSION;
370
1228
  case envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_3:
371
1228
    return TLS1_3_VERSION;
372
14164
  }
373
  IS_ENVOY_BUG("unexpected tls version provided");
374
  return default_version;
375
14164
}
376

            
377
const unsigned ClientContextConfigImpl::DEFAULT_MIN_VERSION = TLS1_2_VERSION;
378
const unsigned ClientContextConfigImpl::DEFAULT_MAX_VERSION = TLS1_2_VERSION;
379

            
380
const std::string ClientContextConfigImpl::DEFAULT_CIPHER_SUITES =
381
    "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]:"
382
    "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:"
383
    "ECDHE-ECDSA-AES256-GCM-SHA384:"
384
    "ECDHE-RSA-AES256-GCM-SHA384:";
385

            
386
const std::string ClientContextConfigImpl::DEFAULT_CIPHER_SUITES_FIPS =
387
    "ECDHE-ECDSA-AES128-GCM-SHA256:"
388
    "ECDHE-RSA-AES128-GCM-SHA256:"
389
    "ECDHE-ECDSA-AES256-GCM-SHA384:"
390
    "ECDHE-RSA-AES256-GCM-SHA384:";
391

            
392
const std::string ClientContextConfigImpl::DEFAULT_CURVES = "X25519:"
393
                                                            "P-256";
394

            
395
const std::string ClientContextConfigImpl::DEFAULT_CURVES_FIPS = "P-256";
396

            
397
absl::StatusOr<std::unique_ptr<ClientContextConfigImpl>> ClientContextConfigImpl::create(
398
    const envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext& config,
399
3549
    Server::Configuration::TransportSocketFactoryContext& secret_provider_context) {
400
3549
  absl::Status creation_status = absl::OkStatus();
401
3549
  std::unique_ptr<ClientContextConfigImpl> ret = absl::WrapUnique(
402
3549
      new ClientContextConfigImpl(config, secret_provider_context, creation_status));
403
3549
  RETURN_IF_NOT_OK(creation_status);
404
3542
  return ret;
405
3549
}
406

            
407
ClientContextConfigImpl::ClientContextConfigImpl(
408
    const envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext& config,
409
    Server::Configuration::TransportSocketFactoryContext& factory_context,
410
    absl::Status& creation_status)
411
3549
    : ContextConfigImpl(
412
3549
          config.common_tls_context(), config.auto_sni_san_validation(), DEFAULT_MIN_VERSION,
413
3549
          DEFAULT_MAX_VERSION, FIPS_mode() ? DEFAULT_CIPHER_SUITES_FIPS : DEFAULT_CIPHER_SUITES,
414
3549
          FIPS_mode() ? DEFAULT_CURVES_FIPS : DEFAULT_CURVES, factory_context, creation_status),
415
3549
      server_name_indication_(config.sni()), auto_host_sni_(config.auto_host_sni()),
416
3549
      allow_renegotiation_(config.allow_renegotiation()),
417
3549
      enforce_rsa_key_usage_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, enforce_rsa_key_usage, true)),
418
3549
      max_session_keys_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, max_session_keys, 1)) {
419

            
420
3549
  if (!enforce_rsa_key_usage_) {
421
1
    ENVOY_LOG(
422
1
        warn,
423
1
        "The 'enforce_rsa_key_usage' option is set to false, which disables the enforcement of RSA "
424
1
        "key usage. This option will be removed in the next version. The handshake will fail "
425
1
        "if the keyUsage extension is present and incompatible with the "
426
1
        "TLS usage. Please update the certificates to be compliant.");
427
1
  }
428

            
429
  // BoringSSL treats this as a C string, so embedded NULL characters will not
430
  // be handled correctly.
431
3549
  if (server_name_indication_.find('\0') != std::string::npos) {
432
2
    creation_status = absl::InvalidArgumentError("SNI names containing NULL-byte are not allowed");
433
2
    return;
434
2
  }
435

            
436
  // TODO(PiotrSikora): Support multiple TLS certificates.
437
3547
  if ((config.common_tls_context().tls_certificates().size() +
438
3547
       config.common_tls_context().tls_certificate_sds_secret_configs().size()) > 1 &&
439
3547
      !config.common_tls_context().has_custom_tls_certificate_selector()) {
440
3
    creation_status = absl::InvalidArgumentError(
441
3
        "Multiple TLS certificates are not supported for client contexts");
442
3
    return;
443
3
  }
444

            
445
3544
  if (config.common_tls_context().has_custom_tls_certificate_selector()) {
446
13
    const auto& provider_config = config.common_tls_context().custom_tls_certificate_selector();
447
13
    Ssl::UpstreamTlsCertificateSelectorConfigFactory& provider_factory =
448
13
        Config::Utility::getAndCheckFactory<Ssl::UpstreamTlsCertificateSelectorConfigFactory>(
449
13
            provider_config);
450
13
    ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig(
451
13
        provider_config.typed_config(), factory_context.messageValidationVisitor(),
452
13
        provider_factory);
453
13
    auto selector_factory = provider_factory.createUpstreamTlsCertificateSelectorFactory(
454
13
        *message, factory_context, *this);
455
13
    SET_AND_RETURN_IF_NOT_OK(selector_factory.status(), creation_status);
456
13
    tls_certificate_selector_factory_ = *std::move(selector_factory);
457
13
  }
458
3544
}
459

            
460
3501
void ClientContextConfigImpl::setSecretUpdateCallback(std::function<absl::Status()> callback) {
461
3501
  auto callback_with_notify = [this, callback] {
462
54
    RETURN_IF_NOT_OK(callback());
463
54
    if (tls_certificate_selector_factory_) {
464
2
      return tls_certificate_selector_factory_->onConfigUpdate();
465
2
    }
466
52
    return absl::OkStatus();
467
54
  };
468
3501
  ContextConfigImpl::setSecretUpdateCallback(callback_with_notify);
469
3501
}
470

            
471
} // namespace Tls
472
} // namespace TransportSockets
473
} // namespace Extensions
474
} // namespace Envoy