Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/tls/context_impl.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef OPENSSL_IS_BORINGSSL
36
#error Envoy requires BoringSSL
37
#endif
38
39
namespace Ssl {
40
41
struct TlsContext {
42
  // Each certificate specified for the context has its own SSL_CTX. `SSL_CTXs`
43
  // are identical with the exception of certificate material, and can be
44
  // safely substituted via SSL_set_SSL_CTX() during the
45
  // SSL_CTX_set_select_certificate_cb() callback following ClientHello.
46
  bssl::UniquePtr<SSL_CTX> ssl_ctx_;
47
  bssl::UniquePtr<X509> cert_chain_;
48
  std::string cert_chain_file_path_;
49
  std::unique_ptr<OcspResponseWrapper> ocsp_response_;
50
  bool is_ecdsa_{};
51
  bool is_must_staple_{};
52
  Ssl::PrivateKeyMethodProviderSharedPtr private_key_method_provider_{};
53
54
#ifdef ENVOY_ENABLE_QUIC
55
  quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> quic_cert_;
56
  std::shared_ptr<quic::CertificatePrivateKey> quic_private_key_;
57
#endif
58
59
0
  std::string getCertChainFileName() const { return cert_chain_file_path_; };
60
  bool isCipherEnabled(uint16_t cipher_id, uint16_t client_version) const;
61
0
  Envoy::Ssl::PrivateKeyMethodProviderSharedPtr getPrivateKeyMethodProvider() {
62
0
    return private_key_method_provider_;
63
0
  }
64
  absl::Status loadCertificateChain(const std::string& data, const std::string& data_path);
65
  absl::Status loadPrivateKey(const std::string& data, const std::string& data_path,
66
                              const std::string& password);
67
  absl::Status loadPkcs12(const std::string& data, const std::string& data_path,
68
                          const std::string& password);
69
  absl::Status checkPrivateKey(const bssl::UniquePtr<EVP_PKEY>& pkey, const std::string& key_path);
70
};
71
} // namespace Ssl
72
73
namespace Extensions {
74
namespace TransportSockets {
75
namespace Tls {
76
77
class ContextImpl : public virtual Envoy::Ssl::Context,
78
                    protected Logger::Loggable<Logger::Id::config> {
79
public:
80
  virtual absl::StatusOr<bssl::UniquePtr<SSL>>
81
  newSsl(const Network::TransportSocketOptionsConstSharedPtr& options);
82
83
  /**
84
   * Logs successful TLS handshake and updates stats.
85
   * @param ssl the connection to log
86
   */
87
  void logHandshake(SSL* ssl) const;
88
89
0
  SslStats& stats() { return stats_; }
90
91
  /**
92
   * The global SSL-library index used for storing a pointer to the SslExtendedSocketInfo
93
   * class in the SSL instance, for retrieval in callbacks.
94
   */
95
  static int sslExtendedSocketInfoIndex();
96
97
  static int sslSocketIndex();
98
  // Ssl::Context
99
  absl::optional<uint32_t> daysUntilFirstCertExpires() const override;
100
  Envoy::Ssl::CertificateDetailsPtr getCaCertInformation() const override;
101
  std::vector<Envoy::Ssl::CertificateDetailsPtr> getCertChainInformation() const override;
102
  absl::optional<uint64_t> secondsUntilFirstOcspResponseExpires() const override;
103
104
  std::vector<Ssl::PrivateKeyMethodProviderSharedPtr> getPrivateKeyMethodProviders();
105
106
  // Validate cert asynchronously for a QUIC connection.
107
  ValidationResults customVerifyCertChainForQuic(
108
      STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server,
109
      const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options,
110
      const CertValidator::ExtraValidationContext& validation_context,
111
      const std::string& host_name);
112
113
  static void keylogCallback(const SSL* ssl, const char* line);
114
115
protected:
116
  friend class ContextImplPeer;
117
118
  ContextImpl(Stats::Scope& scope, const Envoy::Ssl::ContextConfig& config,
119
              Server::Configuration::CommonFactoryContext& factory_context,
120
              Ssl::ContextAdditionalInitFunc additional_init, absl::Status& creation_status);
121
122
  /**
123
   * The global SSL-library index used for storing a pointer to the context
124
   * in the SSL instance, for retrieval in callbacks.
125
   */
126
  static int sslContextIndex();
127
128
  // A SSL_CTX_set_custom_verify callback for asynchronous cert validation.
129
  static enum ssl_verify_result_t customVerifyCallback(SSL* ssl, uint8_t* out_alert);
130
131
  bool parseAndSetAlpn(const std::vector<std::string>& alpn, SSL& ssl, absl::Status& parse_status);
132
  std::vector<uint8_t> parseAlpnProtocols(const std::string& alpn_protocols,
133
                                          absl::Status& parse_status);
134
135
  void incCounter(const Stats::StatName name, absl::string_view value,
136
                  const Stats::StatName fallback) const;
137
138
  // Helper function to validate cert for TCP connections asynchronously.
139
  ValidationResults customVerifyCertChain(
140
      Envoy::Ssl::SslExtendedSocketInfo* extended_socket_info,
141
      const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, SSL* ssl);
142
143
  void populateServerNamesMap(Ssl::TlsContext& ctx, const int pkey_id);
144
145
  // This is always non-empty, with the first context used for all new SSL
146
  // objects. For server contexts, once we have ClientHello, we
147
  // potentially switch to a different CertificateContext based on certificate
148
  // selection.
149
  std::vector<Ssl::TlsContext> tls_contexts_;
150
  CertValidatorPtr cert_validator_;
151
  Stats::Scope& scope_;
152
  SslStats stats_;
153
  std::vector<uint8_t> parsed_alpn_protocols_;
154
  bssl::UniquePtr<X509> cert_chain_;
155
  std::string cert_chain_file_path_;
156
  Server::Configuration::CommonFactoryContext& factory_context_;
157
  const unsigned tls_max_version_;
158
  mutable Stats::StatNameSetPtr stat_name_set_;
159
  const Stats::StatName unknown_ssl_cipher_;
160
  const Stats::StatName unknown_ssl_curve_;
161
  const Stats::StatName unknown_ssl_algorithm_;
162
  const Stats::StatName unknown_ssl_version_;
163
  const Stats::StatName ssl_ciphers_;
164
  const Stats::StatName ssl_versions_;
165
  const Stats::StatName ssl_curves_;
166
  const Stats::StatName ssl_sigalgs_;
167
  const Ssl::HandshakerCapabilities capabilities_;
168
  const Network::Address::IpList tls_keylog_local_;
169
  const Network::Address::IpList tls_keylog_remote_;
170
  AccessLog::AccessLogFileSharedPtr tls_keylog_file_;
171
};
172
173
using ContextImplSharedPtr = std::shared_ptr<ContextImpl>;
174
175
class ServerContextFactory : public Envoy::Config::UntypedFactory {
176
public:
177
56
  std::string category() const override { return "envoy.ssl.server_context_factory"; }
178
  virtual absl::StatusOr<Ssl::ServerContextSharedPtr>
179
  createServerContext(Stats::Scope& scope, const Envoy::Ssl::ServerContextConfig& config,
180
                      const std::vector<std::string>& server_names,
181
                      Server::Configuration::CommonFactoryContext& factory_context,
182
                      Ssl::ContextAdditionalInitFunc additional_init) PURE;
183
};
184
185
} // namespace Tls
186
} // namespace TransportSockets
187
} // namespace Extensions
188
} // namespace Envoy