tls: support handshake fragmentation

Implement TLS record defrag for handshake messages.

Ticket: #5183.
pull/7896/head
Victor Julien 3 years ago
parent bcaf0f6f7d
commit 4bab6e24e5

@ -262,9 +262,7 @@ static inline int SafeMemcpy(void *dst, size_t dst_offset, size_t dst_size,
#define SSLParserHSReset(connp) \
do { \
(connp)->handshake_type = 0; \
(connp)->hs_bytes_processed = 0; \
(connp)->message_length = 0; \
(connp)->message_start = 0; \
} while (0)
#define SSLParserReset(state) \
@ -1390,17 +1388,9 @@ static int TLSDecodeHandshakeHello(SSLState *ssl_state,
}
end:
ssl_state->curr_connp->hs_bytes_processed = 0;
return 0;
}
static inline bool
HaveEntireRecord(const SSLStateConnp *curr_connp, const uint32_t input_len)
{
return (curr_connp->bytes_processed + input_len) >=
(curr_connp->record_length + SSLV3_RECORD_HDR_LEN);
}
#ifdef DEBUG_VALIDATION
static inline bool
RecordAlreadyProcessed(const SSLStateConnp *curr_connp)
@ -1424,10 +1414,33 @@ static inline int SSLv3ParseHandshakeTypeCertificate(SSLState *ssl_state,
SSLParserHSReset(ssl_state->curr_connp);
/* fall through to still consume the cert bytes */
}
ssl_state->curr_connp->bytes_processed += input_len;
return input_len;
}
static int SupportedHandshakeType(const uint8_t type)
{
switch (type) {
case SSLV3_HS_CLIENT_HELLO:
case SSLV3_HS_SERVER_HELLO:
case SSLV3_HS_SERVER_KEY_EXCHANGE:
case SSLV3_HS_CLIENT_KEY_EXCHANGE:
case SSLV3_HS_CERTIFICATE:
case SSLV3_HS_HELLO_REQUEST:
case SSLV3_HS_CERTIFICATE_REQUEST:
case SSLV3_HS_CERTIFICATE_VERIFY:
case SSLV3_HS_FINISHED:
case SSLV3_HS_CERTIFICATE_URL:
case SSLV3_HS_CERTIFICATE_STATUS:
case SSLV3_HS_NEW_SESSION_TICKET:
return true;
break;
default:
return false;
break;
}
}
/**
* \retval parsed number of consumed bytes
* \retval < 0 error
@ -1447,28 +1460,17 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, const uint8_t *input,
case SSLV3_HS_CLIENT_HELLO:
ssl_state->current_flags = SSL_AL_FLAG_STATE_CLIENT_HELLO;
/* Only parse the message if it is complete */
if (input_len >= ssl_state->curr_connp->message_length &&
input_len >= 40) {
rc = TLSDecodeHandshakeHello(ssl_state, input, input_len);
if (rc < 0)
return rc;
}
rc = TLSDecodeHandshakeHello(ssl_state, input, input_len);
if (rc < 0)
return rc;
break;
case SSLV3_HS_SERVER_HELLO:
ssl_state->current_flags = SSL_AL_FLAG_STATE_SERVER_HELLO;
/* Only parse the message if it is complete */
if (input_len >= ssl_state->curr_connp->message_length &&
input_len >= 40) {
rc = TLSDecodeHandshakeHello(ssl_state, input,
ssl_state->curr_connp->message_length);
if (rc < 0)
return rc;
}
rc = TLSDecodeHandshakeHello(ssl_state, input, ssl_state->curr_connp->message_length);
if (rc < 0)
return rc;
break;
case SSLV3_HS_SERVER_KEY_EXCHANGE:
@ -1486,9 +1488,11 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, const uint8_t *input,
"direction!");
break;
}
rc = SSLv3ParseHandshakeTypeCertificate(ssl_state,
initial_input, input_len);
return rc;
if (rc < 0)
return rc;
break;
case SSLV3_HS_HELLO_REQUEST:
@ -1508,29 +1512,10 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, const uint8_t *input,
ssl_state->flags |= ssl_state->current_flags;
SCLogDebug("message: start %u length %u", ssl_state->curr_connp->message_start, ssl_state->curr_connp->message_length);
SCLogDebug("message: length %u", ssl_state->curr_connp->message_length);
SCLogDebug("input_len %u ssl_state->curr_connp->bytes_processed %u", input_len, ssl_state->curr_connp->bytes_processed);
uint32_t write_len = 0;
if (ssl_state->curr_connp->message_start + ssl_state->curr_connp->message_length <
ssl_state->curr_connp->bytes_processed + input_len) {
SCLogDebug("msg done");
// Safety check against integer underflow
DEBUG_VALIDATE_BUG_ON(
ssl_state->curr_connp->message_start + ssl_state->curr_connp->message_length <
ssl_state->curr_connp->bytes_processed);
write_len = (ssl_state->curr_connp->message_start + ssl_state->curr_connp->message_length) -
ssl_state->curr_connp->bytes_processed;
DEBUG_VALIDATE_BUG_ON(write_len > input_len);
ssl_state->curr_connp->bytes_processed += write_len;
SSLParserHSReset(ssl_state->curr_connp);
SCLogDebug("write_len %u", write_len);
return write_len;
} else {
ssl_state->curr_connp->bytes_processed += input_len;
return input_len;
}
return input_len;
}
static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, const uint8_t *input,
@ -1540,74 +1525,161 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, const uint8_t *input
if (input_len == 0 || ssl_state->curr_connp->bytes_processed ==
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN)) {
return 0;
SCReturnInt(0);
}
while (input_len) {
SCLogDebug("bytes_processed %u", ssl_state->curr_connp->bytes_processed);
SCLogDebug("ssl_state->curr_connp->hs_bytes_processed %u input %p input_len %u",
ssl_state->curr_connp->hs_bytes_processed, input, input_len);
SCLogDebug("input_len %u", input_len);
if (ssl_state->curr_connp->hs_buffer != NULL) {
SCLogDebug("partial handshake record in place");
const uint32_t need = ssl_state->curr_connp->hs_buffer_message_size -
ssl_state->curr_connp->hs_buffer_offset;
const uint32_t add = MIN(need, input_len);
/* grow buffer to next multiple of 4k that fits all data we have */
if (ssl_state->curr_connp->hs_buffer_offset + add >
ssl_state->curr_connp->hs_buffer_size) {
const uint32_t avail = ssl_state->curr_connp->hs_buffer_offset + add;
const uint32_t new_size = avail + (4096 - (avail % 4096));
SCLogDebug("new_size %u, avail %u", new_size, avail);
void *ptr = SCRealloc(ssl_state->curr_connp->hs_buffer, new_size);
if (ptr == NULL)
return -1;
ssl_state->curr_connp->hs_buffer = ptr;
ssl_state->curr_connp->hs_buffer_size = new_size;
}
switch (ssl_state->curr_connp->hs_bytes_processed) {
case 0:
ssl_state->curr_connp->handshake_type = *(input++);
SCLogDebug("handshake_type %u", ssl_state->curr_connp->handshake_type);
ssl_state->curr_connp->bytes_processed++;
ssl_state->curr_connp->hs_bytes_processed++;
if (--input_len == 0 ||
ssl_state->curr_connp->bytes_processed ==
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN)) {
return (input - initial_input);
}
SCLogDebug("ssl_state->curr_connp->hs_buffer_offset %u "
"ssl_state->curr_connp->hs_buffer_size %u",
ssl_state->curr_connp->hs_buffer_offset, ssl_state->curr_connp->hs_buffer_size);
SCLogDebug("to add %u total %u", add, ssl_state->curr_connp->hs_buffer_offset + add);
/* fall through */
case 1:
ssl_state->curr_connp->message_length = *(input++) << 16;
ssl_state->curr_connp->bytes_processed++;
ssl_state->curr_connp->hs_bytes_processed++;
if (--input_len == 0 ||
ssl_state->curr_connp->bytes_processed ==
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN)) {
return (input - initial_input);
}
if (SafeMemcpy(ssl_state->curr_connp->hs_buffer,
ssl_state->curr_connp->hs_buffer_offset,
ssl_state->curr_connp->hs_buffer_size, input, 0, add, add) != 0) {
SCLogDebug("copy failed");
return -1;
}
ssl_state->curr_connp->hs_buffer_offset += add;
/* fall through */
case 2:
ssl_state->curr_connp->message_length |= *(input++) << 8;
ssl_state->curr_connp->bytes_processed++;
ssl_state->curr_connp->hs_bytes_processed++;
if (--input_len == 0 ||
ssl_state->curr_connp->bytes_processed ==
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN)) {
return (input - initial_input);
if (ssl_state->curr_connp->hs_buffer_message_size <=
ssl_state->curr_connp->hs_buffer_offset + input_len) {
ssl_state->curr_connp->handshake_type =
ssl_state->curr_connp->hs_buffer_message_type;
ssl_state->curr_connp->message_length =
ssl_state->curr_connp->hs_buffer_message_size;
SCLogDebug("got all data now: handshake_type %u message_length %u",
ssl_state->curr_connp->handshake_type,
ssl_state->curr_connp->message_length);
int retval = SSLv3ParseHandshakeType(ssl_state, ssl_state->curr_connp->hs_buffer,
ssl_state->curr_connp->hs_buffer_offset, direction);
if (retval < 0) {
SSLParserHSReset(ssl_state->curr_connp);
return (retval);
}
SCLogDebug("retval %d", retval);
/* data processed, reset buffer */
SCFree(ssl_state->curr_connp->hs_buffer);
ssl_state->curr_connp->hs_buffer = NULL;
ssl_state->curr_connp->hs_buffer_size = 0;
ssl_state->curr_connp->hs_buffer_message_size = 0;
ssl_state->curr_connp->hs_buffer_message_type = 0;
ssl_state->curr_connp->hs_buffer_offset = 0;
} else {
SCLogDebug("partial data");
}
/* fall through */
case 3:
ssl_state->curr_connp->message_length |= *(input++);
SCLogDebug("message len %u", ssl_state->curr_connp->message_length);
ssl_state->curr_connp->bytes_processed++;
ssl_state->curr_connp->hs_bytes_processed++;
--input_len;
ssl_state->curr_connp->message_start = ssl_state->curr_connp->bytes_processed;
input += add;
input_len -= add;
SCLogDebug("input_len %u", input_len);
SSLParserHSReset(ssl_state->curr_connp);
continue;
}
/* fall through */
SCLogDebug("bytes_processed %u", ssl_state->curr_connp->bytes_processed);
SCLogDebug("input %p input_len %u", input, input_len);
if (input_len < 4) {
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
SCReturnInt(-1);
}
SCLogDebug("message len %u input %p input_len %u", ssl_state->curr_connp->message_length,
input, input_len);
int retval = SSLv3ParseHandshakeType(ssl_state, input, input_len, direction);
if (retval < 0 || retval > (int)input_len) {
DEBUG_VALIDATE_BUG_ON(retval > (int)input_len);
return (retval);
ssl_state->curr_connp->handshake_type = input[0];
ssl_state->curr_connp->message_length = input[1] << 16 | input[2] << 8 | input[3];
SCLogDebug("handshake_type %u message len %u input %p input_len %u",
ssl_state->curr_connp->handshake_type, ssl_state->curr_connp->message_length, input,
input_len);
input += 4;
input_len -= 4;
const uint32_t record_len = ssl_state->curr_connp->message_length;
/* see if we support this type. We check here to not use the fragment
* handling on things we don't support. */
const bool supported_type = SupportedHandshakeType(ssl_state->curr_connp->handshake_type);
SCLogDebug("supported_type %s handshake_type %u/%02x", supported_type ? "true" : "false",
ssl_state->curr_connp->handshake_type, ssl_state->curr_connp->handshake_type);
if (!supported_type) {
uint32_t avail_record_len = MIN(input_len, record_len);
input += avail_record_len;
input_len -= avail_record_len;
SSLParserHSReset(ssl_state->curr_connp);
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_HANDSHAKE_MESSAGE);
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
continue;
}
SCLogDebug("retval %d input_len %u", retval, input_len);
input += retval;
input_len -= retval;
SSLParserHSReset(ssl_state->curr_connp);
}
/* if the message lenght exceeds our input_len, we have a tls fragment. */
if (record_len > input_len) {
const uint32_t avail = input_len;
const uint32_t size = avail + (4096 - (avail % 4096));
SCLogDebug("initial buffer size %u, based on input %u", size, avail);
ssl_state->curr_connp->hs_buffer = SCCalloc(1, size);
if (ssl_state->curr_connp->hs_buffer == NULL) {
return -1;
}
ssl_state->curr_connp->hs_buffer_size = size;
ssl_state->curr_connp->hs_buffer_message_size = record_len;
ssl_state->curr_connp->hs_buffer_message_type = ssl_state->curr_connp->handshake_type;
if (input_len > 0) {
if (SafeMemcpy(ssl_state->curr_connp->hs_buffer, 0,
ssl_state->curr_connp->hs_buffer_size, input, 0, input_len,
input_len) != 0) {
return -1;
}
ssl_state->curr_connp->hs_buffer_offset = input_len;
}
SCLogDebug("opened record buffer %p size %u offset %u type %u msg_size %u",
ssl_state->curr_connp->hs_buffer, ssl_state->curr_connp->hs_buffer_size,
ssl_state->curr_connp->hs_buffer_offset,
ssl_state->curr_connp->hs_buffer_message_type,
ssl_state->curr_connp->hs_buffer_message_size);
input += input_len;
SSLParserHSReset(ssl_state->curr_connp);
return (input - initial_input);
} else {
/* full record, parse it now */
int retval = SSLv3ParseHandshakeType(
ssl_state, input, ssl_state->curr_connp->message_length, direction);
if (retval < 0 || retval > (int)input_len) {
DEBUG_VALIDATE_BUG_ON(retval > (int)input_len);
return (retval);
}
SCLogDebug("retval %d input_len %u", retval, input_len);
input += retval;
input_len -= retval;
SSLParserHSReset(ssl_state->curr_connp);
}
SCLogDebug("input_len left %u", input_len);
}
return (input - initial_input);
}
@ -1934,9 +2006,6 @@ static struct SSLDecoderResult SSLv2Decode(uint8_t direction, SSLState *ssl_stat
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
return SSL_DECODER_ERROR(-1);
}
// TODO review
// BUG_ON(ssl_state->curr_connp->record_lengths_length + 1 !=
// ssl_state->curr_connp->bytes_processed);
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input,
ssl_state->curr_connp->record_lengths_length + ssl_state->curr_connp->record_length,
@ -2119,7 +2188,7 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
ssl_state->curr_connp->record_length + retval, direction, TLS_FRAME_PDU);
AppLayerFrameNewByPointer(
ssl_state->f, &stream_slice, input, SSLV3_RECORD_HDR_LEN, direction, TLS_FRAME_HDR);
parsed += retval;
parsed = retval;
record_len = MIN(input_len - parsed, ssl_state->curr_connp->record_length);
SCLogDebug("record_len %u (input_len %u, parsed %u, ssl_state->curr_connp->record_length %u)",
record_len, input_len, parsed, ssl_state->curr_connp->record_length);
@ -2132,6 +2201,7 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
SCLogDebug("record length %u processed %u got %u",
ssl_state->curr_connp->record_length, ssl_state->curr_connp->bytes_processed, record_len);
/* if we don't have the full record, we return incomplete */
if (ssl_state->curr_connp->record_length > input_len - parsed) {
/* no need to use incomplete api buffering for application
* records that we'll not use anyway. */
@ -2159,7 +2229,6 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
ssl_state->curr_connp->record_length, direction, TLS_FRAME_DATA);
switch (ssl_state->curr_connp->content_type) {
/* we don't need any data from these types */
case SSLV3_CHANGE_CIPHER_SPEC:
ssl_state->flags |= SSL_AL_FLAG_CHANGE_CIPHER_SPEC;
@ -2169,7 +2238,6 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
} else {
ssl_state->flags |= SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC;
}
break;
case SSLV3_ALERT_PROTOCOL:
@ -2207,7 +2275,6 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
AppLayerParserStateSetFlag(pstate,
APP_LAYER_PARSER_BYPASS_READY);
}
break;
case SSLV3_HANDSHAKE_PROTOCOL: {
@ -2221,7 +2288,6 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
/* do nothing */
} else {
// if we started parsing this, we must stop
ssl_state->curr_connp->hs_bytes_processed = 0;
break;
}
}
@ -2235,6 +2301,7 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
int retval = SSLv3ParseHandshakeProtocol(ssl_state, input + parsed,
record_len, direction);
SCLogDebug("retval %d", retval);
if (retval < 0 || retval > (int)record_len) {
DEBUG_VALIDATE_BUG_ON(retval > (int)record_len);
SSLSetEvent(ssl_state,
@ -2244,27 +2311,8 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
SCLogDebug("SSLv3ParseHandshakeProtocol returned %d", retval);
return SSL_DECODER_ERROR(-1);
}
SCLogDebug("retval %d", retval);
parsed += retval;
record_len -= retval;
(void)record_len; /* for scan-build */
SCLogDebug("bytes_processed %u (record+hdr %u)", ssl_state->curr_connp->bytes_processed,
(ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN));
ValidateRecordState(ssl_state->curr_connp);
if (ssl_state->curr_connp->bytes_processed >=
ssl_state->curr_connp->record_length +
SSLV3_RECORD_HDR_LEN) {
SCLogDebug("record ready");
SSLParserReset(ssl_state);
}
SCLogDebug("trigger RAW! (post HS)");
AppLayerParserTriggerRawStreamReassembly(ssl_state->f,
direction == 0 ? STREAM_TOSERVER : STREAM_TOCLIENT);
return SSL_DECODER_OK(parsed);
break;
}
case SSLV3_HEARTBEAT_PROTOCOL: {
AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed,
@ -2285,35 +2333,21 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
return SSL_DECODER_ERROR(-1);
}
if (HaveEntireRecord(ssl_state->curr_connp, record_len)) {
DEBUG_VALIDATE_BUG_ON(((ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) <
ssl_state->curr_connp->bytes_processed));
if ((ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) <
ssl_state->curr_connp->bytes_processed) {
/* defensive checks. Something is wrong. */
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
SCLogDebug("defensive checks. Something is wrong.");
return SSL_DECODER_ERROR(-1);
}
parsed += record_len;
ssl_state->curr_connp->bytes_processed += record_len;
if (ssl_state->curr_connp->bytes_processed >=
ssl_state->curr_connp->record_length + SSLV3_RECORD_HDR_LEN) {
SCLogDebug("record complete, trigger RAW");
AppLayerParserTriggerRawStreamReassembly(ssl_state->f,
direction == 0 ? STREAM_TOSERVER : STREAM_TOCLIENT);
/* looks like we have another record */
uint32_t diff = ssl_state->curr_connp->record_length +
SSLV3_RECORD_HDR_LEN - ssl_state->curr_connp->bytes_processed;
parsed += diff;
AppLayerParserTriggerRawStreamReassembly(
ssl_state->f, direction == 0 ? STREAM_TOSERVER : STREAM_TOCLIENT);
SSLParserReset(ssl_state);
ValidateRecordState(ssl_state->curr_connp);
return SSL_DECODER_OK(parsed);
} else {
/* we still don't have the entire record for the one we are
currently parsing */
} else {
parsed += record_len;
ssl_state->curr_connp->bytes_processed += record_len;
ValidateRecordState(ssl_state->curr_connp);
return SSL_DECODER_OK(parsed);
}
@ -2393,8 +2427,8 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
SCLogDebug("SSL/TLS version reset");
}
}
SCLogDebug("record %u: bytes_processed %u, version %02X", counter,
ssl_state->curr_connp->bytes_processed, ssl_state->curr_connp->version);
SCLogDebug("record %u: bytes_processed %u, version %02X, input_len %u", counter,
ssl_state->curr_connp->bytes_processed, ssl_state->curr_connp->version, input_len);
if (ssl_state->curr_connp->version == SSL_VERSION_2) {
if (ssl_state->curr_connp->bytes_processed == 0) {
@ -2526,6 +2560,8 @@ static void SSLStateFree(void *p)
SCFree(ssl_state->client_connp.sni);
if (ssl_state->client_connp.session_id)
SCFree(ssl_state->client_connp.session_id);
if (ssl_state->client_connp.hs_buffer)
SCFree(ssl_state->client_connp.hs_buffer);
if (ssl_state->server_connp.cert0_subject)
rs_cstring_free(ssl_state->server_connp.cert0_subject);
@ -2548,6 +2584,8 @@ static void SSLStateFree(void *p)
Ja3BufferFree(&ssl_state->server_connp.ja3_str);
if (ssl_state->server_connp.ja3_hash)
SCFree(ssl_state->server_connp.ja3_hash);
if (ssl_state->server_connp.hs_buffer)
SCFree(ssl_state->server_connp.hs_buffer);
AppLayerDecoderEventsFreeEvents(&ssl_state->tx_data.events);
@ -5096,7 +5134,6 @@ static int SSLParserTest25(void)
FAIL_IF_NULL(ssl_state);
FAIL_IF(ssl_state->client_connp.bytes_processed != 0);
FAIL_IF(ssl_state->client_connp.hs_bytes_processed != 0);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
server_hello_certificate_done,
@ -5104,7 +5141,6 @@ static int SSLParserTest25(void)
FAIL_IF(r != 0);
FAIL_IF(ssl_state->client_connp.bytes_processed != 0);
FAIL_IF(ssl_state->client_connp.hs_bytes_processed != 0);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER,
client_key_exchange_cipher_enc_hs,

@ -199,7 +199,6 @@ typedef struct SSLStateConnp_ {
uint32_t record_lengths_length;
/* offset of the beginning of the current message (including header) */
uint32_t message_start;
uint32_t message_length;
uint16_t version;
@ -210,8 +209,6 @@ typedef struct SSLStateConnp_ {
/* the no of bytes processed in the currently parsed record */
uint32_t bytes_processed;
/* the no of bytes processed in the currently parsed handshake */
uint16_t hs_bytes_processed;
uint16_t session_id_length;
@ -235,6 +232,13 @@ typedef struct SSLStateConnp_ {
JA3Buffer *ja3_str;
char *ja3_hash;
/* handshake tls fragmentation buffer. Handshake messages can be fragmented over multiple
* TLS records. */
uint8_t *hs_buffer;
uint8_t hs_buffer_message_type;
uint32_t hs_buffer_message_size;
uint32_t hs_buffer_size; /**< allocation size */
uint32_t hs_buffer_offset; /**< write offset */
} SSLStateConnp;
/**

Loading…
Cancel
Save