From: Mats Klepsland Date: Tue, 17 Jan 2017 08:20:25 +0000 (+0100) Subject: app-layer-tls: decode certificate serial number X-Git-Tag: suricata-4.0.0-beta1~283 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2c1a36dd6e56a84bc2894a7e544b1e83651b85bf;p=thirdparty%2Fsuricata.git app-layer-tls: decode certificate serial number --- diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index 58f54feea6..f6839adc5f 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -1540,6 +1540,8 @@ void SSLStateFree(void *p) SCFree(ssl_state->client_connp.cert0_subject); if (ssl_state->client_connp.cert0_issuerdn) SCFree(ssl_state->client_connp.cert0_issuerdn); + if (ssl_state->server_connp.cert0_serial) + SCFree(ssl_state->server_connp.cert0_serial); if (ssl_state->client_connp.cert0_fingerprint) SCFree(ssl_state->client_connp.cert0_fingerprint); if (ssl_state->client_connp.sni) diff --git a/src/app-layer-ssl.h b/src/app-layer-ssl.h index d2279e2f2b..f237578366 100644 --- a/src/app-layer-ssl.h +++ b/src/app-layer-ssl.h @@ -149,6 +149,7 @@ typedef struct SSLStateConnp_ { char *cert0_subject; char *cert0_issuerdn; + char *cert0_serial; time_t cert0_not_before; time_t cert0_not_after; char *cert0_fingerprint; diff --git a/src/app-layer-tls-handshake.c b/src/app-layer-tls-handshake.c index 9ae3a10801..6c3226f2d5 100644 --- a/src/app-layer-tls-handshake.c +++ b/src/app-layer-tls-handshake.c @@ -177,6 +177,21 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input, } } + rc = Asn1DerGetSerial(cert, buffer, sizeof(buffer), &errcode); + if (rc != 0) { + TLSCertificateErrCodeToWarning(ssl_state, errcode); + } else { + if (i == 0) { + if (ssl_state->server_connp.cert0_serial == NULL) { + ssl_state->server_connp.cert0_serial = SCStrdup(buffer); + } + if (ssl_state->server_connp.cert0_serial == NULL) { + DerFree(cert); + return -1; + } + } + } + rc = Asn1DerGetValidity(cert, ¬_before, ¬_after, &errcode); if (rc != 0) { TLSCertificateErrCodeToWarning(ssl_state, errcode); diff --git a/src/util-decode-der-get.c b/src/util-decode-der-get.c index fc132cf45e..3e90788f74 100644 --- a/src/util-decode-der-get.c +++ b/src/util-decode-der-get.c @@ -37,6 +37,7 @@ #include "util-decode-der.h" #include "util-decode-der-get.h" +static const uint8_t SEQ_IDX_SERIAL[] = { 0, 0 }; static const uint8_t SEQ_IDX_ISSUER[] = { 0, 2 }; static const uint8_t SEQ_IDX_VALIDITY[] = { 0, 3 }; static const uint8_t SEQ_IDX_SUBJECT[] = { 0, 4 }; @@ -241,6 +242,50 @@ validity_error: return rc; } +int Asn1DerGetSerial(const Asn1Generic *cert, char *buffer, uint32_t length, + uint32_t *errcode) +{ + const Asn1Generic *node; + uint32_t node_len, i; + int rc = -1; + + if (errcode) + *errcode = ERR_DER_MISSING_ELEMENT; + + buffer[0] = '\0'; + + node = Asn1DerGet(cert, SEQ_IDX_SERIAL, sizeof(SEQ_IDX_SERIAL), errcode); + if ((node == NULL) || node->type != ASN1_INTEGER || node->str == NULL) + goto serial_error; + + node_len = strlen(node->str); + + /* make sure the buffer is big enough */ + if (node_len + (node_len / 2) > length) + goto serial_error; + + /* format serial number (e.g. XX:XX:XX:XX:XX) */ + for (i = 0; i < node_len; i++) { + char c[3]; + /* insert separator before each even number */ + if (((i % 2) == 0) && (i != 0)) { + snprintf(c, sizeof(c), ":%c", node->str[i]); + } else { + snprintf(c, sizeof(c), "%c", node->str[i]); + } + + strlcat(buffer, c, length); + } + + if (errcode) + *errcode = 0; + + rc = 0; + +serial_error: + return rc; +} + int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode) { diff --git a/src/util-decode-der-get.h b/src/util-decode-der-get.h index 2d2168aeb3..bed1cfebed 100644 --- a/src/util-decode-der-get.h +++ b/src/util-decode-der-get.h @@ -38,6 +38,7 @@ const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index, const uint32_t seqsz, uint32_t *errcode); int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode); +int Asn1DerGetSerial(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode); int Asn1DerGetValidity(const Asn1Generic *cert, time_t *not_before, time_t *not_after, uint32_t *errcode); int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode);