Tighten up SCT list checking

This commit is contained in:
Joseph Birr-Pixton 2017-07-16 16:38:27 +01:00
parent b25072598e
commit 8890d193e3
4 changed files with 30 additions and 3 deletions

View File

@ -237,6 +237,10 @@
"SendUnknownExtensionOnCertificate-TLS13": ":PEER_MISBEHAVIOUR:",
"LargePlaintext": ":PEER_MISBEHAVIOUR:",
"SendDuplicateExtensionsOnCerts-TLS13": ":PEER_MISBEHAVIOUR:",
"SignedCertificateTimestampListEmpty-Client-TLS12": ":PEER_MISBEHAVIOUR:",
"SignedCertificateTimestampListEmpty-Client-TLS13": ":PEER_MISBEHAVIOUR:",
"SignedCertificateTimestampListEmptySCT-Client-TLS12": ":PEER_MISBEHAVIOUR:",
"SignedCertificateTimestampListEmptySCT-Client-TLS13": ":PEER_MISBEHAVIOUR:",
"EMS-Forbidden-TLS13": ":PEER_MISBEHAVIOUR:",
"SendExtensionOnClientCertificate-TLS13": ":PEER_MISBEHAVIOUR:",
"ExtendedMasterSecret-NoToYes-Client": ":PEER_MISBEHAVIOUR:",

View File

@ -376,6 +376,12 @@ fn main() {
"-signed-cert-timestamps" => {
opts.server_sct_list = base64::decode(args.remove(0).as_bytes())
.expect("invalid base64");
if opts.server_sct_list.len() == 2 &&
opts.server_sct_list[0] == 0x00 &&
opts.server_sct_list[1] == 0x00 {
quit(":INVALID_SCT_LIST:");
}
}
"-select-alpn" => {
opts.protocols.push(args.remove(0));

View File

@ -14,7 +14,7 @@ use msgs::handshake::{CertificatePayloadTLS13, CertificateEntry};
use msgs::handshake::ServerKeyExchangePayload;
use msgs::handshake::DigitallySignedStruct;
use msgs::handshake::{PresharedKeyIdentity, PresharedKeyOffer, HelloRetryRequest};
use msgs::handshake::CertificateStatusRequest;
use msgs::handshake::{CertificateStatusRequest, SCTList};
use msgs::enums::{ClientCertificateType, PSKKeyExchangeMode, ECPointFormat};
use msgs::codec::Codec;
use msgs::persist;
@ -585,6 +585,11 @@ fn handle_server_hello(sess: &mut ClientSessionImpl, m: Message) -> StateResult
// Save any sent SCTs for verification against the certificate.
if let Some(sct_list) = server_hello.get_sct_list() {
info!("Server sent {:?} SCTs", sct_list.len());
if sct_list_is_invalid(&sct_list) {
let error_msg = "server sent invalid SCT list".to_string();
return Err(TLSError::PeerMisbehavedError(error_msg));
}
sess.handshake_data.server_cert_scts = Some(sct_list.clone());
}
@ -759,6 +764,11 @@ static EXPECT_TLS13_ENCRYPTED_EXTENSIONS: State = State {
handle: handle_encrypted_extensions,
};
fn sct_list_is_invalid(scts: &SCTList) -> bool {
scts.is_empty() ||
scts.iter().any(|sct| sct.0.is_empty())
}
fn handle_certificate_tls13(sess: &mut ClientSessionImpl, m: Message) -> StateResult {
let cert_chain = extract_handshake!(m, HandshakePayload::CertificateTLS13).unwrap();
sess.handshake_data.transcript.add_message(&m);
@ -780,6 +790,14 @@ fn handle_certificate_tls13(sess: &mut ClientSessionImpl, m: Message) -> StateRe
sess.handshake_data.server_cert_ocsp_response = cert_chain.get_end_entity_ocsp();
sess.handshake_data.server_cert_scts = cert_chain.get_end_entity_scts();
sess.handshake_data.server_cert_chain = cert_chain.convert();
if let Some(sct_list) = sess.handshake_data.server_cert_scts.as_ref() {
if sct_list_is_invalid(&sct_list) {
let error_msg = "server sent invalid SCT list".to_string();
return Err(TLSError::PeerMisbehavedError(error_msg));
}
}
Ok(&EXPECT_TLS13_CERTIFICATE_VERIFY)
}

View File

@ -224,7 +224,6 @@ pub fn verify_scts(cert: &Certificate,
scts: &SCTList,
logs: &[&sct::Log]) -> Result<(), TLSError> {
let mut valid_scts = 0;
let total_scts = scts.len();
let now = (time::get_time().sec * 1000) as u64;
let mut last_sct_error = None;
@ -247,7 +246,7 @@ pub fn verify_scts(cert: &Certificate,
/* If we were supplied with some logs, and some SCTs,
* but couldn't verify any of them, fail the handshake. */
if !logs.is_empty() && total_scts != 0 && valid_scts == 0 {
if !logs.is_empty() && !scts.is_empty() && valid_scts == 0 {
warn!("No valid SCTs provided");
return Err(TLSError::InvalidSCT(last_sct_error.unwrap()));
}