1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef QUICHE_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_ 6 #define QUICHE_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_ 7 8 #include <cstddef> 9 #include <cstdint> 10 #include <memory> 11 #include <optional> 12 #include <string> 13 #include <vector> 14 15 #include "absl/status/status.h" 16 #include "absl/strings/string_view.h" 17 #include "absl/types/variant.h" 18 #include "openssl/base.h" 19 #include "openssl/pool.h" 20 #include "openssl/ssl.h" 21 #include "quiche/quic/core/crypto/certificate_view.h" 22 #include "quiche/quic/core/crypto/quic_crypto_proof.h" 23 #include "quiche/quic/core/quic_connection_id.h" 24 #include "quiche/quic/core/quic_types.h" 25 #include "quiche/quic/core/quic_versions.h" 26 #include "quiche/quic/platform/api/quic_socket_address.h" 27 #include "quiche/common/platform/api/quiche_export.h" 28 #include "quiche/common/platform/api/quiche_reference_counted.h" 29 30 namespace quic { 31 32 namespace test { 33 class FakeProofSourceHandle; 34 } // namespace test 35 36 // CryptoBuffers is a RAII class to own a std::vector<CRYPTO_BUFFER*> and the 37 // buffers the elements point to. 38 struct QUICHE_EXPORT CryptoBuffers { 39 CryptoBuffers() = default; 40 CryptoBuffers(const CryptoBuffers&) = delete; 41 CryptoBuffers(CryptoBuffers&&) = default; 42 ~CryptoBuffers(); 43 44 std::vector<CRYPTO_BUFFER*> value; 45 }; 46 47 // ProofSource is an interface by which a QUIC server can obtain certificate 48 // chains and signatures that prove its identity. 49 class QUICHE_EXPORT ProofSource { 50 public: 51 // Chain is a reference-counted wrapper for a vector of stringified 52 // certificates. 53 struct QUICHE_EXPORT Chain : public quiche::QuicheReferenceCounted { 54 explicit Chain(const std::vector<std::string>& certs); 55 Chain(const Chain&) = delete; 56 Chain& operator=(const Chain&) = delete; 57 58 CryptoBuffers ToCryptoBuffers() const; 59 60 const std::vector<std::string> certs; 61 62 protected: 63 ~Chain() override; 64 }; 65 66 // Details is an abstract class which acts as a container for any 67 // implementation-specific details that a ProofSource wants to return. 68 class QUICHE_EXPORT Details { 69 public: ~Details()70 virtual ~Details() {} 71 }; 72 73 // Callback base class for receiving the results of an async call to GetProof. 74 class QUICHE_EXPORT Callback { 75 public: Callback()76 Callback() {} ~Callback()77 virtual ~Callback() {} 78 79 // Invoked upon completion of GetProof. 80 // 81 // |ok| indicates whether the operation completed successfully. If false, 82 // the values of the remaining three arguments are undefined. 83 // 84 // |chain| is a reference-counted pointer to an object representing the 85 // certificate chain. 86 // 87 // |signature| contains the signature of the server config. 88 // 89 // |leaf_cert_sct| holds the signed timestamp (RFC6962) of the leaf cert. 90 // 91 // |details| holds a pointer to an object representing the statistics, if 92 // any, gathered during the operation of GetProof. If no stats are 93 // available, this will be nullptr. 94 virtual void Run(bool ok, 95 const quiche::QuicheReferenceCountedPointer<Chain>& chain, 96 const QuicCryptoProof& proof, 97 std::unique_ptr<Details> details) = 0; 98 99 private: 100 Callback(const Callback&) = delete; 101 Callback& operator=(const Callback&) = delete; 102 }; 103 104 // Base class for signalling the completion of a call to ComputeTlsSignature. 105 class QUICHE_EXPORT SignatureCallback { 106 public: SignatureCallback()107 SignatureCallback() {} 108 virtual ~SignatureCallback() = default; 109 110 // Invoked upon completion of ComputeTlsSignature. 111 // 112 // |ok| indicates whether the operation completed successfully. 113 // 114 // |signature| contains the signature of the data provided to 115 // ComputeTlsSignature. Its value is undefined if |ok| is false. 116 // 117 // |details| holds a pointer to an object representing the statistics, if 118 // any, gathered during the operation of ComputeTlsSignature. If no stats 119 // are available, this will be nullptr. 120 virtual void Run(bool ok, std::string signature, 121 std::unique_ptr<Details> details) = 0; 122 123 private: 124 SignatureCallback(const SignatureCallback&) = delete; 125 SignatureCallback& operator=(const SignatureCallback&) = delete; 126 }; 127 ~ProofSource()128 virtual ~ProofSource() {} 129 130 // OnNewSslCtx changes SSL parameters if required by ProofSource 131 // implementation. It is called when new SSL_CTX is created for a listener. 132 // Default implementation does nothing. 133 // 134 // This function may be called concurrently. 135 virtual void OnNewSslCtx(SSL_CTX* ssl_ctx); 136 137 // GetProof finds a certificate chain for |hostname| (in leaf-first order), 138 // and calculates a signature of |server_config| using that chain. 139 // 140 // The signature uses SHA-256 as the hash function and PSS padding when the 141 // key is RSA. 142 // 143 // The signature uses SHA-256 as the hash function when the key is ECDSA. 144 // The signature may use an ECDSA key. 145 // 146 // The signature depends on |chlo_hash| which means that the signature can not 147 // be cached. 148 // 149 // |hostname| may be empty to signify that a default certificate should be 150 // used. 151 // 152 // This function may be called concurrently. 153 // 154 // Callers should expect that |callback| might be invoked synchronously. 155 virtual void GetProof(const QuicSocketAddress& server_address, 156 const QuicSocketAddress& client_address, 157 const std::string& hostname, 158 const std::string& server_config, 159 QuicTransportVersion transport_version, 160 absl::string_view chlo_hash, 161 std::unique_ptr<Callback> callback) = 0; 162 163 // Returns the certificate chain for |hostname| in leaf-first order. 164 // 165 // Sets *cert_matched_sni to true if the certificate matched the given 166 // hostname, false if a default cert not matching the hostname was used. 167 virtual quiche::QuicheReferenceCountedPointer<Chain> GetCertChain( 168 const QuicSocketAddress& server_address, 169 const QuicSocketAddress& client_address, const std::string& hostname, 170 bool* cert_matched_sni) = 0; 171 172 // Computes a signature using the private key of the certificate for 173 // |hostname|. The value in |in| is signed using the algorithm specified by 174 // |signature_algorithm|, which is an |SSL_SIGN_*| value (as defined in TLS 175 // 1.3). Implementations can only assume that |in| is valid during the call to 176 // ComputeTlsSignature - an implementation computing signatures asynchronously 177 // must copy it if the value to be signed is used outside of this function. 178 // 179 // Callers should expect that |callback| might be invoked synchronously. 180 virtual void ComputeTlsSignature( 181 const QuicSocketAddress& server_address, 182 const QuicSocketAddress& client_address, const std::string& hostname, 183 uint16_t signature_algorithm, absl::string_view in, 184 std::unique_ptr<SignatureCallback> callback) = 0; 185 186 // Return the list of TLS signature algorithms that is acceptable by the 187 // ComputeTlsSignature method. If the entire BoringSSL's default list of 188 // supported signature algorithms are acceptable, return an empty list. 189 // 190 // If returns a non-empty list, ComputeTlsSignature will only be called with a 191 // algorithm in the list. 192 virtual QuicSignatureAlgorithmVector SupportedTlsSignatureAlgorithms() 193 const = 0; 194 195 class QUICHE_EXPORT DecryptCallback { 196 public: 197 DecryptCallback() = default; 198 virtual ~DecryptCallback() = default; 199 200 virtual void Run(std::vector<uint8_t> plaintext) = 0; 201 202 private: 203 DecryptCallback(const Callback&) = delete; 204 DecryptCallback& operator=(const Callback&) = delete; 205 }; 206 207 // TicketCrypter is an interface for managing encryption and decryption of TLS 208 // session tickets. A TicketCrypter gets used as an 209 // SSL_CTX_set_ticket_aead_method in BoringSSL, which has a synchronous 210 // Encrypt/Seal operation and a potentially asynchronous Decrypt/Open 211 // operation. This interface allows for ticket decryptions to be performed on 212 // a remote service. 213 class QUICHE_EXPORT TicketCrypter { 214 public: 215 TicketCrypter() = default; 216 virtual ~TicketCrypter() = default; 217 218 // MaxOverhead returns the maximum number of bytes of overhead that may get 219 // added when encrypting the ticket. 220 virtual size_t MaxOverhead() = 0; 221 222 // Encrypt takes a serialized TLS session ticket in |in|, encrypts it, and 223 // returns the encrypted ticket. The resulting value must not be larger than 224 // MaxOverhead bytes larger than |in|. If encryption fails, this method 225 // returns an empty vector. 226 // 227 // If |encryption_key| is nonempty, this method should use it for minting 228 // TLS resumption tickets. If it is empty, this method may use an 229 // internally cached encryption key, if available. 230 virtual std::vector<uint8_t> Encrypt(absl::string_view in, 231 absl::string_view encryption_key) = 0; 232 233 // Decrypt takes an encrypted ticket |in|, decrypts it, and calls 234 // |callback->Run| with the decrypted ticket, which must not be larger than 235 // |in|. If decryption fails, the callback is invoked with an empty 236 // vector. 237 virtual void Decrypt(absl::string_view in, 238 std::shared_ptr<DecryptCallback> callback) = 0; 239 }; 240 241 // Returns the TicketCrypter used for encrypting and decrypting TLS 242 // session tickets, or nullptr if that functionality is not supported. The 243 // TicketCrypter returned (if not nullptr) must be valid for the lifetime of 244 // the ProofSource, and the caller does not take ownership of said 245 // TicketCrypter. 246 virtual TicketCrypter* GetTicketCrypter() = 0; 247 }; 248 249 // ProofSourceHandleCallback is an interface that contains the callbacks when 250 // the operations in ProofSourceHandle completes. 251 // TODO(wub): Consider deprecating ProofSource by moving all functionalities of 252 // ProofSource into ProofSourceHandle. 253 class QUICHE_EXPORT ProofSourceHandleCallback { 254 public: 255 virtual ~ProofSourceHandleCallback() = default; 256 257 // Configuration to use for configuring the SSL object when handshaking 258 // locally. 259 struct LocalSSLConfig { 260 const ProofSource::Chain* chain; 261 QuicDelayedSSLConfig delayed_ssl_config; 262 }; 263 264 // Functor to call to configure the SSL object. This functor must not be 265 // called more than once. 266 using ConfigureSSLFunc = 267 std::function<absl::Status(SSL& ssl, const SSL_PRIVATE_KEY_METHOD& key)>; 268 269 // Configuration to use for configuring the SSL object when using a 270 // handshake-hints server. 271 struct HintsSSLConfig { 272 ConfigureSSLFunc configure_ssl; 273 QuicDelayedSSLConfig delayed_ssl_config; 274 }; 275 276 using SSLConfig = absl::variant<LocalSSLConfig, HintsSSLConfig>; 277 278 // Called when a ProofSourceHandle::SelectCertificate operation completes. 279 // |ok| indicates whether the operation was successful. 280 // |is_sync| indicates whether the operation completed synchronously, i.e. 281 // whether it is completed before ProofSourceHandle::SelectCertificate 282 // returned. 283 // |ssl_config| configuration used to configure the SSL object. 284 // |ticket_encryption_key| (optional) encryption key to be used for minting 285 // TLS resumption tickets. 286 // |cert_matched_sni| is true if the certificate matched the SNI hostname, 287 // false if a non-matching default cert was used. 288 // 289 // When called asynchronously(is_sync=false), this method will be responsible 290 // to continue the handshake from where it left off. 291 virtual void OnSelectCertificateDone(bool ok, bool is_sync, 292 SSLConfig ssl_config, 293 absl::string_view ticket_encryption_key, 294 bool cert_matched_sni) = 0; 295 296 // Called when a ProofSourceHandle::ComputeSignature operation completes. 297 virtual void OnComputeSignatureDone( 298 bool ok, bool is_sync, std::string signature, 299 std::unique_ptr<ProofSource::Details> details) = 0; 300 301 // Return true iff ProofSourceHandle::ComputeSignature won't be called later. 302 // The handle can use this function to release resources promptly. 303 virtual bool WillNotCallComputeSignature() const = 0; 304 }; 305 306 // ProofSourceHandle is an interface by which a TlsServerHandshaker can obtain 307 // certificate chains and signatures that prove its identity. 308 // The operations this interface supports are similar to those in ProofSource, 309 // the main difference is that ProofSourceHandle is per-handshaker, so 310 // an implementation can have states that are shared by multiple calls on the 311 // same handle. 312 // 313 // A handle object is owned by a TlsServerHandshaker. Since there might be an 314 // async operation pending when the handle destructs, an implementation must 315 // ensure when such operations finish, their corresponding callback method won't 316 // be invoked. 317 // 318 // A handle will have at most one async operation pending at a time. 319 class QUICHE_EXPORT ProofSourceHandle { 320 public: 321 virtual ~ProofSourceHandle() = default; 322 323 // Close the handle. Cancel the pending operation, if any. 324 // Once called, any completion method on |callback()| won't be invoked, and 325 // future SelectCertificate and ComputeSignature calls should return failure. 326 virtual void CloseHandle() = 0; 327 328 // Starts a select certificate operation. If the operation is not cancelled 329 // when it completes, callback()->OnSelectCertificateDone will be invoked. 330 // 331 // server_address and client_address should be normalized by the caller before 332 // sending down to this function. 333 // 334 // If the operation is handled synchronously: 335 // - QUIC_SUCCESS or QUIC_FAILURE will be returned. 336 // - callback()->OnSelectCertificateDone should be invoked before the function 337 // returns. 338 // 339 // If the operation is handled asynchronously: 340 // - QUIC_PENDING will be returned. 341 // - When the operation is done, callback()->OnSelectCertificateDone should be 342 // invoked. 343 virtual QuicAsyncStatus SelectCertificate( 344 const QuicSocketAddress& server_address, 345 const QuicSocketAddress& client_address, 346 const QuicConnectionId& original_connection_id, 347 absl::string_view ssl_capabilities, const std::string& hostname, 348 absl::string_view client_hello, const std::string& alpn, 349 std::optional<std::string> alps, 350 const std::vector<uint8_t>& quic_transport_params, 351 const std::optional<std::vector<uint8_t>>& early_data_context, 352 const QuicSSLConfig& ssl_config) = 0; 353 354 // Starts a compute signature operation. If the operation is not cancelled 355 // when it completes, callback()->OnComputeSignatureDone will be invoked. 356 // 357 // See the comments of SelectCertificate for sync vs. async operations. 358 virtual QuicAsyncStatus ComputeSignature( 359 const QuicSocketAddress& server_address, 360 const QuicSocketAddress& client_address, const std::string& hostname, 361 uint16_t signature_algorithm, absl::string_view in, 362 size_t max_signature_size) = 0; 363 364 protected: 365 // Returns the object that will be notified when an operation completes. 366 virtual ProofSourceHandleCallback* callback() = 0; 367 368 private: 369 friend class test::FakeProofSourceHandle; 370 }; 371 372 // Returns true if |chain| contains a parsable DER-encoded X.509 leaf cert and 373 // it matches with |key|. 374 QUICHE_EXPORT bool ValidateCertAndKey( 375 const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain, 376 const CertificatePrivateKey& key); 377 378 } // namespace quic 379 380 #endif // QUICHE_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_ 381