Coverage Report

Created: 2026-06-13 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pjsip/tests/fuzz/fuzz-srtp.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2026 Teluu Inc. (http://www.teluu.com)
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 */
18
#include <stdint.h>
19
#include <stdlib.h>
20
#include <pjlib.h>
21
#include <pjlib-util.h>
22
#include <pjmedia.h>
23
#include <pjmedia/transport_srtp.h>
24
#include <pjmedia/transport_loop.h>
25
26
26.9k
#define kMinInputLength 16
27
13.3k
#define kMaxInputLength 5120
28
29
/* For SRTP session testing */
30
pj_pool_factory *mem;
31
32
/* SRTP key material: raw binary format */
33
static const unsigned char key_30[30] = {
34
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
35
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
36
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
37
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d
38
};
39
40
static const unsigned char key_46[46] = {
41
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
42
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
43
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
44
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
45
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
46
    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d
47
};
48
49
static void setup_crypto_config(uint8_t crypto_selector,
50
                                pjmedia_srtp_crypto *tx_crypto,
51
                                pjmedia_srtp_crypto *rx_crypto)
52
345
{
53
345
    const char *crypto_names[] = {
54
345
        "AES_CM_128_HMAC_SHA1_80",
55
345
        "AES_CM_128_HMAC_SHA1_32",
56
345
        "AES_CM_256_HMAC_SHA1_80",
57
345
        "AES_CM_256_HMAC_SHA1_32",
58
345
        "NULL_HMAC_SHA1_80",
59
345
        "NULL_HMAC_SHA1_32"
60
345
    };
61
62
345
    pj_bzero(tx_crypto, sizeof(*tx_crypto));
63
345
    pj_bzero(rx_crypto, sizeof(*rx_crypto));
64
345
    tx_crypto->name = pj_str((char*)crypto_names[crypto_selector]);
65
345
    rx_crypto->name = pj_str((char*)crypto_names[crypto_selector]);
66
67
345
    if (crypto_selector == 0 || crypto_selector == 1 ||
68
336
        crypto_selector == 4 || crypto_selector == 5) {
69
336
        tx_crypto->key.ptr = (char*)key_30;
70
336
        tx_crypto->key.slen = 30;
71
336
        rx_crypto->key.ptr = (char*)key_30;
72
336
        rx_crypto->key.slen = 30;
73
336
    } else {
74
9
        tx_crypto->key.ptr = (char*)key_46;
75
9
        tx_crypto->key.slen = 46;
76
9
        rx_crypto->key.ptr = (char*)key_46;
77
9
        rx_crypto->key.slen = 46;
78
9
    }
79
345
}
80
81
static pj_status_t create_srtp_transport(pjmedia_endpt *endpt,
82
                                         pjmedia_transport **loop_tp,
83
                                         pjmedia_transport **srtp_tp)
84
345
{
85
345
    pj_status_t status;
86
345
    pjmedia_srtp_setting srtp_opt;
87
88
345
    status = pjmedia_transport_loop_create(endpt, loop_tp);
89
345
    if (status != PJ_SUCCESS)
90
0
        return status;
91
92
345
    pjmedia_srtp_setting_default(&srtp_opt);
93
345
    srtp_opt.close_member_tp = PJ_FALSE;
94
345
    srtp_opt.use = PJMEDIA_SRTP_MANDATORY;
95
96
345
    status = pjmedia_transport_srtp_create(endpt, *loop_tp, &srtp_opt, srtp_tp);
97
345
    if (status != PJ_SUCCESS) {
98
0
        return status;
99
0
    }
100
101
345
    return PJ_SUCCESS;
102
345
}
103
104
static void fuzz_srtp_decrypt(pjmedia_transport *srtp_tp,
105
                              pj_bool_t is_rtp,
106
                              const uint8_t *pkt_data,
107
                              int pkt_len,
108
                              pj_pool_t *pool)
109
327
{
110
327
    unsigned char *pkt_buf;
111
327
    int dec_len;
112
113
327
    if (pkt_len <= 0)
114
0
        return;
115
116
327
    pkt_buf = (unsigned char*)pj_pool_alloc(pool, pkt_len);
117
327
    if (!pkt_buf)
118
0
        return;
119
120
327
    pj_memcpy(pkt_buf, pkt_data, pkt_len);
121
122
327
    dec_len = pkt_len;
123
327
    pjmedia_transport_srtp_decrypt_pkt(srtp_tp, is_rtp, pkt_buf, &dec_len);
124
327
}
125
126
void srtp_test(const uint8_t *data, size_t size)
127
345
{
128
345
    pjmedia_endpt *endpt = NULL;
129
345
    pj_pool_t *pool = NULL;
130
345
    pj_status_t status;
131
345
    pjmedia_transport *loop_tp = NULL;
132
345
    pjmedia_transport *srtp_tp = NULL;
133
345
    pjmedia_srtp_crypto tx_crypto, rx_crypto;
134
135
    /* Create media endpoint */
136
345
    status = pjmedia_endpt_create(mem, NULL, 1, &endpt);
137
345
    if (status != PJ_SUCCESS)
138
0
        return;
139
140
    /* Initialize SRTP library */
141
345
    status = pjmedia_srtp_init_lib(endpt);
142
345
    if (status != PJ_SUCCESS)
143
0
        goto cleanup;
144
145
    /* Create memory pool */
146
345
    pool = pj_pool_create(mem, "srtp-fuzz", 4000, 4000, NULL);
147
345
    if (!pool)
148
0
        goto cleanup;
149
150
    /* Create transport stack */
151
345
    status = create_srtp_transport(endpt, &loop_tp, &srtp_tp);
152
345
    if (status != PJ_SUCCESS)
153
0
        goto cleanup;
154
155
    /* Setup crypto configuration from fuzzer input */
156
345
    setup_crypto_config(data[0] % 6, &tx_crypto, &rx_crypto);
157
158
    /* Start SRTP session */
159
345
    status = pjmedia_transport_srtp_start(srtp_tp, &tx_crypto, &rx_crypto);
160
345
    if (status != PJ_SUCCESS)
161
18
        goto cleanup;
162
163
    /* Test SRTP decryption with packet data */
164
327
    fuzz_srtp_decrypt(srtp_tp, (data[1] & 0x01) ? PJ_TRUE : PJ_FALSE,
165
327
                      data + 4, (int)(size - 4), pool);
166
167
345
cleanup:
168
345
    if (srtp_tp)
169
345
        pjmedia_transport_close(srtp_tp);
170
345
    if (loop_tp)
171
345
        pjmedia_transport_close(loop_tp);
172
345
    if (pool)
173
345
        pj_pool_release(pool);
174
345
    if (endpt)
175
345
        pjmedia_endpt_destroy(endpt);
176
345
}
177
178
extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
179
13.4k
{
180
13.4k
    pj_caching_pool caching_pool;
181
182
13.4k
    if (Size < kMinInputLength || Size > kMaxInputLength) {
183
156
        return 1;
184
156
    }
185
186
    /* Init */
187
13.3k
    pj_init();
188
13.3k
    pj_caching_pool_init(&caching_pool, &pj_pool_factory_default_policy, 0);
189
13.3k
    pj_log_set_level(0);
190
191
    /* Configure the global blocking pool */
192
13.3k
    mem = &caching_pool.factory;
193
194
    /* Fuzz SRTP */
195
13.3k
    srtp_test(Data, Size);
196
197
    /* Cleanup */
198
13.3k
    pj_caching_pool_destroy(&caching_pool);
199
200
13.3k
    return 0;
201
13.4k
}