blob: 9301f2cb19b7d22e8381cac0e27ce824760e6796 [file] [log] [blame]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstddef>
#include <cstdint>
#include <vector>
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "openssl/base.h"
#include "openssl/ssl.h"
#include "quiche/quic/core/crypto/proof_source.h"
#include "quiche/quic/core/crypto/tls_connection.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/common/platform/api/quiche_export.h"
namespace quic {
// TlsServerConnection receives calls for client-specific BoringSSL callbacks
// and calls its Delegate for the implementation of those callbacks.
class QUICHE_EXPORT TlsServerConnection : public TlsConnection {
// A TlsServerConnection::Delegate implement the server-specific methods that
// are set as callbacks for an SSL object.
class QUICHE_EXPORT Delegate {
virtual ~Delegate() {}
// Called from BoringSSL right after SNI is extracted, which is very early
// in the handshake process.
virtual ssl_select_cert_result_t EarlySelectCertCallback(
const SSL_CLIENT_HELLO* client_hello) = 0;
// Called after the ClientHello extensions have been successfully parsed.
// Returns an SSL_TLSEXT_ERR_* value (see
// On success, return SSL_TLSEXT_ERR_OK causes the server_name extension to
// be acknowledged in the ServerHello, or return SSL_TLSEXT_ERR_NOACK which
// causes it to be not acknowledged.
// If the function returns SSL_TLSEXT_ERR_ALERT_FATAL, then it puts in
// |*out_alert| the TLS alert value that the server will send.
virtual int TlsExtServernameCallback(int* out_alert) = 0;
// Selects which ALPN to use based on the list sent by the client.
virtual int SelectAlpn(const uint8_t** out, uint8_t* out_len,
const uint8_t* in, unsigned in_len) = 0;
// Signs |in| using the signature algorithm specified by |sig_alg| (an
// SSL_SIGN_* value). If the signing operation cannot be completed
// synchronously, ssl_private_key_retry is returned. If there is an error
// signing, or if the signature is longer than |max_out|, then
// ssl_private_key_failure is returned. Otherwise, ssl_private_key_success
// is returned with the signature put in |*out| and the length in
// |*out_len|.
virtual ssl_private_key_result_t PrivateKeySign(uint8_t* out,
size_t* out_len,
size_t max_out,
uint16_t sig_alg,
absl::string_view in) = 0;
// When PrivateKeySign returns ssl_private_key_retry, PrivateKeyComplete
// will be called after the async sign operation has completed.
// PrivateKeyComplete puts the resulting signature in |*out| and length in
// |*out_len|. If the length is greater than |max_out| or if there was an
// error in signing, then ssl_private_key_failure is returned. Otherwise,
// ssl_private_key_success is returned.
virtual ssl_private_key_result_t PrivateKeyComplete(uint8_t* out,
size_t* out_len,
size_t max_out) = 0;
// The following functions are used to implement an SSL_TICKET_AEAD_METHOD.
// See
// for details on the BoringSSL API.
// SessionTicketMaxOverhead returns the maximum number of bytes of overhead
// that SessionTicketSeal may add when encrypting a session ticket.
virtual size_t SessionTicketMaxOverhead() = 0;
// SessionTicketSeal encrypts the session ticket in |in|, putting the
// resulting encrypted ticket in |out|, writing the length of the bytes
// written to |*out_len|, which is no larger than |max_out_len|. It returns
// 1 on success and 0 on error.
virtual int SessionTicketSeal(uint8_t* out, size_t* out_len,
size_t max_out_len, absl::string_view in) = 0;
// SessionTicketOpen is called when BoringSSL has an encrypted session
// ticket |in| and wants the ticket decrypted. This decryption operation can
// happen synchronously or asynchronously.
// If the decrypted ticket is not available at the time of the function
// call, this function returns ssl_ticket_aead_retry. If this function
// returns ssl_ticket_aead_retry, then SSL_do_handshake will return
// SSL_ERROR_PENDING_TICKET. Once the pending ticket decryption has
// completed, SSL_do_handshake needs to be called again.
// When this function is called and the decrypted ticket is available
// (either the ticket was decrypted synchronously, or an asynchronous
// operation has completed and SSL_do_handshake has been called again), the
// decrypted ticket is put in |out|, and the length of that output is
// written to |*out_len|, not to exceed |max_out_len|, and
// ssl_ticket_aead_success is returned. If the ticket cannot be decrypted
// and should be ignored, this function returns
// ssl_ticket_aead_ignore_ticket and a full handshake will be performed
// instead. If a fatal error occurs, ssl_ticket_aead_error can be returned
// which will terminate the handshake.
virtual enum ssl_ticket_aead_result_t SessionTicketOpen(
uint8_t* out, size_t* out_len, size_t max_out_len,
absl::string_view in) = 0;
// Provides the delegate for callbacks that are shared between client and
// server.
virtual TlsConnection::Delegate* ConnectionDelegate() = 0;
friend class TlsServerConnection;
TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate,
QuicSSLConfig ssl_config);
// Creates and configures an SSL_CTX that is appropriate for servers to use.
static bssl::UniquePtr<SSL_CTX> CreateSslCtx(ProofSource* proof_source);
// Invoke |configure_ssl| to configure the SSL object.
absl::Status ConfigureSSL(
ProofSourceHandleCallback::ConfigureSSLFunc configure_ssl);
void SetCertChain(const std::vector<CRYPTO_BUFFER*>& cert_chain);
// Set the client cert mode to be used on this connection. This should be
// called right after cert selection at the latest, otherwise it is too late
// to has an effect.
void SetClientCertMode(ClientCertMode client_cert_mode);
// Specialization of TlsConnection::ConnectionFromSsl.
static TlsServerConnection* ConnectionFromSsl(SSL* ssl);
static ssl_select_cert_result_t EarlySelectCertCallback(
const SSL_CLIENT_HELLO* client_hello);
// These functions are registered as callbacks in BoringSSL and delegate their
// implementation to the matching methods in Delegate above.
static int TlsExtServernameCallback(SSL* ssl, int* out_alert, void* arg);
static int SelectAlpnCallback(SSL* ssl, const uint8_t** out, uint8_t* out_len,
const uint8_t* in, unsigned in_len, void* arg);
// |kPrivateKeyMethod| is a vtable pointing to PrivateKeySign and
// PrivateKeyComplete used by the TLS stack to compute the signature for the
// CertificateVerify message (using the server's private key).
static const SSL_PRIVATE_KEY_METHOD kPrivateKeyMethod;
// The following functions make up the contents of |kPrivateKeyMethod|.
static ssl_private_key_result_t PrivateKeySign(
SSL* ssl, uint8_t* out, size_t* out_len, size_t max_out, uint16_t sig_alg,
const uint8_t* in, size_t in_len);
static ssl_private_key_result_t PrivateKeyComplete(SSL* ssl, uint8_t* out,
size_t* out_len,
size_t max_out);
// Implementation of SSL_TICKET_AEAD_METHOD which delegates to corresponding
// methods in TlsServerConnection::Delegate (a.k.a. TlsServerHandshaker).
static const SSL_TICKET_AEAD_METHOD kSessionTicketMethod;
// The following functions make up the contents of |kSessionTicketMethod|.
static size_t SessionTicketMaxOverhead(SSL* ssl);
static int SessionTicketSeal(SSL* ssl, uint8_t* out, size_t* out_len,
size_t max_out_len, const uint8_t* in,
size_t in_len);
static enum ssl_ticket_aead_result_t SessionTicketOpen(SSL* ssl, uint8_t* out,
size_t* out_len,
size_t max_out_len,
const uint8_t* in,
size_t in_len);
// Install custom verify callback on ssl() if |ssl_config().client_cert_mode|
// is not ClientCertMode::kNone. Uninstall otherwise.
void UpdateCertVerifyCallback();
Delegate* delegate_;
} // namespace quic