// 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>);
///
/// 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()
+ }
}
}
}
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)
}
}
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,
+ },
+ }
+}
{ "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
}
}
+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)
const uint32_t input_len)
{
const uint8_t *input = (uint8_t *)initial_input;
+ uint32_t err_code = 0;
X509 *x509 = NULL;
/* coverity[tainted_data] */
while (processed_len < cert_chain_len)
{
+ err_code = 0;
+
if (!(HAS_SPACE(3)))
goto invalid_cert;
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, ¬_before, ¬_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;
return (input - initial_input);
error:
+ if (err_code != 0)
+ TlsDecodeHSCertificateErrSetEvent(ssl_state, err_code);
if (x509 != NULL)
rs_x509_free(x509);
return -1;
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,
};