Test detection of truncated handshake messages

This commit is contained in:
Joseph Birr-Pixton 2020-05-08 12:49:39 +01:00
parent 59ee30545e
commit cb397f0e15
2 changed files with 98 additions and 2 deletions

View File

@ -4,7 +4,7 @@ import os
import glob
import subprocess
LLVM_PATH = glob.glob('/usr/lib/llvm-3.8/lib/clang/3.8.[0-9]/lib/linux/')[0]
LLVM_PATH = glob.glob('/usr/lib/llvm-3.*/lib/clang/3.*.[0-9]/lib/linux/')[0]
COVERAGE_OPTIONS = '-Ccodegen-units=1 -Clink-dead-code -Cpasses=insert-gcov-profiling -Cpanic=abort -Zpanic-abort-tests -L%s -lclang_rt.profile-x86_64' % LLVM_PATH
LCOVOPTS = '--gcov-tool ./admin/llvm-gcov --rc lcov_excl_line=assert'.split()

View File

@ -1,7 +1,7 @@
use super::handshake::*;
use super::enums::*;
use super::base::{Payload, PayloadU8, PayloadU16, PayloadU24};
use super::codec::{Reader, Codec};
use super::codec::{Reader, Codec, put_u16};
use webpki::DNSNameRef;
use crate::key::Certificate;
@ -409,6 +409,38 @@ fn client_has_duplicate_extensions_works() {
assert!(!chp.has_duplicate_extension());
}
#[test]
fn test_truncated_client_extension_is_detected() {
let chp = get_sample_clienthellopayload();
for ext in &chp.extensions {
let mut enc = ext.get_encoding();
println!("testing {:?} enc {:?}", ext, enc);
// "outer" truncation, ie, where the extension-level length is longer than
// the input
for l in 0..enc.len() {
assert!(ClientExtension::read_bytes(&enc[..l]).is_none());
}
// these extension types don't have any internal encoding that rustls validates:
match ext.get_type() {
ExtensionType::TransportParameters | ExtensionType::Unknown(_) => {
continue;
}
_ => {}
};
// "inner" truncation, where the extension-level length agrees with the input
// length, but isn't long enough for the type of extension
for l in 0..(enc.len()-4) {
put_u16(l as u16, &mut enc[2..]);
println!(" encoding {:?} len {:?}", enc, l);
assert!(ClientExtension::read_bytes(&enc).is_none());
}
}
}
fn test_client_extension_getter(typ: ExtensionType, getter: fn(&ClientHelloPayload) -> bool) {
let mut chp = get_sample_clienthellopayload();
let ext = chp.find_extension(typ).unwrap().clone();
@ -488,6 +520,38 @@ fn client_get_psk_modes() {
|chp| chp.get_psk_modes().is_some());
}
#[test]
fn test_truncated_helloretry_extension_is_detected() {
let hrr = get_sample_helloretryrequest();
for ext in &hrr.extensions {
let mut enc = ext.get_encoding();
println!("testing {:?} enc {:?}", ext, enc);
// "outer" truncation, ie, where the extension-level length is longer than
// the input
for l in 0..enc.len() {
assert!(HelloRetryExtension::read_bytes(&enc[..l]).is_none());
}
// these extension types don't have any internal encoding that rustls validates:
match ext.get_type() {
ExtensionType::Unknown(_) => {
continue;
}
_ => {}
};
// "inner" truncation, where the extension-level length agrees with the input
// length, but isn't long enough for the type of extension
for l in 0..(enc.len()-4) {
put_u16(l as u16, &mut enc[2..]);
println!(" encoding {:?} len {:?}", enc, l);
assert!(HelloRetryExtension::read_bytes(&enc).is_none());
}
}
}
fn test_helloretry_extension_getter(typ: ExtensionType, getter: fn(&HelloRetryRequest) -> bool) {
let mut hrr = get_sample_helloretryrequest();
let mut exts = mem::replace(&mut hrr.extensions, vec![]);
@ -525,6 +589,38 @@ fn helloretry_get_supported_versions() {
|hrr| hrr.get_supported_versions().is_some());
}
#[test]
fn test_truncated_server_extension_is_detected() {
let shp = get_sample_serverhellopayload();
for ext in &shp.extensions {
let mut enc = ext.get_encoding();
println!("testing {:?} enc {:?}", ext, enc);
// "outer" truncation, ie, where the extension-level length is longer than
// the input
for l in 0..enc.len() {
assert!(ServerExtension::read_bytes(&enc[..l]).is_none());
}
// these extension types don't have any internal encoding that rustls validates:
match ext.get_type() {
ExtensionType::TransportParameters | ExtensionType::Unknown(_) => {
continue;
}
_ => {}
};
// "inner" truncation, where the extension-level length agrees with the input
// length, but isn't long enough for the type of extension
for l in 0..(enc.len()-4) {
put_u16(l as u16, &mut enc[2..]);
println!(" encoding {:?} len {:?}", enc, l);
assert!(ServerExtension::read_bytes(&enc).is_none());
}
}
}
fn test_server_extension_getter(typ: ExtensionType, getter: fn(&ServerHelloPayload) -> bool) {
let mut shp = get_sample_serverhellopayload();
let ext = shp.find_extension(typ).unwrap().clone();