Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
#include "tls_server_config.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include "nss_scoped_ptrs.h"
#include "pk11pub.h"
#include "prio.h"
#include "seccomon.h"
#include "ssl.h"
#include "sslexp.h"
#include "sslt.h"
#include "tls_common.h"
const SSLCertificateCompressionAlgorithm kCompressionAlg = {
0x1337, "fuzz", DummyCompressionEncode, DummyCompressionDecode};
const PRUint8 kPskIdentity[] = "fuzz-psk-identity";
static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checksig,
PRBool isServer) {
assert(isServer);
auto config = reinterpret_cast<ServerConfig*>(arg);
if (config->FailCertificateAuthentication()) return SECFailure;
return SECSuccess;
}
static SECStatus CanFalseStartCallback(PRFileDesc* fd, void* arg,
PRBool* canFalseStart) {
*canFalseStart = true;
return SECSuccess;
}
// XOR 64-bit chunks of data to build a bitmap of config options derived from
// the fuzzing input. This seems the only way to fuzz various options while
// still maintaining compatibility with BoringSSL or OpenSSL fuzzers.
ServerConfig::ServerConfig(const uint8_t* data, size_t len) {
union {
uint64_t bitmap;
struct {
uint32_t config;
uint16_t ssl_version_range_min;
uint16_t ssl_version_range_max;
};
};
for (size_t i = 0; i < len; i++) {
bitmap ^= static_cast<uint64_t>(data[i]) << (8 * (i % 8));
}
// Map SSL version values to a valid range.
ssl_version_range_min =
SSL_VERSION_RANGE_MIN_VALID +
(ssl_version_range_min %
(1 + SSL_VERSION_RANGE_MAX_VALID - SSL_VERSION_RANGE_MIN_VALID));
ssl_version_range_max =
ssl_version_range_min +
(ssl_version_range_max %
(1 + SSL_VERSION_RANGE_MAX_VALID - ssl_version_range_min));
config_ = config;
ssl_version_range_ = {
.min = ssl_version_range_min,
.max = ssl_version_range_max,
};
}
void ServerConfig::SetCallbacks(PRFileDesc* fd) {
SECStatus rv = SSL_AuthCertificateHook(fd, AuthCertificateHook, this);
assert(rv == SECSuccess);
rv = SSL_SetCanFalseStartCallback(fd, CanFalseStartCallback, nullptr);
assert(rv == SECSuccess);
}
void ServerConfig::SetSocketOptions(PRFileDesc* fd) {
SECStatus rv = SSL_OptionSet(fd, SSL_ENABLE_EXTENDED_MASTER_SECRET,
this->EnableExtendedMasterSecret());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_REQUEST_CERTIFICATE, this->RequestCertificate());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_REQUIRE_CERTIFICATE, this->RequireCertificate());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_DEFLATE, this->EnableDeflate());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_CBC_RANDOM_IV, this->EnableCbcRandomIv());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_REQUIRE_SAFE_NEGOTIATION,
this->RequireSafeNegotiation());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_NO_CACHE, this->NoCache());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_GREASE, this->EnableGrease());
assert(rv == SECSuccess);
if (this->SetCertificateCompressionAlgorithm()) {
rv = SSL_SetCertificateCompressionAlgorithm(fd, kCompressionAlg);
assert(rv == SECSuccess);
}
if (this->SetVersionRange()) {
rv = SSL_VersionRangeSet(fd, &ssl_version_range_);
assert(rv == SECSuccess);
}
if (this->AddExternalPsk()) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
assert(slot);
ScopedPK11SymKey key(PK11_KeyGen(slot.get(), CKM_NSS_CHACHA20_POLY1305,
nullptr, 32, nullptr));
assert(key);
rv = SSL_AddExternalPsk(fd, key.get(), kPskIdentity,
sizeof(kPskIdentity) - 1, this->PskHashType());
assert(rv == SECSuccess);
}
rv = SSL_OptionSet(fd, SSL_ENABLE_0RTT_DATA, this->EnableZeroRtt());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_ALPN, this->EnableAlpn());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_FALLBACK_SCSV, this->EnableFallbackScsv());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_SESSION_TICKETS,
this->EnableSessionTickets());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_NO_LOCKS, this->NoLocks());
assert(rv == SECSuccess);
#ifndef IS_DTLS_FUZZ
rv =
SSL_OptionSet(fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_UNRESTRICTED);
assert(rv == SECSuccess);
#endif
}
std::ostream& operator<<(std::ostream& out, ServerConfig& config) {
out << "============= ServerConfig ============="
<< "\n";
out << "SSL_NO_CACHE: " << config.NoCache() << "\n";
out << "SSL_ENABLE_EXTENDED_MASTER_SECRET: "
<< config.EnableExtendedMasterSecret() << "\n";
out << "SSL_REQUEST_CERTIFICATE: "
<< config.RequestCertificate() << "\n";
out << "SSL_REQUIRE_CERTIFICATE: "
<< config.RequireCertificate() << "\n";
out << "SSL_ENABLE_DEFLATE: " << config.EnableDeflate()
<< "\n";
out << "SSL_CBC_RANDOM_IV: "
<< config.EnableCbcRandomIv() << "\n";
out << "SSL_REQUIRE_SAFE_NEGOTIATION: "
<< config.RequireSafeNegotiation() << "\n";
out << "SSL_ENABLE_GREASE: " << config.EnableGrease()
<< "\n";
out << "SSL_SetCertificateCompressionAlgorithm: "
<< config.SetCertificateCompressionAlgorithm() << "\n";
out << "SSL_VersionRangeSet: " << config.SetVersionRange()
<< "\n";
out << " Min: "
<< config.SslVersionRange().min << "\n";
out << " Max: "
<< config.SslVersionRange().max << "\n";
out << "SSL_AddExternalPsk: " << config.AddExternalPsk()
<< "\n";
out << " Type: " << config.PskHashType()
<< "\n";
out << "SSL_ENABLE_0RTT_DATA: " << config.EnableZeroRtt()
<< "\n";
out << "SSL_ENABLE_ALPN: " << config.EnableAlpn()
<< "\n";
out << "SSL_ENABLE_FALLBACK_SCSV: "
<< config.EnableFallbackScsv() << "\n";
out << "SSL_ENABLE_SESSION_TICKETS: "
<< config.EnableSessionTickets() << "\n";
out << "SSL_NO_LOCKS: " << config.NoLocks() << "\n";
out << "========================================";
return out;
}