rust/x509: map decoding errors to decoder events

pull/4721/head
Pierre Chifflier 5 years ago
parent 333fcc43e7
commit 01aef49cbd

@ -18,9 +18,27 @@
// written by Pierre Chifflier <chifflier@wzdftpd.net>
use crate::common::rust_string_to_c;
use nom;
use std;
use std::os::raw::c_char;
use x509_parser::{parse_x509_der, X509Certificate};
use x509_parser::{error::X509Error, parse_x509_der, X509Certificate};
#[repr(u32)]
pub enum X509DecodeError {
Success = 0,
/// Generic decoding error
InvalidCert,
/// Some length does not match, or certificate is incomplete
InvalidLength,
InvalidVersion,
InvalidSerial,
InvalidAlgorithmIdentifier,
InvalidX509Name,
InvalidDate,
InvalidExtensions,
/// DER structure is invalid
InvalidDER,
}
pub struct X509(X509Certificate<'static>);
@ -30,12 +48,20 @@ pub struct X509(X509Certificate<'static>);
///
/// input must be a valid buffer of at least input_len bytes
#[no_mangle]
pub unsafe extern "C" fn rs_x509_decode(input: *const u8, input_len: u32) -> *mut X509 {
pub unsafe extern "C" fn rs_x509_decode(
input: *const u8,
input_len: u32,
err_code: *mut u32,
) -> *mut X509 {
let slice = std::slice::from_raw_parts(input, input_len as usize);
let res = parse_x509_der(slice);
match res {
Ok((_rem, cert)) => Box::into_raw(Box::new(X509(cert))),
Err(_) => std::ptr::null_mut(),
Err(e) => {
let error = x509_parse_error_to_errcode(&e);
*err_code = error as u32;
std::ptr::null_mut()
}
}
}
@ -66,10 +92,7 @@ pub extern "C" fn rs_x509_get_serial(ptr: *const X509) -> *mut c_char {
}
let x509 = cast_pointer! {ptr, X509};
let raw_serial = x509.0.tbs_certificate.raw_serial();
let v : Vec<_> = raw_serial
.iter()
.map(|x| format!("{:02X}", x))
.collect();
let v: Vec<_> = raw_serial.iter().map(|x| format!("{:02X}", x)).collect();
let serial = v.join(":");
rust_string_to_c(serial)
}
@ -108,3 +131,19 @@ pub unsafe extern "C" fn rs_x509_free(ptr: *mut X509) {
}
drop(Box::from_raw(ptr));
}
fn x509_parse_error_to_errcode(e: &nom::Err<X509Error>) -> X509DecodeError {
match e {
nom::Err::Incomplete(_) => X509DecodeError::InvalidLength,
nom::Err::Error(e) | nom::Err::Failure(e) => match e {
X509Error::InvalidVersion => X509DecodeError::InvalidVersion,
X509Error::InvalidSerial => X509DecodeError::InvalidSerial,
X509Error::InvalidAlgorithmIdentifier => X509DecodeError::InvalidAlgorithmIdentifier,
X509Error::InvalidX509Name => X509DecodeError::InvalidX509Name,
X509Error::InvalidDate => X509DecodeError::InvalidDate,
X509Error::InvalidExtensions => X509DecodeError::InvalidExtensions,
X509Error::Der(_) => X509DecodeError::InvalidDER,
_ => X509DecodeError::InvalidCert,
},
}
}

@ -71,16 +71,42 @@ SCEnumCharMap tls_decoder_event_table[ ] = {
{ "TOO_MANY_RECORDS_IN_PACKET", TLS_DECODER_EVENT_TOO_MANY_RECORDS_IN_PACKET },
/* certificate decoding messages */
{ "INVALID_CERTIFICATE", TLS_DECODER_EVENT_INVALID_CERTIFICATE },
{ "CERTIFICATE_MISSING_ELEMENT", TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT },
{ "CERTIFICATE_UNKNOWN_ELEMENT", TLS_DECODER_EVENT_CERTIFICATE_UNKNOWN_ELEMENT },
{ "CERTIFICATE_INVALID_LENGTH", TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH },
{ "CERTIFICATE_INVALID_STRING", TLS_DECODER_EVENT_CERTIFICATE_INVALID_STRING },
{ "CERTIFICATE_INVALID_VERSION", TLS_DECODER_EVENT_CERTIFICATE_INVALID_VERSION },
{ "CERTIFICATE_INVALID_SERIAL", TLS_DECODER_EVENT_CERTIFICATE_INVALID_SERIAL },
{ "CERTIFICATE_INVALID_ALGORITHMIDENTIFIER", TLS_DECODER_EVENT_CERTIFICATE_INVALID_ALGORITHMIDENTIFIER },
{ "CERTIFICATE_INVALID_X509NAME", TLS_DECODER_EVENT_CERTIFICATE_INVALID_X509NAME },
{ "CERTIFICATE_INVALID_DATE", TLS_DECODER_EVENT_CERTIFICATE_INVALID_DATE },
{ "CERTIFICATE_INVALID_EXTENSIONS", TLS_DECODER_EVENT_CERTIFICATE_INVALID_EXTENSIONS },
{ "CERTIFICATE_INVALID_DER", TLS_DECODER_EVENT_CERTIFICATE_INVALID_DER },
{ "CERTIFICATE_INVALID_SUBJECT", TLS_DECODER_EVENT_CERTIFICATE_INVALID_SUBJECT },
{ "CERTIFICATE_INVALID_ISSUER", TLS_DECODER_EVENT_CERTIFICATE_INVALID_ISSUER },
{ "CERTIFICATE_INVALID_VALIDITY", TLS_DECODER_EVENT_CERTIFICATE_INVALID_VALIDITY },
{ "ERROR_MESSAGE_ENCOUNTERED", TLS_DECODER_EVENT_ERROR_MSG_ENCOUNTERED },
/* used as a generic error event */
{ "INVALID_SSL_RECORD", TLS_DECODER_EVENT_INVALID_SSL_RECORD },
{ NULL, -1 },
};
enum {
/* X.509 error codes, returned by decoder
* THESE CONSTANTS MUST MATCH rust/src/x509/mod.rs ! */
ERR_INVALID_CERTIFICATE=1,
ERR_INVALID_LENGTH,
ERR_INVALID_VERSION,
ERR_INVALID_SERIAL,
ERR_INVALID_ALGORITHMIDENTIFIER,
ERR_INVALID_X509NAME,
ERR_INVALID_DATE,
ERR_INVALID_EXTENSIONS,
ERR_INVALID_DER,
/* error getting data */
ERR_EXTRACT_SUBJECT,
ERR_EXTRACT_ISSUER,
ERR_EXTRACT_VALIDITY,
};
/* JA3 fingerprints are disabled by default */
#define SSL_CONFIG_DEFAULT_JA3 0
@ -353,6 +379,49 @@ void SSLVersionToString(uint16_t version, char *buffer)
}
}
static void TlsDecodeHSCertificateErrSetEvent(SSLState *ssl_state, uint32_t err)
{
switch(err) {
case ERR_EXTRACT_VALIDITY:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_VALIDITY);
break;
case ERR_EXTRACT_ISSUER:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_ISSUER);
break;
case ERR_EXTRACT_SUBJECT:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_SUBJECT);
break;
case ERR_INVALID_DER:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_DER);
break;
case ERR_INVALID_EXTENSIONS:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_EXTENSIONS);
break;
case ERR_INVALID_DATE:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_DATE);
break;
case ERR_INVALID_X509NAME:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_X509NAME);
break;
case ERR_INVALID_ALGORITHMIDENTIFIER:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_ALGORITHMIDENTIFIER);
break;
case ERR_INVALID_SERIAL:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_SERIAL);
break;
case ERR_INVALID_VERSION:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_VERSION);
break;
case ERR_INVALID_LENGTH:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH);
break;
case ERR_INVALID_CERTIFICATE:
default:
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_CERTIFICATE);
break;
}
}
static inline int TlsDecodeHSCertificateFingerprint(SSLState *ssl_state,
const uint8_t *input,
uint32_t cert_len)
@ -397,6 +466,7 @@ static int TlsDecodeHSCertificate(SSLState *ssl_state,
const uint32_t input_len)
{
const uint8_t *input = (uint8_t *)initial_input;
uint32_t err_code = 0;
X509 *x509 = NULL;
@ -413,6 +483,8 @@ static int TlsDecodeHSCertificate(SSLState *ssl_state,
/* coverity[tainted_data] */
while (processed_len < cert_chain_len)
{
err_code = 0;
if (!(HAS_SPACE(3)))
goto invalid_cert;
@ -430,30 +502,38 @@ static int TlsDecodeHSCertificate(SSLState *ssl_state,
char * str;
int64_t not_before, not_after;
x509 = rs_x509_decode(input, cert_len);
x509 = rs_x509_decode(input, cert_len, &err_code);
if (x509 == NULL) {
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_CERTIFICATE);
TlsDecodeHSCertificateErrSetEvent(ssl_state, err_code);
goto next;
}
str = rs_x509_get_subject(x509);
if (str == NULL)
if (str == NULL) {
err_code = ERR_EXTRACT_SUBJECT;
goto error;
}
ssl_state->server_connp.cert0_subject = str;
str = rs_x509_get_issuer(x509);
if (str == NULL)
if (str == NULL) {
err_code = ERR_EXTRACT_ISSUER;
goto error;
}
ssl_state->server_connp.cert0_issuerdn = str;
str = rs_x509_get_serial(x509);
if (str == NULL)
if (str == NULL) {
err_code = ERR_INVALID_SERIAL;
goto error;
}
ssl_state->server_connp.cert0_serial = str;
rc = rs_x509_get_validity(x509, &not_before, &not_after);
if (rc != 0)
if (rc != 0) {
err_code = ERR_EXTRACT_VALIDITY;
goto error;
}
ssl_state->server_connp.cert0_not_before = (time_t)not_before;
ssl_state->server_connp.cert0_not_after = (time_t)not_after;
@ -477,6 +557,8 @@ next:
return (input - initial_input);
error:
if (err_code != 0)
TlsDecodeHSCertificateErrSetEvent(ssl_state, err_code);
if (x509 != NULL)
rs_x509_free(x509);
return -1;

@ -50,10 +50,17 @@ enum {
TLS_DECODER_EVENT_TOO_MANY_RECORDS_IN_PACKET,
/* Certificates decoding messages */
TLS_DECODER_EVENT_INVALID_CERTIFICATE,
TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT,
TLS_DECODER_EVENT_CERTIFICATE_UNKNOWN_ELEMENT,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_STRING,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_VERSION,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_SERIAL,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_ALGORITHMIDENTIFIER,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_X509NAME,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_DATE,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_EXTENSIONS,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_DER,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_SUBJECT,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_ISSUER,
TLS_DECODER_EVENT_CERTIFICATE_INVALID_VALIDITY,
TLS_DECODER_EVENT_ERROR_MSG_ENCOUNTERED,
TLS_DECODER_EVENT_INVALID_SSL_RECORD,
};

Loading…
Cancel
Save