1
#include "source/common/tls/server_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/network/cidr_range.h"
12
#include "source/common/protobuf/message_validator_impl.h"
13
#include "source/common/protobuf/utility.h"
14
#include "source/common/secret/sds_api.h"
15
#include "source/common/ssl/certificate_validation_context_config_impl.h"
16
#include "source/common/tls/default_tls_certificate_selector.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
Secret::TlsSessionTicketKeysConfigProviderSharedPtr getTlsSessionTicketKeysConfigProvider(
30
    Server::Configuration::TransportSocketFactoryContext& factory_context,
31
    const envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext& config,
32
3540
    absl::Status& creation_status) {
33
3540
  switch (config.session_ticket_keys_type_case()) {
34
50
  case envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::
35
50
      SessionTicketKeysTypeCase::kSessionTicketKeys:
36
50
    return factory_context.serverFactoryContext()
37
50
        .secretManager()
38
50
        .createInlineTlsSessionTicketKeysProvider(config.session_ticket_keys());
39
2
  case envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::
40
2
      SessionTicketKeysTypeCase::kSessionTicketKeysSdsSecretConfig: {
41
2
    const auto& sds_secret_config = config.session_ticket_keys_sds_secret_config();
42
2
    if (sds_secret_config.has_sds_config()) {
43
      // Fetch dynamic secret.
44
1
      return factory_context.serverFactoryContext()
45
1
          .secretManager()
46
1
          .findOrCreateTlsSessionTicketKeysContextProvider(
47
1
              sds_secret_config.sds_config(), sds_secret_config.name(),
48
1
              factory_context.serverFactoryContext(), factory_context.initManager());
49
1
    } else {
50
      // Load static secret.
51
1
      auto secret_provider =
52
1
          factory_context.serverFactoryContext()
53
1
              .secretManager()
54
1
              .findStaticTlsSessionTicketKeysContextProvider(sds_secret_config.name());
55
1
      if (secret_provider) {
56
1
        return secret_provider;
57
1
      }
58
      creation_status = absl::InvalidArgumentError(
59
          fmt::format("Unknown tls session ticket keys: {}", sds_secret_config.name()));
60
      return nullptr;
61
1
    }
62
2
  }
63
19
  case envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::
64
19
      SessionTicketKeysTypeCase::kDisableStatelessSessionResumption:
65
3488
  case envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::
66
3488
      SessionTicketKeysTypeCase::SESSION_TICKET_KEYS_TYPE_NOT_SET:
67
3488
    return nullptr;
68
  default:
69
    creation_status = absl::InvalidArgumentError(
70
        fmt::format("Unexpected case for oneof session_ticket_keys: {}",
71
                    static_cast<int>(config.session_ticket_keys_type_case())));
72
    return nullptr;
73
3540
  }
74
3540
}
75

            
76
bool getStatelessSessionResumptionDisabled(
77
3540
    const envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext& config) {
78
3540
  if (config.session_ticket_keys_type_case() ==
79
3540
      envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::
80
3540
          SessionTicketKeysTypeCase::kDisableStatelessSessionResumption) {
81
19
    return config.disable_stateless_session_resumption();
82
3525
  } else {
83
3521
    return false;
84
3521
  }
85
3540
}
86

            
87
} // namespace
88

            
89
const unsigned ServerContextConfigImpl::DEFAULT_MIN_VERSION = TLS1_2_VERSION;
90
const unsigned ServerContextConfigImpl::DEFAULT_MAX_VERSION = TLS1_3_VERSION;
91

            
92
const std::string ServerContextConfigImpl::DEFAULT_CIPHER_SUITES =
93
    "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]:"
94
    "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:"
95
    "ECDHE-ECDSA-AES256-GCM-SHA384:"
96
    "ECDHE-RSA-AES256-GCM-SHA384:";
97

            
98
const std::string ServerContextConfigImpl::DEFAULT_CIPHER_SUITES_FIPS =
99
    "ECDHE-ECDSA-AES128-GCM-SHA256:"
100
    "ECDHE-RSA-AES128-GCM-SHA256:"
101
    "ECDHE-ECDSA-AES256-GCM-SHA384:"
102
    "ECDHE-RSA-AES256-GCM-SHA384:";
103

            
104
const std::string ServerContextConfigImpl::DEFAULT_CURVES = "X25519:"
105
                                                            "P-256";
106

            
107
const std::string ServerContextConfigImpl::DEFAULT_CURVES_FIPS = "P-256";
108

            
109
absl::StatusOr<std::unique_ptr<ServerContextConfigImpl>> ServerContextConfigImpl::create(
110
    const envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext& config,
111
    Server::Configuration::TransportSocketFactoryContext& secret_provider_context,
112
3541
    const std::vector<std::string>& server_names, bool for_quic) {
113
3541
  absl::Status creation_status = absl::OkStatus();
114
3541
  std::unique_ptr<ServerContextConfigImpl> ret = absl::WrapUnique(new ServerContextConfigImpl(
115
3541
      config, secret_provider_context, creation_status, server_names, for_quic));
116
3541
  RETURN_IF_NOT_OK(creation_status);
117
3507
  return ret;
118
3541
}
119

            
120
ServerContextConfigImpl::ServerContextConfigImpl(
121
    const envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext& config,
122
    Server::Configuration::TransportSocketFactoryContext& factory_context,
123
    absl::Status& creation_status, const std::vector<std::string>& server_names, bool for_quic)
124
3541
    : ContextConfigImpl(
125
3541
          config.common_tls_context(), false /* auto_sni_san_match */, DEFAULT_MIN_VERSION,
126
3541
          DEFAULT_MAX_VERSION, FIPS_mode() ? DEFAULT_CIPHER_SUITES_FIPS : DEFAULT_CIPHER_SUITES,
127
3541
          FIPS_mode() ? DEFAULT_CURVES_FIPS : DEFAULT_CURVES, factory_context, creation_status),
128
3541
      server_names_(server_names), require_client_certificate_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(
129
                                       config, require_client_certificate, false)),
130
3541
      ocsp_staple_policy_(ocspStaplePolicyFromProto(config.ocsp_staple_policy())),
131
      session_ticket_keys_provider_(
132
3541
          getTlsSessionTicketKeysConfigProvider(factory_context, config, creation_status)),
133
3541
      disable_stateless_session_resumption_(getStatelessSessionResumptionDisabled(config)),
134
3541
      disable_stateful_session_resumption_(config.disable_stateful_session_resumption()),
135
      full_scan_certs_on_sni_mismatch_(
136
3541
          PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, full_scan_certs_on_sni_mismatch, false)),
137
3541
      prefer_client_ciphers_(config.prefer_client_ciphers()) {
138
3541
  SET_AND_RETURN_IF_NOT_OK(creation_status, creation_status);
139
3517
  if (session_ticket_keys_provider_ != nullptr) {
140
    // Validate tls session ticket keys early to reject bad sds updates.
141
52
    stk_validation_callback_handle_ = session_ticket_keys_provider_->addValidationCallback(
142
52
        [this](const envoy::extensions::transport_sockets::tls::v3::TlsSessionTicketKeys& keys) {
143
          return getSessionTicketKeys(keys).status();
144
        });
145
    // Load inlined, static or dynamic secret that's already available.
146
52
    if (session_ticket_keys_provider_->secret() != nullptr) {
147
51
      auto keys_or_error = getSessionTicketKeys(*session_ticket_keys_provider_->secret());
148
51
      SET_AND_RETURN_IF_NOT_OK(keys_or_error.status(), creation_status);
149
45
      session_ticket_keys_ = *keys_or_error;
150
45
    }
151
52
  }
152

            
153
3511
  if (!capabilities().provides_certificates) {
154
3509
    if ((config.common_tls_context().tls_certificates().size() +
155
3509
         config.common_tls_context().tls_certificate_sds_secret_configs().size()) == 0 &&
156
3509
        !config.common_tls_context().has_custom_tls_certificate_selector()) {
157
2
      creation_status = absl::InvalidArgumentError("No TLS certificates found for server context");
158
3507
    } else if (!config.common_tls_context().tls_certificates().empty() &&
159
3507
               !config.common_tls_context().tls_certificate_sds_secret_configs().empty()) {
160
1
      creation_status = absl::InvalidArgumentError(
161
1
          "SDS and non-SDS TLS certificates may not be mixed in server contexts");
162
1
      return;
163
1
    }
164
3509
  }
165

            
166
3510
  if (config.has_session_timeout()) {
167
2
    session_timeout_ =
168
2
        std::chrono::seconds(DurationUtil::durationToSeconds(config.session_timeout()));
169
2
  }
170

            
171
3510
  if (!config.has_require_client_certificate() &&
172
3510
      config.common_tls_context().validation_context_type_case() !=
173
3474
          envoy::extensions::transport_sockets::tls::v3::CommonTlsContext::
174
3474
              ValidationContextTypeCase::VALIDATION_CONTEXT_TYPE_NOT_SET) {
175
2744
    ENVOY_LOG_MISC(
176
2744
        warn,
177
2744
        "Using deprecated insecure default of not requiring client cert when a validation context "
178
2744
        "is configured. This default will be changed in a future version. Please explicitly "
179
2744
        "configure a value for require_client_certificate.");
180
2744
    factory_context.serverFactoryContext().runtime().countDeprecatedFeatureUse();
181
2744
  }
182

            
183
3510
  if (config.common_tls_context().has_custom_tls_certificate_selector()) {
184
    // If a custom tls context provider is configured, derive the factory from the config.
185
23
    const auto& provider_config = config.common_tls_context().custom_tls_certificate_selector();
186
23
    Ssl::TlsCertificateSelectorConfigFactory& provider_factory =
187
23
        Config::Utility::getAndCheckFactory<Ssl::TlsCertificateSelectorConfigFactory>(
188
23
            provider_config);
189
23
    ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig(
190
23
        provider_config.typed_config(), factory_context.messageValidationVisitor(),
191
23
        provider_factory);
192
23
    auto selector_factory = provider_factory.createTlsCertificateSelectorFactory(
193
23
        *message, factory_context, *this, for_quic);
194
23
    SET_AND_RETURN_IF_NOT_OK(selector_factory.status(), creation_status);
195
22
    tls_certificate_selector_factory_ = *std::move(selector_factory);
196
3491
  } else {
197
3487
    auto factory =
198
3487
        TlsCertificateSelectorConfigFactoryImpl::getDefaultTlsCertificateSelectorConfigFactory();
199
3487
    const Protobuf::Any any;
200
3487
    auto selector_factory =
201
3487
        factory->createTlsCertificateSelectorFactory(any, factory_context, *this, for_quic);
202
3487
    SET_AND_RETURN_IF_NOT_OK(selector_factory.status(), creation_status);
203
3487
    tls_certificate_selector_factory_ = *std::move(selector_factory);
204
3487
  }
205
3510
}
206

            
207
3448
void ServerContextConfigImpl::setSecretUpdateCallback(std::function<absl::Status()> callback) {
208
3448
  auto callback_with_notify = [this, callback] {
209
62
    RETURN_IF_NOT_OK(callback());
210
62
    return tls_certificate_selector_factory_->onConfigUpdate();
211
62
  };
212
3448
  ContextConfigImpl::setSecretUpdateCallback(callback_with_notify);
213
3448
  if (session_ticket_keys_provider_) {
214
    // Once session_ticket_keys_ receives new secret, this callback updates
215
    // ContextConfigImpl::session_ticket_keys_ with new session ticket keys.
216
42
    stk_update_callback_handle_ =
217
42
        session_ticket_keys_provider_->addUpdateCallback([this, callback_with_notify]() {
218
          auto keys_or_error = getSessionTicketKeys(*session_ticket_keys_provider_->secret());
219
          RETURN_IF_NOT_OK(keys_or_error.status());
220
          session_ticket_keys_ = *keys_or_error;
221
          return callback_with_notify();
222
        });
223
42
  }
224
3448
}
225

            
226
absl::StatusOr<std::vector<Ssl::ServerContextConfig::SessionTicketKey>>
227
ServerContextConfigImpl::getSessionTicketKeys(
228
51
    const envoy::extensions::transport_sockets::tls::v3::TlsSessionTicketKeys& keys) {
229
51
  std::vector<Ssl::ServerContextConfig::SessionTicketKey> result;
230
52
  for (const auto& datasource : keys.keys()) {
231
52
    auto datasource_or_error = Config::DataSource::read(datasource, false, api_);
232
52
    RETURN_IF_NOT_OK(datasource_or_error.status());
233
51
    auto key_or_error = getSessionTicketKey(std::move(*datasource_or_error));
234
51
    RETURN_IF_NOT_OK(key_or_error.status());
235
46
    result.emplace_back(std::move(*key_or_error));
236
46
  }
237
45
  return result;
238
51
}
239

            
240
// Extracts a SessionTicketKey from raw binary data.
241
// Throws if key_data is invalid.
242
absl::StatusOr<Ssl::ServerContextConfig::SessionTicketKey>
243
51
ServerContextConfigImpl::getSessionTicketKey(const std::string& key_data) {
244
  // If this changes, need to figure out how to deal with key files
245
  // that previously worked. For now, just assert so we'll notice that
246
  // it changed if it does.
247
51
  static_assert(sizeof(SessionTicketKey) == 80, "Input is expected to be this size");
248

            
249
51
  if (key_data.size() != sizeof(SessionTicketKey)) {
250
5
    return absl::InvalidArgumentError(fmt::format("Incorrect TLS session ticket key length. "
251
5
                                                  "Length {}, expected length {}.",
252
5
                                                  key_data.size(), sizeof(SessionTicketKey)));
253
5
  }
254

            
255
46
  SessionTicketKey dst_key;
256

            
257
46
  std::copy_n(key_data.begin(), dst_key.name_.size(), dst_key.name_.begin());
258
46
  size_t pos = dst_key.name_.size();
259
46
  std::copy_n(key_data.begin() + pos, dst_key.hmac_key_.size(), dst_key.hmac_key_.begin());
260
46
  pos += dst_key.hmac_key_.size();
261
46
  std::copy_n(key_data.begin() + pos, dst_key.aes_key_.size(), dst_key.aes_key_.begin());
262
46
  pos += dst_key.aes_key_.size();
263
46
  ASSERT(key_data.begin() + pos == key_data.end());
264

            
265
46
  return dst_key;
266
51
}
267

            
268
Ssl::ServerContextConfig::OcspStaplePolicy ServerContextConfigImpl::ocspStaplePolicyFromProto(
269
    const envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::OcspStaplePolicy&
270
3540
        policy) {
271
3540
  switch (policy) {
272
    PANIC_ON_PROTO_ENUM_SENTINEL_VALUES;
273
3526
  case envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::LENIENT_STAPLING:
274
3526
    return Ssl::ServerContextConfig::OcspStaplePolicy::LenientStapling;
275
2
  case envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::STRICT_STAPLING:
276
2
    return Ssl::ServerContextConfig::OcspStaplePolicy::StrictStapling;
277
12
  case envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::MUST_STAPLE:
278
12
    return Ssl::ServerContextConfig::OcspStaplePolicy::MustStaple;
279
3540
  }
280
  PANIC_DUE_TO_CORRUPT_ENUM;
281
}
282

            
283
3475
Ssl::TlsCertificateSelectorFactory& ServerContextConfigImpl::tlsCertificateSelectorFactory() const {
284
3475
  if (!tls_certificate_selector_factory_) {
285
    IS_ENVOY_BUG("No envoy.tls.certificate_selectors registered");
286
  }
287
3475
  return *tls_certificate_selector_factory_;
288
3475
}
289

            
290
} // namespace Tls
291
} // namespace TransportSockets
292
} // namespace Extensions
293
} // namespace Envoy