Coverage Report

Created: 2026-09-28 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata/src/detect-tls-random.c
Line
Count
Source
1
/* Copyright (C) 2022 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
#include "suricata-common.h"
19
#include "threads.h"
20
#include "detect.h"
21
22
#include "detect-parse.h"
23
#include "detect-engine.h"
24
#include "detect-engine-buffer.h"
25
#include "detect-engine-mpm.h"
26
#include "detect-content.h"
27
28
#include "flow.h"
29
#include "stream-tcp.h"
30
31
#include "app-layer.h"
32
#include "app-layer-ssl.h"
33
#include "detect-engine-prefilter.h"
34
#include "detect-tls-random.h"
35
36
423
#define DETECT_TLS_RANDOM_TIME_LEN  4
37
134
#define DETECT_TLS_RANDOM_BYTES_LEN 28
38
39
static int DetectTlsRandomTimeSetup(DetectEngineCtx *, Signature *, const char *);
40
static int DetectTlsRandomBytesSetup(DetectEngineCtx *, Signature *, const char *);
41
static int DetectTlsRandomSetup(DetectEngineCtx *, Signature *, const char *);
42
static InspectionBuffer *GetRandomTimeData(DetectEngineThreadCtx *det_ctx,
43
        const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
44
        const int list_id);
45
static InspectionBuffer *GetRandomBytesData(DetectEngineThreadCtx *det_ctx,
46
        const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
47
        const int list_id);
48
static InspectionBuffer *GetRandomData(DetectEngineThreadCtx *det_ctx,
49
        const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
50
        const int list_id);
51
52
static int g_tls_random_time_buffer_id = 0;
53
static int g_tls_random_bytes_buffer_id = 0;
54
static int g_tls_random_buffer_id = 0;
55
56
void DetectTlsRandomTimeRegister(void)
57
79
{
58
79
    sigmatch_table[DETECT_TLS_RANDOM_TIME].name = "tls.random_time";
59
79
    sigmatch_table[DETECT_TLS_RANDOM_TIME].desc = "sticky buffer to match specifically and only "
60
79
                                                  "on the first 4 bytes of a TLS random buffer";
61
79
    sigmatch_table[DETECT_TLS_RANDOM_TIME].url = "/rules/tls-keywords.html#tls-random-time";
62
79
    sigmatch_table[DETECT_TLS_RANDOM_TIME].Setup = DetectTlsRandomTimeSetup;
63
79
    sigmatch_table[DETECT_TLS_RANDOM_TIME].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
64
65
    /* Register engine for Server random */
66
79
    DetectAppLayerInspectEngineRegister("tls.random_time", ALPROTO_TLS, SIG_FLAG_TOSERVER,
67
79
            TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectBufferGeneric, GetRandomTimeData);
68
79
    DetectAppLayerMpmRegister("tls.random_time", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
69
79
            GetRandomTimeData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
70
71
    /* Register engine for Client random */
72
79
    DetectAppLayerInspectEngineRegister("tls.random_time", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
73
79
            TLS_STATE_SERVER_HELLO, DetectEngineInspectBufferGeneric, GetRandomTimeData);
74
79
    DetectAppLayerMpmRegister("tls.random_time", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
75
79
            GetRandomTimeData, ALPROTO_TLS, TLS_STATE_SERVER_HELLO);
76
77
79
    DetectBufferTypeSetDescriptionByName("tls.random_time", "TLS Random Time");
78
79
79
    g_tls_random_time_buffer_id = DetectBufferTypeGetByName("tls.random_time");
80
79
}
81
82
void DetectTlsRandomBytesRegister(void)
83
79
{
84
79
    sigmatch_table[DETECT_TLS_RANDOM_BYTES].name = "tls.random_bytes";
85
79
    sigmatch_table[DETECT_TLS_RANDOM_BYTES].desc =
86
79
            "sticky buffer to match specifically and only on the last 28 bytes of a TLS random "
87
79
            "buffer";
88
79
    sigmatch_table[DETECT_TLS_RANDOM_BYTES].url = "/rules/tls-keywords.html#tls-random-bytes";
89
79
    sigmatch_table[DETECT_TLS_RANDOM_BYTES].Setup = DetectTlsRandomBytesSetup;
90
79
    sigmatch_table[DETECT_TLS_RANDOM_BYTES].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
91
92
    /* Register engine for Server random */
93
79
    DetectAppLayerInspectEngineRegister("tls.random_bytes", ALPROTO_TLS, SIG_FLAG_TOSERVER,
94
79
            TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectBufferGeneric, GetRandomBytesData);
95
79
    DetectAppLayerMpmRegister("tls.random_bytes", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
96
79
            GetRandomBytesData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
97
98
    /* Register engine for Client random */
99
79
    DetectAppLayerInspectEngineRegister("tls.random_bytes", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
100
79
            TLS_STATE_SERVER_HELLO, DetectEngineInspectBufferGeneric, GetRandomBytesData);
101
79
    DetectAppLayerMpmRegister("tls.random_bytes", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
102
79
            GetRandomBytesData, ALPROTO_TLS, TLS_STATE_SERVER_HELLO);
103
104
79
    DetectBufferTypeSetDescriptionByName("tls.random_bytes", "TLS Random Bytes");
105
106
79
    g_tls_random_bytes_buffer_id = DetectBufferTypeGetByName("tls.random_bytes");
107
79
}
108
109
/**
110
 * \brief Registration function for keyword: tls.random
111
 */
112
void DetectTlsRandomRegister(void)
113
79
{
114
79
    DetectTlsRandomTimeRegister();
115
79
    DetectTlsRandomBytesRegister();
116
117
79
    sigmatch_table[DETECT_TLS_RANDOM].name = "tls.random";
118
79
    sigmatch_table[DETECT_TLS_RANDOM].desc =
119
79
            "sticky buffer to match specifically and only on a TLS random buffer";
120
79
    sigmatch_table[DETECT_TLS_RANDOM].url = "/rules/tls-keywords.html#tls-random";
121
79
    sigmatch_table[DETECT_TLS_RANDOM].Setup = DetectTlsRandomSetup;
122
79
    sigmatch_table[DETECT_TLS_RANDOM].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
123
124
    /* Register engine for Server random */
125
79
    DetectAppLayerInspectEngineRegister("tls.random", ALPROTO_TLS, SIG_FLAG_TOSERVER, 0,
126
79
            DetectEngineInspectBufferGeneric, GetRandomData);
127
79
    DetectAppLayerMpmRegister("tls.random", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
128
79
            GetRandomData, ALPROTO_TLS, 0);
129
130
    /* Register engine for Client random */
131
79
    DetectAppLayerInspectEngineRegister("tls.random", ALPROTO_TLS, SIG_FLAG_TOCLIENT, 0,
132
79
            DetectEngineInspectBufferGeneric, GetRandomData);
133
79
    DetectAppLayerMpmRegister("tls.random", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
134
79
            GetRandomData, ALPROTO_TLS, 0);
135
136
79
    DetectBufferTypeSetDescriptionByName("tls.random", "TLS Random");
137
138
79
    g_tls_random_buffer_id = DetectBufferTypeGetByName("tls.random");
139
79
}
140
141
/**
142
 * \brief this function setup the tls.random_time sticky buffer keyword used in the rule
143
 *
144
 * \param de_ctx   Pointer to the Detection Engine Context
145
 * \param s        Pointer to the Signature to which the current keyword belongs
146
 * \param str      Should hold an empty string always
147
 *
148
 * \retval 0  On success
149
 * \retval -1 On failure
150
 */
151
static int DetectTlsRandomTimeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
152
4.39k
{
153
4.39k
    if (SCDetectBufferSetActiveList(de_ctx, s, g_tls_random_time_buffer_id) < 0)
154
3
        return -1;
155
156
4.39k
    if (SCDetectSignatureSetAppProto(s, ALPROTO_TLS) < 0)
157
77
        return -1;
158
159
4.31k
    return 0;
160
4.39k
}
161
162
/**
163
 * \brief this function setup the tls.random_bytes sticky buffer keyword used in the rule
164
 *
165
 * \param de_ctx   Pointer to the Detection Engine Context
166
 * \param s        Pointer to the Signature to which the current keyword belongs
167
 * \param str      Should hold an empty string always
168
 *
169
 * \retval 0  On success
170
 * \retval -1 On failure
171
 */
172
static int DetectTlsRandomBytesSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
173
1.90k
{
174
1.90k
    if (SCDetectBufferSetActiveList(de_ctx, s, g_tls_random_bytes_buffer_id) < 0)
175
3
        return -1;
176
177
1.89k
    if (SCDetectSignatureSetAppProto(s, ALPROTO_TLS) < 0)
178
5
        return -1;
179
180
1.89k
    return 0;
181
1.89k
}
182
183
/**
184
 * \brief this function setup the tls.random sticky buffer keyword used in the rule
185
 *
186
 * \param de_ctx   Pointer to the Detection Engine Context
187
 * \param s        Pointer to the Signature to which the current keyword belongs
188
 * \param str      Should hold an empty string always
189
 *
190
 * \retval 0  On success
191
 * \retval -1 On failure
192
 */
193
static int DetectTlsRandomSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
194
1.81k
{
195
1.81k
    if (SCDetectBufferSetActiveList(de_ctx, s, g_tls_random_buffer_id) < 0)
196
4
        return -1;
197
198
1.81k
    if (SCDetectSignatureSetAppProto(s, ALPROTO_TLS) < 0)
199
1.23k
        return -1;
200
201
580
    return 0;
202
1.81k
}
203
204
static InspectionBuffer *GetRandomTimeData(DetectEngineThreadCtx *det_ctx,
205
        const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
206
        const int list_id)
207
358
{
208
358
    InspectionBuffer *buffer = SCInspectionBufferGet(det_ctx, list_id);
209
358
    if (buffer->inspect == NULL) {
210
354
        const SSLState *ssl_state = (SSLState *)f->alstate;
211
354
        if (flow_flags & STREAM_TOSERVER) {
212
264
            if (!(ssl_state->flags & TLS_TS_RANDOM_SET))
213
60
                return NULL;
214
264
        } else {
215
90
            if (!(ssl_state->flags & TLS_TC_RANDOM_SET))
216
5
                return NULL;
217
90
        }
218
289
        const uint8_t *data;
219
289
        if (flow_flags & STREAM_TOSERVER) {
220
204
            data = ssl_state->client_connp.random;
221
204
        } else {
222
85
            data = ssl_state->server_connp.random;
223
85
        }
224
289
        SCInspectionBufferSetupAndApplyTransforms(
225
289
                det_ctx, list_id, buffer, data, DETECT_TLS_RANDOM_TIME_LEN, transforms);
226
289
    }
227
293
    return buffer;
228
358
}
229
230
static InspectionBuffer *GetRandomBytesData(DetectEngineThreadCtx *det_ctx,
231
        const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
232
        const int list_id)
233
147
{
234
147
    InspectionBuffer *buffer = SCInspectionBufferGet(det_ctx, list_id);
235
147
    if (buffer->inspect == NULL) {
236
145
        const SSLState *ssl_state = (SSLState *)f->alstate;
237
145
        if (flow_flags & STREAM_TOSERVER) {
238
66
            if (!(ssl_state->flags & TLS_TS_RANDOM_SET))
239
6
                return NULL;
240
79
        } else {
241
79
            if (!(ssl_state->flags & TLS_TC_RANDOM_SET))
242
5
                return NULL;
243
79
        }
244
134
        const uint8_t *data;
245
134
        if (flow_flags & STREAM_TOSERVER) {
246
60
            data = ssl_state->client_connp.random + DETECT_TLS_RANDOM_TIME_LEN;
247
74
        } else {
248
74
            data = ssl_state->server_connp.random + DETECT_TLS_RANDOM_TIME_LEN;
249
74
        }
250
134
        SCInspectionBufferSetupAndApplyTransforms(
251
134
                det_ctx, list_id, buffer, data, DETECT_TLS_RANDOM_BYTES_LEN, transforms);
252
134
    }
253
136
    return buffer;
254
147
}
255
256
static InspectionBuffer *GetRandomData(DetectEngineThreadCtx *det_ctx,
257
        const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
258
        const int list_id)
259
305
{
260
305
    InspectionBuffer *buffer = SCInspectionBufferGet(det_ctx, list_id);
261
305
    if (buffer->inspect == NULL) {
262
301
        const SSLState *ssl_state = (SSLState *)f->alstate;
263
301
        if (flow_flags & STREAM_TOSERVER) {
264
148
            if (!(ssl_state->flags & TLS_TS_RANDOM_SET))
265
66
                return NULL;
266
153
        } else {
267
153
            if (!(ssl_state->flags & TLS_TC_RANDOM_SET))
268
28
                return NULL;
269
153
        }
270
207
        const uint8_t *data;
271
207
        if (flow_flags & STREAM_TOSERVER) {
272
82
            data = ssl_state->client_connp.random;
273
125
        } else {
274
125
            data = ssl_state->server_connp.random;
275
125
        }
276
207
        SCInspectionBufferSetupAndApplyTransforms(
277
207
                det_ctx, list_id, buffer, data, TLS_RANDOM_LEN, transforms);
278
207
    }
279
211
    return buffer;
280
305
}