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
10996
std::string generateCertificateHash(const std::string& cert_data) {
30
10996
  Buffer::OwnedImpl buffer(cert_data);
31

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

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

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

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

            
57
5154
      providers.push_back(TlsCertificateConfigProviderSharedPtrWithName{
58
5154
          cert_id,
59
5154
          factory_context.serverFactoryContext().secretManager().createInlineTlsCertificateProvider(
60
5154
              tls_certificate)});
61
5154
    }
62
5093
    return providers;
63
5093
  }
64
2005
  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
1928
  return {};
92
2005
}
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
7098
    absl::Status& creation_status) {
127
7098
  switch (config.validation_context_type_case()) {
128
5923
  case envoy::extensions::transport_sockets::tls::v3::CommonTlsContext::ValidationContextTypeCase::
129
5923
      kValidationContext: {
130
5923
    std::string ca_cert_id = "unnamed_ca_cert";
131
5923
    const auto& validation_context = config.validation_context();
132
5923
    if (validation_context.has_trusted_ca()) {
133
5855
      const std::string hash_id =
134
5855
          generateCertificateHash(validation_context.trusted_ca().inline_bytes());
135
5855
      if (!hash_id.empty()) {
136
5855
        ca_cert_id = absl::StrCat(ca_cert_id, "_", hash_id);
137
5855
      }
138
5855
    }
139
5923
    return CertificateValidationContextConfigProviderSharedPtrWithName{
140
5923
        ca_cert_id,
141
5923
        factory_context.serverFactoryContext()
142
5923
            .secretManager()
143
5923
            .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
1123
  default:
164
1123
    return {EMPTY_STRING, nullptr};
165
7098
  }
166
7098
}
167

            
168
absl::optional<envoy::extensions::transport_sockets::tls::v3::TlsParameters::CompliancePolicy>
169
compliancePolicyFromProto(
170
7098
    const envoy::extensions::transport_sockets::tls::v3::TlsParameters& params) {
171
7098
  switch (params.compliance_policies_size()) {
172
7097
  case 0:
173
7097
    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
7098
  }
180
7098
}
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
7098
    : api_(factory_context.serverFactoryContext().api()),
192
7098
      options_(factory_context.serverFactoryContext().options()),
193
7098
      singleton_manager_(factory_context.serverFactoryContext().singletonManager()),
194
7098
      lifecycle_notifier_(factory_context.serverFactoryContext().lifecycleNotifier()),
195
7098
      auto_sni_san_match_(auto_sni_san_match),
196
7098
      alpn_protocols_(RepeatedPtrUtil::join(config.alpn_protocols(), ",")),
197
7098
      cipher_suites_(StringUtil::nonEmptyStringOrDefault(
198
7098
          RepeatedPtrUtil::join(config.tls_params().cipher_suites(), ":"), default_cipher_suites)),
199
7098
      ecdh_curves_(StringUtil::nonEmptyStringOrDefault(
200
7098
          RepeatedPtrUtil::join(config.tls_params().ecdh_curves(), ":"), default_curves)),
201
7098
      signature_algorithms_(RepeatedPtrUtil::join(config.tls_params().signature_algorithms(), ":")),
202
      tls_certificate_providers_(
203
7098
          getTlsCertificateConfigProviders(config, factory_context, creation_status)),
204
7098
      certificate_validation_context_provider_(getCertificateValidationContextConfigProvider(
205
7098
          config, factory_context, &default_cvc_, creation_status)),
206
7098
      min_protocol_version_(tlsVersionFromProto(config.tls_params().tls_minimum_protocol_version(),
207
7098
                                                default_min_protocol_version)),
208
7098
      max_protocol_version_(tlsVersionFromProto(config.tls_params().tls_maximum_protocol_version(),
209
7098
                                                default_max_protocol_version)),
210
7098
      factory_context_(factory_context), tls_keylog_path_(config.key_log().path()),
211
7098
      compliance_policy_(compliancePolicyFromProto(config.tls_params())) {
212
7098
  SET_AND_RETURN_IF_NOT_OK(creation_status, creation_status);
213
7096
  auto list_or_error = Network::Address::IpList::create(config.key_log().local_address_range());
214
7096
  SET_AND_RETURN_IF_NOT_OK(list_or_error.status(), creation_status);
215
7096
  tls_keylog_local_ = std::move(list_or_error.value());
216
7096
  list_or_error = Network::Address::IpList::create(config.key_log().remote_address_range());
217
7096
  SET_AND_RETURN_IF_NOT_OK(list_or_error.status(), creation_status);
218
7096
  tls_keylog_remote_ = std::move(list_or_error.value());
219

            
220
7096
  if (certificate_validation_context_provider_.provider_ != nullptr) {
221
5974
    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
5974
    if (certificate_validation_context_provider_.provider_->secret() != nullptr) {
241
5935
      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
5931
      } else {
248
5931
        auto config_or_status = Envoy::Ssl::CertificateValidationContextConfigImpl::create(
249
5931
            *certificate_validation_context_provider_.provider_->secret(), auto_sni_san_match, api_,
250
5931
            certificate_validation_context_provider_.certificate_name_);
251
5931
        SET_AND_RETURN_IF_NOT_OK(config_or_status.status(), creation_status);
252
5918
        validation_context_config_ = std::move(config_or_status.value());
253
5918
      }
254
5935
    }
255
5974
  }
256
  // Load inlined, static or dynamic secrets that are already available.
257
7083
  if (!tls_certificate_providers_.empty()) {
258
5228
    for (auto& provider : tls_certificate_providers_) {
259
5228
      if (provider.provider_->secret() != nullptr) {
260
5152
        auto config_or_error = Ssl::TlsCertificateConfigImpl::create(
261
5152
            *provider.provider_->secret(), factory_context, api_, provider.certificate_name_);
262
5152
        SET_AND_RETURN_IF_NOT_OK(config_or_error.status(), creation_status);
263
5140
        tls_certificate_configs_.emplace_back(std::move(*config_or_error));
264
5140
      }
265
5228
    }
266
5155
  }
267

            
268
7071
  HandshakerFactoryContextImpl handshaker_factory_context(api_, options_, alpn_protocols_,
269
7071
                                                          singleton_manager_, lifecycle_notifier_);
270
7071
  Ssl::HandshakerFactory* handshaker_factory;
271
7071
  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
7071
  } else {
280
    // Otherwise, derive the config from the default factory.
281
7067
    handshaker_factory = HandshakerFactoryImpl::getDefaultHandshakerFactory();
282
7067
    handshaker_factory_cb_ = handshaker_factory->createHandshakerCb(
283
7067
        *handshaker_factory->createEmptyConfigProto(), handshaker_factory_context,
284
7067
        factory_context.messageValidationVisitor());
285
7067
  }
286
7071
  capabilities_ = handshaker_factory->capabilities();
287
7071
  sslctx_cb_ = handshaker_factory->sslctxCb(handshaker_factory_context);
288
7071
}
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
6957
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
6996
  for (const auto& tls_certificate_provider : tls_certificate_providers_) {
307
5112
    tc_update_callback_handles_.push_back(
308
5112
        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
5112
  }
322
6957
  if (certificate_validation_context_provider_.provider_) {
323
5933
    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
5921
    } else {
338
      // Once certificate_validation_context_provider_ receives new secret, this callback updates
339
      // ContextConfigImpl::validation_context_config_ with new secret.
340
5921
      cvc_update_callback_handle_ =
341
5921
          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
5921
    }
350
5933
  }
351
6957
}
352

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

            
357
unsigned ContextConfigImpl::tlsVersionFromProto(
358
    const envoy::extensions::transport_sockets::tls::v3::TlsParameters::TlsProtocol& version,
359
14196
    unsigned default_version) {
360
14196
  switch (version) {
361
    PANIC_ON_PROTO_ENUM_SENTINEL_VALUES;
362
12584
  case envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLS_AUTO:
363
12584
    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
14196
  }
373
  IS_ENVOY_BUG("unexpected tls version provided");
374
  return default_version;
375
14196
}
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
3557
    Server::Configuration::TransportSocketFactoryContext& secret_provider_context) {
400
3557
  absl::Status creation_status = absl::OkStatus();
401
3557
  std::unique_ptr<ClientContextConfigImpl> ret = absl::WrapUnique(
402
3557
      new ClientContextConfigImpl(config, secret_provider_context, creation_status));
403
3557
  RETURN_IF_NOT_OK(creation_status);
404
3550
  return ret;
405
3557
}
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
3557
    : ContextConfigImpl(
412
3557
          config.common_tls_context(), config.auto_sni_san_validation(), DEFAULT_MIN_VERSION,
413
3557
          DEFAULT_MAX_VERSION, FIPS_mode() ? DEFAULT_CIPHER_SUITES_FIPS : DEFAULT_CIPHER_SUITES,
414
3557
          FIPS_mode() ? DEFAULT_CURVES_FIPS : DEFAULT_CURVES, factory_context, creation_status),
415
3557
      server_name_indication_(config.sni()), auto_host_sni_(config.auto_host_sni()),
416
3557
      allow_renegotiation_(config.allow_renegotiation()),
417
3557
      enforce_rsa_key_usage_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, enforce_rsa_key_usage, true)),
418
3557
      max_session_keys_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, max_session_keys, 1)) {
419

            
420
3557
  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
3557
  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
3555
  if ((config.common_tls_context().tls_certificates().size() +
438
3555
       config.common_tls_context().tls_certificate_sds_secret_configs().size()) > 1 &&
439
3555
      !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
3552
  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
3552
}
459

            
460
3509
void ClientContextConfigImpl::setSecretUpdateCallback(std::function<absl::Status()> callback) {
461
3509
  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
3509
  ContextConfigImpl::setSecretUpdateCallback(callback_with_notify);
469
3509
}
470

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