blob: ed7e5b238fe57b61ad3e3d6b49f74d95d0a4655b [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 "quiche/quic/core/crypto/tls_server_connection.h"
#include "absl/strings/string_view.h"
#include "openssl/ssl.h"
#include "quiche/quic/core/crypto/proof_source.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/platform/api/quic_flag_utils.h"
#include "quiche/quic/platform/api/quic_flags.h"
namespace quic {
TlsServerConnection::TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate,
QuicSSLConfig ssl_config)
: TlsConnection(ssl_ctx, delegate->ConnectionDelegate(),
std::move(ssl_config)),
delegate_(delegate) {
// By default, cert verify callback is not installed on ssl(), so only need to
// UpdateCertVerifyCallback() if client_cert_mode is not kNone.
if (TlsConnection::ssl_config().client_cert_mode != ClientCertMode::kNone) {
UpdateCertVerifyCallback();
}
}
// static
bssl::UniquePtr<SSL_CTX> TlsServerConnection::CreateSslCtx(
ProofSource* proof_source) {
bssl::UniquePtr<SSL_CTX> ssl_ctx = TlsConnection::CreateSslCtx();
// Server does not request/verify client certs by default. Individual server
// connections may call SSL_set_custom_verify on their SSL object to request
// client certs.
SSL_CTX_set_tlsext_servername_callback(ssl_ctx.get(),
&TlsExtServernameCallback);
SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), &SelectAlpnCallback, nullptr);
// We don't actually need the TicketCrypter here, but we need to know
// whether it's set.
if (proof_source->GetTicketCrypter()) {
QUIC_CODE_COUNT(quic_session_tickets_enabled);
SSL_CTX_set_ticket_aead_method(ssl_ctx.get(),
&TlsServerConnection::kSessionTicketMethod);
} else {
QUIC_CODE_COUNT(quic_session_tickets_disabled);
}
SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
SSL_CTX_set_select_certificate_cb(
ssl_ctx.get(), &TlsServerConnection::EarlySelectCertCallback);
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
return ssl_ctx;
}
void TlsServerConnection::SetCertChain(
const std::vector<CRYPTO_BUFFER*>& cert_chain) {
SSL_set_chain_and_key(ssl(), cert_chain.data(), cert_chain.size(), nullptr,
&TlsServerConnection::kPrivateKeyMethod);
}
void TlsServerConnection::SetClientCertMode(ClientCertMode client_cert_mode) {
if (ssl_config().client_cert_mode == client_cert_mode) {
return;
}
mutable_ssl_config().client_cert_mode = client_cert_mode;
UpdateCertVerifyCallback();
}
void TlsServerConnection::UpdateCertVerifyCallback() {
const ClientCertMode client_cert_mode = ssl_config().client_cert_mode;
if (client_cert_mode == ClientCertMode::kNone) {
SSL_set_custom_verify(ssl(), SSL_VERIFY_NONE, nullptr);
return;
}
int mode = SSL_VERIFY_PEER;
if (client_cert_mode == ClientCertMode::kRequire) {
mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
} else {
QUICHE_DCHECK_EQ(client_cert_mode, ClientCertMode::kRequest);
}
SSL_set_custom_verify(ssl(), mode, &VerifyCallback);
}
const SSL_PRIVATE_KEY_METHOD TlsServerConnection::kPrivateKeyMethod{
&TlsServerConnection::PrivateKeySign,
nullptr, // decrypt
&TlsServerConnection::PrivateKeyComplete,
};
// static
TlsServerConnection* TlsServerConnection::ConnectionFromSsl(SSL* ssl) {
return static_cast<TlsServerConnection*>(
TlsConnection::ConnectionFromSsl(ssl));
}
// static
ssl_select_cert_result_t TlsServerConnection::EarlySelectCertCallback(
const SSL_CLIENT_HELLO* client_hello) {
return ConnectionFromSsl(client_hello->ssl)
->delegate_->EarlySelectCertCallback(client_hello);
}
// static
int TlsServerConnection::TlsExtServernameCallback(SSL* ssl, int* out_alert,
void* /*arg*/) {
return ConnectionFromSsl(ssl)->delegate_->TlsExtServernameCallback(out_alert);
}
// static
int TlsServerConnection::SelectAlpnCallback(SSL* ssl, const uint8_t** out,
uint8_t* out_len, const uint8_t* in,
unsigned in_len, void* /*arg*/) {
return ConnectionFromSsl(ssl)->delegate_->SelectAlpn(out, out_len, in,
in_len);
}
// static
ssl_private_key_result_t TlsServerConnection::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) {
return ConnectionFromSsl(ssl)->delegate_->PrivateKeySign(
out, out_len, max_out, sig_alg,
absl::string_view(reinterpret_cast<const char*>(in), in_len));
}
// static
ssl_private_key_result_t TlsServerConnection::PrivateKeyComplete(
SSL* ssl, uint8_t* out, size_t* out_len, size_t max_out) {
return ConnectionFromSsl(ssl)->delegate_->PrivateKeyComplete(out, out_len,
max_out);
}
// static
const SSL_TICKET_AEAD_METHOD TlsServerConnection::kSessionTicketMethod{
TlsServerConnection::SessionTicketMaxOverhead,
TlsServerConnection::SessionTicketSeal,
TlsServerConnection::SessionTicketOpen,
};
// static
size_t TlsServerConnection::SessionTicketMaxOverhead(SSL* ssl) {
return ConnectionFromSsl(ssl)->delegate_->SessionTicketMaxOverhead();
}
// static
int TlsServerConnection::SessionTicketSeal(SSL* ssl, uint8_t* out,
size_t* out_len, size_t max_out_len,
const uint8_t* in, size_t in_len) {
return ConnectionFromSsl(ssl)->delegate_->SessionTicketSeal(
out, out_len, max_out_len,
absl::string_view(reinterpret_cast<const char*>(in), in_len));
}
// static
enum ssl_ticket_aead_result_t TlsServerConnection::SessionTicketOpen(
SSL* ssl, uint8_t* out, size_t* out_len, size_t max_out_len,
const uint8_t* in, size_t in_len) {
return ConnectionFromSsl(ssl)->delegate_->SessionTicketOpen(
out, out_len, max_out_len,
absl::string_view(reinterpret_cast<const char*>(in), in_len));
}
} // namespace quic