1
#pragma once
2

            
3
#include <openssl/safestack.h>
4

            
5
#include <array>
6
#include <deque>
7
#include <functional>
8
#include <memory>
9
#include <string>
10
#include <vector>
11

            
12
#include "envoy/network/transport_socket.h"
13
#include "envoy/ssl/context.h"
14
#include "envoy/ssl/context_config.h"
15
#include "envoy/ssl/private_key/private_key.h"
16
#include "envoy/ssl/ssl_socket_extended_info.h"
17
#include "envoy/stats/scope.h"
18
#include "envoy/stats/stats_macros.h"
19

            
20
#include "source/common/common/matchers.h"
21
#include "source/common/stats/symbol_table.h"
22
#include "source/common/tls/cert_validator/cert_validator.h"
23
#include "source/common/tls/context_manager_impl.h"
24
#include "source/common/tls/stats.h"
25

            
26
#include "absl/synchronization/mutex.h"
27
#include "openssl/ssl.h"
28
#include "openssl/x509v3.h"
29

            
30
#ifdef ENVOY_ENABLE_QUIC
31
#include "quiche/quic/core/crypto/proof_source.h"
32
#endif
33

            
34
namespace Envoy {
35
#if !defined OPENSSL_IS_BORINGSSL && !defined OPENSSL_IS_AWSLC
36
#error Envoy requires BoringSSL
37
#endif
38

            
39
namespace Ssl {
40

            
41
const int EC_CURVE_INVALID_NID = -1;
42

            
43
struct TlsContext {
44
  // Each certificate specified for the context has its own SSL_CTX. `SSL_CTXs`
45
  // are identical with the exception of certificate material, and can be
46
  // safely substituted via SSL_set_SSL_CTX() during the
47
  // SSL_CTX_set_select_certificate_cb() callback following ClientHello.
48
  bssl::UniquePtr<SSL_CTX> ssl_ctx_;
49
  bssl::UniquePtr<X509> cert_chain_;
50
  std::string cert_chain_file_path_;
51
  std::unique_ptr<OcspResponseWrapper> ocsp_response_;
52
  // We initialize the curve name variable to EC_CURVE_INVALID_NID which is used as a sentinel value
53
  // for "not an ECDSA context".
54
  CurveNID ec_group_curve_name_ = EC_CURVE_INVALID_NID;
55
  bool is_must_staple_{};
56
  Ssl::PrivateKeyMethodProviderSharedPtr private_key_method_provider_{};
57

            
58
#ifdef ENVOY_ENABLE_QUIC
59
  quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> quic_cert_;
60
  std::shared_ptr<quic::CertificatePrivateKey> quic_private_key_;
61
#endif
62

            
63
5
  std::string getCertChainFileName() const { return cert_chain_file_path_; };
64
  bool isCipherEnabled(uint16_t cipher_id, uint16_t client_version) const;
65
5133
  Envoy::Ssl::PrivateKeyMethodProviderSharedPtr getPrivateKeyMethodProvider() {
66
5133
    return private_key_method_provider_;
67
5133
  }
68
  absl::Status loadCertificateChain(const std::string& data, const std::string& data_path);
69
  absl::Status loadPrivateKey(const std::string& data, const std::string& data_path,
70
                              const std::string& password, bool fips_mode);
71
  absl::Status loadPkcs12(const std::string& data, const std::string& data_path,
72
                          const std::string& password, bool fips_mode);
73
  absl::Status checkPrivateKey(const bssl::UniquePtr<EVP_PKEY>& pkey, const std::string& key_path,
74
                               bool fips_mode);
75
};
76
} // namespace Ssl
77

            
78
namespace Extensions {
79
namespace TransportSockets {
80
namespace Tls {
81

            
82
class ContextImpl : public virtual Envoy::Ssl::Context,
83
                    protected Logger::Loggable<Logger::Id::config> {
84
public:
85
  virtual absl::StatusOr<bssl::UniquePtr<SSL>>
86
  newSsl(const Network::TransportSocketOptionsConstSharedPtr& options,
87
         Upstream::HostDescriptionConstSharedPtr host);
88

            
89
  /**
90
   * Logs successful TLS handshake and updates stats.
91
   * @param ssl the connection to log
92
   */
93
  void logHandshake(SSL* ssl) const;
94

            
95
1421
  SslStats& stats() { return stats_; }
96

            
97
  /**
98
   * The global SSL-library index used for storing a pointer to the SslExtendedSocketInfo
99
   * class in the SSL instance, for retrieval in callbacks.
100
   */
101
  static int sslExtendedSocketInfoIndex();
102

            
103
  static int sslSocketIndex();
104
  // Ssl::Context
105
  absl::optional<uint32_t> daysUntilFirstCertExpires() const override;
106
  Envoy::Ssl::CertificateDetailsPtr getCaCertInformation() const override;
107
  std::vector<Envoy::Ssl::CertificateDetailsPtr> getCertChainInformation() const override;
108
  absl::optional<uint64_t> secondsUntilFirstOcspResponseExpires() const override;
109

            
110
  std::vector<Ssl::PrivateKeyMethodProviderSharedPtr> getPrivateKeyMethodProviders();
111

            
112
  // Validate cert asynchronously for a QUIC connection.
113
  ValidationResults customVerifyCertChainForQuic(
114
      STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server,
115
      const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options,
116
      const CertValidator::ExtraValidationContext& validation_context,
117
      const std::string& host_name);
118

            
119
  static void keylogCallback(const SSL* ssl, const char* line);
120

            
121
protected:
122
  friend class ContextImplPeer;
123

            
124
  ContextImpl(
125
      Stats::Scope& scope, const Envoy::Ssl::ContextConfig& config,
126
      const std::vector<std::reference_wrapper<const Ssl::TlsCertificateConfig>>& tls_certificates,
127
      Server::Configuration::CommonFactoryContext& factory_context,
128
      Ssl::ContextAdditionalInitFunc additional_init, absl::Status& creation_status);
129

            
130
  /**
131
   * The global SSL-library index used for storing a pointer to the context
132
   * in the SSL instance, for retrieval in callbacks.
133
   */
134
  static int sslContextIndex();
135

            
136
  // A SSL_CTX_set_custom_verify callback for asynchronous cert validation.
137
  static enum ssl_verify_result_t customVerifyCallback(SSL* ssl, uint8_t* out_alert);
138

            
139
  bool parseAndSetAlpn(const std::vector<std::string>& alpn, SSL& ssl, absl::Status& parse_status);
140
  std::vector<uint8_t> parseAlpnProtocols(const std::string& alpn_protocols,
141
                                          absl::Status& parse_status);
142

            
143
  void incCounter(const Stats::StatName name, absl::string_view value,
144
                  const Stats::StatName fallback) const;
145

            
146
  // Helper function to validate cert for TCP connections asynchronously.
147
  ValidationResults customVerifyCertChain(
148
      Envoy::Ssl::SslExtendedSocketInfo* extended_socket_info,
149
      const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, SSL* ssl);
150

            
151
  void populateServerNamesMap(Ssl::TlsContext& ctx, const int pkey_id);
152

            
153
  // This is always non-empty, with the first context used for all new SSL
154
  // objects. For server contexts, once we have ClientHello, we
155
  // potentially switch to a different CertificateContext based on certificate
156
  // selection.
157
  std::vector<Ssl::TlsContext> tls_contexts_;
158
  CertValidatorPtr cert_validator_;
159
  Stats::Scope& scope_;
160
  SslStats stats_;
161
  std::vector<uint8_t> parsed_alpn_protocols_;
162
  bssl::UniquePtr<X509> cert_chain_;
163
  std::string cert_chain_file_path_;
164
  Server::Configuration::CommonFactoryContext& factory_context_;
165
  const unsigned tls_max_version_;
166
  mutable Stats::StatNameSetPtr stat_name_set_;
167
  const Stats::StatName unknown_ssl_cipher_;
168
  const Stats::StatName unknown_ssl_curve_;
169
  const Stats::StatName unknown_ssl_algorithm_;
170
  const Stats::StatName unknown_ssl_version_;
171
  const Stats::StatName ssl_ciphers_;
172
  const Stats::StatName ssl_versions_;
173
  const Stats::StatName ssl_curves_;
174
  const Stats::StatName ssl_sigalgs_;
175
  const Ssl::HandshakerCapabilities capabilities_;
176
  const Network::Address::IpList tls_keylog_local_;
177
  const Network::Address::IpList tls_keylog_remote_;
178
  AccessLog::AccessLogFileSharedPtr tls_keylog_file_;
179
};
180

            
181
using ContextImplSharedPtr = std::shared_ptr<ContextImpl>;
182

            
183
class ServerContextFactory : public Envoy::Config::UntypedFactory {
184
public:
185
1066
  std::string category() const override { return "envoy.ssl.server_context_factory"; }
186
  virtual absl::StatusOr<Ssl::ServerContextSharedPtr>
187
  createServerContext(Stats::Scope& scope, const Envoy::Ssl::ServerContextConfig& config,
188
                      Server::Configuration::CommonFactoryContext& factory_context,
189
                      Ssl::ContextAdditionalInitFunc additional_init) PURE;
190
};
191

            
192
} // namespace Tls
193
} // namespace TransportSockets
194
} // namespace Extensions
195
} // namespace Envoy