blob: e27d896731476d8067d03de56f70ef210b767a32 [file] [log] [blame]
// Copyright (c) 2017 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.
#ifndef QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_
#define QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_
#include <string>
#include "third_party/boringssl/src/include/openssl/pool.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters.pb.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/tls_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
// An implementation of QuicCryptoServerStream::HandshakerDelegate which uses
// TLS 1.3 for the crypto handshake protocol.
class QUIC_EXPORT_PRIVATE TlsServerHandshaker
: public QuicCryptoServerStream::HandshakerDelegate,
public TlsHandshaker {
public:
TlsServerHandshaker(QuicCryptoStream* stream,
QuicSession* session,
SSL_CTX* ssl_ctx,
ProofSource* proof_source);
TlsServerHandshaker(const TlsServerHandshaker&) = delete;
TlsServerHandshaker& operator=(const TlsServerHandshaker&) = delete;
~TlsServerHandshaker() override;
// Creates and configures an SSL_CTX to be used with a TlsServerHandshaker.
// The caller is responsible for ownership of the newly created struct.
static bssl::UniquePtr<SSL_CTX> CreateSslCtx();
// From QuicCryptoServerStream::HandshakerDelegate
void CancelOutstandingCallbacks() override;
bool GetBase64SHA256ClientChannelID(std::string* output) const override;
void SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) override;
uint8_t NumHandshakeMessages() const override;
uint8_t NumHandshakeMessagesWithServerNonces() const override;
int NumServerConfigUpdateMessagesSent() const override;
const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
bool ZeroRttAttempted() const override;
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
bool ShouldSendExpectCTHeader() const override;
// From QuicCryptoServerStream::HandshakerDelegate and TlsHandshaker
bool encryption_established() const override;
bool handshake_confirmed() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
// Calls SelectCertificate after looking up the TlsServerHandshaker from
// |ssl|.
static int SelectCertificateCallback(SSL* ssl, int* out_alert, void* arg);
// Calls SelectAlpn after looking up the TlsServerHandshaker from |ssl|.
static int SelectAlpnCallback(SSL* ssl,
const uint8_t** out,
uint8_t* out_len,
const uint8_t* in,
unsigned in_len,
void* arg);
private:
class SignatureCallback : public ProofSource::SignatureCallback {
public:
explicit SignatureCallback(TlsServerHandshaker* handshaker);
void Run(bool ok, std::string signature) override;
// If called, Cancel causes the pending callback to be a no-op.
void Cancel();
private:
TlsServerHandshaker* handshaker_;
};
enum State {
STATE_LISTENING,
STATE_SIGNATURE_PENDING,
STATE_SIGNATURE_COMPLETE,
STATE_HANDSHAKE_COMPLETE,
STATE_CONNECTION_CLOSED,
};
// |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;
// Called when a new message is received on the crypto stream and is available
// for the TLS stack to read.
void AdvanceHandshake() override;
void CloseConnection(QuicErrorCode error,
const std::string& reason_phrase) override;
// Called when the TLS handshake is complete.
void FinishHandshake();
void CloseConnection(const std::string& reason_phrase);
bool SetTransportParameters();
bool ProcessTransportParameters(std::string* error_details);
// Calls the instance method PrivateKeySign after looking up the
// TlsServerHandshaker from |ssl|.
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);
// 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|.
ssl_private_key_result_t PrivateKeySign(uint8_t* out,
size_t* out_len,
size_t max_out,
uint16_t sig_alg,
QuicStringPiece in);
// Calls the instance method PrivateKeyComplete after looking up the
// TlsServerHandshaker from |ssl|.
static ssl_private_key_result_t PrivateKeyComplete(SSL* ssl,
uint8_t* out,
size_t* out_len,
size_t max_out);
// 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.
ssl_private_key_result_t PrivateKeyComplete(uint8_t* out,
size_t* out_len,
size_t max_out);
// Configures the certificate to use on |ssl_| based on the SNI sent by the
// client. Returns an SSL_TLSEXT_ERR_* value (see
// https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_tlsext_servername_callback).
//
// If SelectCertificate returns SSL_TLSEXT_ERR_ALERT_FATAL, then it puts in
// |*out_alert| the TLS alert value that the server will send.
int SelectCertificate(int* out_alert);
// Selects which ALPN to use based on the list sent by the client.
int SelectAlpn(const uint8_t** out,
uint8_t* out_len,
const uint8_t* in,
unsigned in_len);
static TlsServerHandshaker* HandshakerFromSsl(SSL* ssl);
State state_ = STATE_LISTENING;
ProofSource* proof_source_;
SignatureCallback* signature_callback_ = nullptr;
std::string hostname_;
std::string cert_verify_sig_;
bool encryption_established_ = false;
bool handshake_confirmed_ = false;
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
crypto_negotiated_params_;
};
} // namespace quic
#endif // QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_