tls: store cert data in heap buffer

Cert chain is a list of pointers into this buffer, so can't use a
stream slice approach.
pull/7896/head
Victor Julien 3 years ago
parent 4a283d480d
commit c73d812026

@ -494,28 +494,12 @@ static inline int TlsDecodeHSCertificateAddCertToChain(
return 0;
}
/** \retval consumed bytes consumed or -1 on error */
static int TlsDecodeHSCertificate(SSLState *ssl_state, SSLStateConnp *connp,
const uint8_t *const initial_input, const uint32_t input_len)
const uint8_t *const initial_input, const uint32_t input_len, const int certn)
{
const uint8_t *input = (uint8_t *)initial_input;
uint32_t err_code = 0;
X509 *x509 = NULL;
if (!(HAS_SPACE(3)))
return 0;
uint32_t cert_chain_len = *input << 16 | *(input + 1) << 8 | *(input + 2);
input += 3;
if (!(HAS_SPACE(cert_chain_len)))
return 0;
uint32_t processed_len = 0;
/* coverity[tainted_data] */
while (processed_len < cert_chain_len)
{
err_code = 0;
int rc = 0;
if (!(HAS_SPACE(3)))
@ -528,7 +512,7 @@ static int TlsDecodeHSCertificate(SSLState *ssl_state, SSLStateConnp *connp,
goto invalid_cert;
/* only store fields from the first certificate in the chain */
if (processed_len == 0 && connp->cert0_subject == NULL && connp->cert0_issuerdn == NULL &&
if (certn == 0 && connp->cert0_subject == NULL && connp->cert0_issuerdn == NULL &&
connp->cert0_serial == NULL) {
int64_t not_before, not_after;
@ -585,9 +569,6 @@ static int TlsDecodeHSCertificate(SSLState *ssl_state, SSLStateConnp *connp,
next:
input += cert_len;
processed_len += cert_len + 3;
}
return (input - initial_input);
error:
@ -603,6 +584,57 @@ invalid_cert:
return -1;
}
/** \internal
* \brief parse cert data in a certificate handshake message
* will be called with all data.
* \retval consumed bytes consumed or -1 on error
*/
static int TlsDecodeHSCertificates(SSLState *ssl_state, SSLStateConnp *connp,
const uint8_t *const initial_input, const uint32_t input_len)
{
const uint8_t *input = (uint8_t *)initial_input;
if (!(HAS_SPACE(3)))
return -1;
const uint32_t cert_chain_len = *input << 16 | *(input + 1) << 8 | *(input + 2);
input += 3;
if (!(HAS_SPACE(cert_chain_len)))
return -1;
if (connp->certs_buffer != NULL) {
// TODO should we set an event here?
return -1;
}
connp->certs_buffer = SCCalloc(1, cert_chain_len);
if (connp->certs_buffer == NULL) {
return -1;
}
connp->certs_buffer_size = cert_chain_len;
memcpy(connp->certs_buffer, input, cert_chain_len);
int cert_cnt = 0;
uint32_t processed_len = 0;
/* coverity[tainted_data] */
while (processed_len < cert_chain_len) {
int rc = TlsDecodeHSCertificate(ssl_state, connp, connp->certs_buffer + processed_len,
connp->certs_buffer_size - processed_len, cert_cnt);
if (rc <= 0) { // 0 should be impossible, but lets be defensive
return -1;
}
DEBUG_VALIDATE_BUG_ON(processed_len + (uint32_t)rc > cert_chain_len);
if (processed_len + (uint32_t)rc > cert_chain_len) {
return -1;
}
processed_len += (uint32_t)rc;
}
return processed_len + 3;
}
/**
* \inline
* \brief Check if value is GREASE.
@ -1399,7 +1431,7 @@ RecordAlreadyProcessed(const SSLStateConnp *curr_connp)
static inline int SSLv3ParseHandshakeTypeCertificate(SSLState *ssl_state, SSLStateConnp *connp,
const uint8_t *const initial_input, const uint32_t input_len)
{
int rc = TlsDecodeHSCertificate(ssl_state, connp, initial_input, input_len);
int rc = TlsDecodeHSCertificates(ssl_state, connp, initial_input, input_len);
SCLogDebug("rc %d", rc);
if (rc > 0) {
DEBUG_VALIDATE_BUG_ON(rc > (int)input_len);
@ -2603,12 +2635,16 @@ static void SSLStateFree(void *p)
}
/* Free certificate chain */
if (ssl_state->server_connp.certs_buffer)
SCFree(ssl_state->server_connp.certs_buffer);
while ((item = TAILQ_FIRST(&ssl_state->server_connp.certs))) {
TAILQ_REMOVE(&ssl_state->server_connp.certs, item, next);
SCFree(item);
}
TAILQ_INIT(&ssl_state->server_connp.certs);
/* Free certificate chain */
if (ssl_state->client_connp.certs_buffer)
SCFree(ssl_state->client_connp.certs_buffer);
while ((item = TAILQ_FIRST(&ssl_state->client_connp.certs))) {
TAILQ_REMOVE(&ssl_state->client_connp.certs, item, next);
SCFree(item);

@ -230,6 +230,9 @@ typedef struct SSLStateConnp_ {
TAILQ_HEAD(, SSLCertsChain_) certs;
uint8_t *certs_buffer;
uint32_t certs_buffer_size;
uint32_t cert_log_flag;
JA3Buffer *ja3_str;

Loading…
Cancel
Save