Commit 6f334b7d authored by Tim Taubert's avatar Tim Taubert

Bug 1310991 - Fuzzing mode: Disable session ticket encryption and MAC checks r=franziskus

Differential Revision: https://nss-review.dev.mozaws.net/D254
parent 878c48cf
......@@ -363,10 +363,12 @@
[ 'fuzz_tls==1', {
'cflags': [
'-Wno-unused-function',
'-Wno-unused-variable',
],
'xcode_settings': {
'OTHER_CFLAGS': [
'-Wno-unused-function',
'-Wno-unused-variable',
],
},
}],
......
......@@ -226,4 +226,101 @@ FUZZ_P(TlsConnectGeneric, BogusClientAuthSignature) {
std::make_shared<TlsSignatureDamager>(kTlsHandshakeCertificateVerify));
Connect();
}
// Check that session ticket resumption works.
FUZZ_P(TlsConnectGeneric, SessionTicketResumption) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
Connect();
SendReceive();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
ExpectResumption(RESUME_TICKET);
Connect();
SendReceive();
}
class TlsSessionTicketMacDamager : public TlsExtensionFilter {
public:
TlsSessionTicketMacDamager() {}
virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
const DataBuffer& input,
DataBuffer* output) {
if (extension_type != ssl_session_ticket_xtn &&
extension_type != ssl_tls13_pre_shared_key_xtn) {
return KEEP;
}
*output = input;
// Handle everything before TLS 1.3.
if (extension_type == ssl_session_ticket_xtn) {
// Modify the last byte of the MAC.
output->data()[output->len() - 1] ^= 0xff;
}
// Handle TLS 1.3.
if (extension_type == ssl_tls13_pre_shared_key_xtn) {
TlsParser parser(input);
uint32_t ids_len;
EXPECT_TRUE(parser.Read(&ids_len, 2) && ids_len > 0);
uint32_t ticket_len;
EXPECT_TRUE(parser.Read(&ticket_len, 2) && ticket_len > 0);
// Modify the last byte of the MAC.
output->data()[2 + 2 + ticket_len - 1] ^= 0xff;
}
return CHANGE;
}
};
// Check that session ticket resumption works with a bad MAC.
FUZZ_P(TlsConnectGeneric, SessionTicketResumptionBadMac) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
Connect();
SendReceive();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
ExpectResumption(RESUME_TICKET);
client_->SetPacketFilter(std::make_shared<TlsSessionTicketMacDamager>());
Connect();
SendReceive();
}
// Check that session tickets are not encrypted.
FUZZ_P(TlsConnectGeneric, UnencryptedSessionTickets) {
ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
auto i1 = std::make_shared<TlsInspectorRecordHandshakeMessage>(
kTlsHandshakeNewSessionTicket);
server_->SetPacketFilter(i1);
Connect();
size_t offset = 4; /* lifetime */
if (version_ == SSL_LIBRARY_VERSION_TLS_1_3) {
offset += 1 + 1 + /* ke_modes */
1 + 1; /* auth_modes */
}
offset += 2 + /* ticket length */
16 + /* SESS_TICKET_KEY_NAME_LEN */
16 + /* AES-128 IV */
2 + /* ciphertext length */
2; /* TLS_EX_SESS_TICKET_VERSION */
// Check the protocol version number.
uint32_t tls_version;
EXPECT_TRUE(i1->buffer().Read(offset, sizeof(version_), &tls_version));
EXPECT_EQ(version_, static_cast<decltype(version_)>(tls_version));
// Check the cipher suite.
uint32_t suite;
EXPECT_TRUE(i1->buffer().Read(offset + sizeof(version_), 2, &suite));
client_->CheckCipherSuite(static_cast<uint16_t>(suite));
}
}
......@@ -241,6 +241,10 @@ bool TlsAgent::GetPeerChainLength(size_t* count) {
return true;
}
void TlsAgent::CheckCipherSuite(uint16_t cipher_suite) {
EXPECT_EQ(csinfo_.cipherSuite, cipher_suite);
}
void TlsAgent::RequestClientAuth(bool requireAuth) {
EXPECT_TRUE(EnsureTlsSetup());
ASSERT_EQ(SERVER, role_);
......
......@@ -163,6 +163,7 @@ class TlsAgent : public PollTarget {
void ConfigNamedGroups(const std::vector<SSLNamedGroup>& groups);
void DisableECDHEServerKeyReuse();
bool GetPeerChainLength(size_t* count);
void CheckCipherSuite(uint16_t cipher_suite);
const std::string& name() const { return name_; }
......
......@@ -26,6 +26,7 @@ const uint8_t kTlsApplicationDataType = 23;
const uint8_t kTlsHandshakeClientHello = 1;
const uint8_t kTlsHandshakeServerHello = 2;
const uint8_t kTlsHandshakeNewSessionTicket = 4;
const uint8_t kTlsHandshakeHelloRetryRequest = 6;
const uint8_t kTlsHandshakeEncryptedExtensions = 8;
const uint8_t kTlsHandshakeCertificate = 11;
......
......@@ -1004,9 +1004,13 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
+ sizeof(ticket->ticket_lifetime_hint) /* ticket lifetime hint */
+ sizeof(ticket->flags) /* ticket flags */
+ 1 + alpnSelection.len; /* npn value + length field. */
#ifdef UNSAFE_FUZZER_MODE
padding_length = 0;
#else
padding_length = AES_BLOCK_SIZE -
(ciphertext_length %
AES_BLOCK_SIZE);
#endif
ciphertext_length += padding_length;
if (SECITEM_AllocItem(NULL, &plaintext_item, ciphertext_length) == NULL)
......@@ -1159,6 +1163,10 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
/* Generate encrypted portion of ticket. */
PORT_Assert(aes_key);
#ifdef UNSAFE_FUZZER_MODE
ciphertext.len = plaintext_item.len;
PORT_Memcpy(ciphertext.data, plaintext_item.data, plaintext_item.len);
#else
aes_ctx = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, aes_key, &ivItem);
if (!aes_ctx)
goto loser;
......@@ -1170,10 +1178,10 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
PK11_DestroyContext(aes_ctx, PR_TRUE);
if (rv != SECSuccess)
goto loser;
#endif
/* Convert ciphertext length to network order. */
length_buf[0] = (ciphertext.len >> 8) & 0xff;
length_buf[1] = (ciphertext.len) & 0xff;
(void)ssl_EncodeUintX(ciphertext.len, 2, length_buf);
/* Compute MAC. */
PORT_Assert(mac_key);
......@@ -1337,9 +1345,11 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
*/
if (PORT_Memcmp(enc_session_ticket.key_name, key_name,
SESS_TICKET_KEY_NAME_LEN) != 0) {
#ifndef UNSAFE_FUZZER_MODE
SSL_DBG(("%d: SSL[%d]: Session ticket key_name sent mismatch.",
SSL_GETPID(), ss->fd));
goto no_ticket;
#endif
}
/* Verify the MAC on the ticket. MAC verification may also
......@@ -1376,9 +1386,11 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
if (NSS_SecureMemcmp(computed_mac, enc_session_ticket.mac,
computed_mac_length) !=
0) {
#ifndef UNSAFE_FUZZER_MODE
SSL_DBG(("%d: SSL[%d]: Session ticket MAC mismatch.",
SSL_GETPID(), ss->fd));
goto no_ticket;
#endif
}
/* We ignore key_name for now.
......@@ -1392,6 +1404,12 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
enc_session_ticket.encrypted_state.len);
PORT_Assert(aes_key);
#ifdef UNSAFE_FUZZER_MODE
decrypted_state->len = enc_session_ticket.encrypted_state.len;
PORT_Memcpy(decrypted_state->data,
enc_session_ticket.encrypted_state.data,
enc_session_ticket.encrypted_state.len);
#else
ivItem.data = enc_session_ticket.iv;
ivItem.len = AES_BLOCK_SIZE;
aes_ctx = PK11_CreateContextBySymKey(cipherMech, CKA_DECRYPT,
......@@ -1422,6 +1440,7 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
if (padding_length != (PRUint32)*padding)
goto no_ticket;
}
#endif
/* Deserialize session state. */
buffer = decrypted_state->data;
......@@ -1589,9 +1608,12 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
goto no_ticket;
}
#ifndef UNSAFE_FUZZER_MODE
/* Done parsing. Check that all bytes have been consumed. */
if (buffer_len != padding_length)
if (buffer_len != padding_length) {
goto no_ticket;
}
#endif
/* Use the ticket if it has not expired, otherwise free the allocated
* memory since the ticket is of no use.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment