1 // Copyright (c) 2019 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_TLS_SERVER_CONNECTION_H_ 6 #define QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_ 7 8 #include <cstddef> 9 #include <cstdint> 10 #include <vector> 11 12 #include "absl/status/status.h" 13 #include "absl/strings/string_view.h" 14 #include "openssl/base.h" 15 #include "openssl/ssl.h" 16 #include "quiche/quic/core/crypto/proof_source.h" 17 #include "quiche/quic/core/crypto/tls_connection.h" 18 #include "quiche/quic/core/quic_types.h" 19 #include "quiche/common/platform/api/quiche_export.h" 20 21 namespace quic { 22 23 // TlsServerConnection receives calls for client-specific BoringSSL callbacks 24 // and calls its Delegate for the implementation of those callbacks. 25 class QUICHE_EXPORT TlsServerConnection : public TlsConnection { 26 public: 27 // A TlsServerConnection::Delegate implement the server-specific methods that 28 // are set as callbacks for an SSL object. 29 class QUICHE_EXPORT Delegate { 30 public: ~Delegate()31 virtual ~Delegate() {} 32 33 protected: 34 // Called from BoringSSL right after SNI is extracted, which is very early 35 // in the handshake process. 36 virtual ssl_select_cert_result_t EarlySelectCertCallback( 37 const SSL_CLIENT_HELLO* client_hello) = 0; 38 39 // Called after the ClientHello extensions have been successfully parsed. 40 // Returns an SSL_TLSEXT_ERR_* value (see 41 // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_tlsext_servername_callback). 42 // 43 // On success, return SSL_TLSEXT_ERR_OK causes the server_name extension to 44 // be acknowledged in the ServerHello, or return SSL_TLSEXT_ERR_NOACK which 45 // causes it to be not acknowledged. 46 // 47 // If the function returns SSL_TLSEXT_ERR_ALERT_FATAL, then it puts in 48 // |*out_alert| the TLS alert value that the server will send. 49 // 50 virtual int TlsExtServernameCallback(int* out_alert) = 0; 51 52 // Selects which ALPN to use based on the list sent by the client. 53 virtual int SelectAlpn(const uint8_t** out, uint8_t* out_len, 54 const uint8_t* in, unsigned in_len) = 0; 55 56 // Signs |in| using the signature algorithm specified by |sig_alg| (an 57 // SSL_SIGN_* value). If the signing operation cannot be completed 58 // synchronously, ssl_private_key_retry is returned. If there is an error 59 // signing, or if the signature is longer than |max_out|, then 60 // ssl_private_key_failure is returned. Otherwise, ssl_private_key_success 61 // is returned with the signature put in |*out| and the length in 62 // |*out_len|. 63 virtual ssl_private_key_result_t PrivateKeySign(uint8_t* out, 64 size_t* out_len, 65 size_t max_out, 66 uint16_t sig_alg, 67 absl::string_view in) = 0; 68 69 // When PrivateKeySign returns ssl_private_key_retry, PrivateKeyComplete 70 // will be called after the async sign operation has completed. 71 // PrivateKeyComplete puts the resulting signature in |*out| and length in 72 // |*out_len|. If the length is greater than |max_out| or if there was an 73 // error in signing, then ssl_private_key_failure is returned. Otherwise, 74 // ssl_private_key_success is returned. 75 virtual ssl_private_key_result_t PrivateKeyComplete(uint8_t* out, 76 size_t* out_len, 77 size_t max_out) = 0; 78 79 // The following functions are used to implement an SSL_TICKET_AEAD_METHOD. 80 // See 81 // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#ssl_ticket_aead_result_t 82 // for details on the BoringSSL API. 83 84 // SessionTicketMaxOverhead returns the maximum number of bytes of overhead 85 // that SessionTicketSeal may add when encrypting a session ticket. 86 virtual size_t SessionTicketMaxOverhead() = 0; 87 88 // SessionTicketSeal encrypts the session ticket in |in|, putting the 89 // resulting encrypted ticket in |out|, writing the length of the bytes 90 // written to |*out_len|, which is no larger than |max_out_len|. It returns 91 // 1 on success and 0 on error. 92 virtual int SessionTicketSeal(uint8_t* out, size_t* out_len, 93 size_t max_out_len, absl::string_view in) = 0; 94 95 // SessionTicketOpen is called when BoringSSL has an encrypted session 96 // ticket |in| and wants the ticket decrypted. This decryption operation can 97 // happen synchronously or asynchronously. 98 // 99 // If the decrypted ticket is not available at the time of the function 100 // call, this function returns ssl_ticket_aead_retry. If this function 101 // returns ssl_ticket_aead_retry, then SSL_do_handshake will return 102 // SSL_ERROR_PENDING_TICKET. Once the pending ticket decryption has 103 // completed, SSL_do_handshake needs to be called again. 104 // 105 // When this function is called and the decrypted ticket is available 106 // (either the ticket was decrypted synchronously, or an asynchronous 107 // operation has completed and SSL_do_handshake has been called again), the 108 // decrypted ticket is put in |out|, and the length of that output is 109 // written to |*out_len|, not to exceed |max_out_len|, and 110 // ssl_ticket_aead_success is returned. If the ticket cannot be decrypted 111 // and should be ignored, this function returns 112 // ssl_ticket_aead_ignore_ticket and a full handshake will be performed 113 // instead. If a fatal error occurs, ssl_ticket_aead_error can be returned 114 // which will terminate the handshake. 115 virtual enum ssl_ticket_aead_result_t SessionTicketOpen( 116 uint8_t* out, size_t* out_len, size_t max_out_len, 117 absl::string_view in) = 0; 118 119 // Provides the delegate for callbacks that are shared between client and 120 // server. 121 virtual TlsConnection::Delegate* ConnectionDelegate() = 0; 122 123 friend class TlsServerConnection; 124 }; 125 126 TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate, 127 QuicSSLConfig ssl_config); 128 129 // Creates and configures an SSL_CTX that is appropriate for servers to use. 130 static bssl::UniquePtr<SSL_CTX> CreateSslCtx(ProofSource* proof_source); 131 132 // Invoke |configure_ssl| to configure the SSL object. 133 absl::Status ConfigureSSL( 134 ProofSourceHandleCallback::ConfigureSSLFunc configure_ssl); 135 136 void SetCertChain(const std::vector<CRYPTO_BUFFER*>& cert_chain); 137 138 // Set the client cert mode to be used on this connection. This should be 139 // called right after cert selection at the latest, otherwise it is too late 140 // to has an effect. 141 void SetClientCertMode(ClientCertMode client_cert_mode); 142 143 private: 144 // Specialization of TlsConnection::ConnectionFromSsl. 145 static TlsServerConnection* ConnectionFromSsl(SSL* ssl); 146 147 static ssl_select_cert_result_t EarlySelectCertCallback( 148 const SSL_CLIENT_HELLO* client_hello); 149 150 // These functions are registered as callbacks in BoringSSL and delegate their 151 // implementation to the matching methods in Delegate above. 152 static int TlsExtServernameCallback(SSL* ssl, int* out_alert, void* arg); 153 static int SelectAlpnCallback(SSL* ssl, const uint8_t** out, uint8_t* out_len, 154 const uint8_t* in, unsigned in_len, void* arg); 155 156 // |kPrivateKeyMethod| is a vtable pointing to PrivateKeySign and 157 // PrivateKeyComplete used by the TLS stack to compute the signature for the 158 // CertificateVerify message (using the server's private key). 159 static const SSL_PRIVATE_KEY_METHOD kPrivateKeyMethod; 160 161 // The following functions make up the contents of |kPrivateKeyMethod|. 162 static ssl_private_key_result_t PrivateKeySign( 163 SSL* ssl, uint8_t* out, size_t* out_len, size_t max_out, uint16_t sig_alg, 164 const uint8_t* in, size_t in_len); 165 static ssl_private_key_result_t PrivateKeyComplete(SSL* ssl, uint8_t* out, 166 size_t* out_len, 167 size_t max_out); 168 169 // Implementation of SSL_TICKET_AEAD_METHOD which delegates to corresponding 170 // methods in TlsServerConnection::Delegate (a.k.a. TlsServerHandshaker). 171 static const SSL_TICKET_AEAD_METHOD kSessionTicketMethod; 172 173 // The following functions make up the contents of |kSessionTicketMethod|. 174 static size_t SessionTicketMaxOverhead(SSL* ssl); 175 static int SessionTicketSeal(SSL* ssl, uint8_t* out, size_t* out_len, 176 size_t max_out_len, const uint8_t* in, 177 size_t in_len); 178 static enum ssl_ticket_aead_result_t SessionTicketOpen(SSL* ssl, uint8_t* out, 179 size_t* out_len, 180 size_t max_out_len, 181 const uint8_t* in, 182 size_t in_len); 183 184 // Install custom verify callback on ssl() if |ssl_config().client_cert_mode| 185 // is not ClientCertMode::kNone. Uninstall otherwise. 186 void UpdateCertVerifyCallback(); 187 188 Delegate* delegate_; 189 }; 190 191 } // namespace quic 192 193 #endif // QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_ 194