blob: 6318b39b2c8ae48ed1ac1eebf09c59d302aaf33c [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 "quic/core/crypto/tls_server_connection.h"
#include "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "quic/core/crypto/proof_source.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
namespace quic {
TlsServerConnection::TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate)
: TlsConnection(ssl_ctx, delegate->ConnectionDelegate()),
delegate_(delegate) {}
// static
bssl::UniquePtr<SSL_CTX> TlsServerConnection::CreateSslCtx(
ProofSource* proof_source) {
bssl::UniquePtr<SSL_CTX> ssl_ctx =
TlsConnection::CreateSslCtx(SSL_VERIFY_NONE);
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_RESTART_FLAG_COUNT_N(quic_session_tickets_always_enabled, 1, 3);
SSL_CTX_set_ticket_aead_method(ssl_ctx.get(),
&TlsServerConnection::kSessionTicketMethod);
} else if (!GetQuicRestartFlag(quic_session_tickets_always_enabled)) {
QUIC_RESTART_FLAG_COUNT_N(quic_session_tickets_always_enabled, 2, 3);
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_NO_TICKET);
} else {
QUIC_RESTART_FLAG_COUNT_N(quic_session_tickets_always_enabled, 3, 3);
}
if (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) &&
(proof_source->GetTicketCrypter() ||
GetQuicRestartFlag(quic_session_tickets_always_enabled))) {
SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
}
SSL_CTX_set_select_certificate_cb(
ssl_ctx.get(), &TlsServerConnection::EarlySelectCertCallback);
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);
}
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