Coverage Report

Created: 2025-07-11 07:06

/src/rtpproxy/modules/dtls_gw/rtpp_dtls.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2022 Sippy Software, Inc., http://www.sippysoft.com
3
 * Copyright (C) 2010 Alfred E. Heggestad
4
 * Copyright (C) 2010 Creytiv.com
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 */
28
29
#include <assert.h>
30
#include <stddef.h>
31
#include <stdint.h>
32
#include <stdlib.h>
33
#include <string.h>
34
35
#include <openssl/ssl.h>
36
#include <openssl/err.h>
37
#include <openssl/rand.h>
38
39
#include "config_pp.h"
40
41
#include "rtpp_module.h"
42
#include "rtpp_codeptr.h"
43
#include "rtpp_refcnt.h"
44
#include "rtpp_str.h"
45
46
#include "rtpp_dtls.h"
47
#include "rtpp_dtls_util.h"
48
#include "rtpp_dtls_conn.h"
49
50
struct rtpp_dtls_priv {
51
    struct rtpp_dtls pub;
52
    const struct rtpp_cfg *cfsp;
53
    struct rtpp_minfo *mself;
54
    SSL_CTX *ctx;
55
    X509 *cert;
56
    char fingerprint[FP_DIGEST_STRBUF_LEN];
57
};
58
59
static const char * const srtp_profiles =
60
  "SRTP_AES128_CM_SHA1_80:"
61
  "SRTP_AES128_CM_SHA1_32:"
62
  "SRTP_AEAD_AES_128_GCM:"
63
  "SRTP_AEAD_AES_256_GCM";
64
65
const char * const cn = "dtls@rtpproxy";
66
const char * const ecname = "prime256v1";
67
68
struct rtpp_dtls_conn *rtpp_dtls_newconn(struct rtpp_dtls *,
69
  struct rtpp_stream *);
70
71
static X509 *tls_set_selfsigned_ec(SSL_CTX *, const char *, const char *);
72
static void tls_set_verify_client(SSL_CTX *);
73
74
static void
75
rtpp_dtls_dtor(struct rtpp_dtls_priv *pvt)
76
4
{
77
78
4
    X509_free(pvt->cert);
79
4
    SSL_CTX_free(pvt->ctx);
80
4
}
81
82
struct rtpp_dtls *
83
rtpp_dtls_ctor(const struct rtpp_cfg *cfsp, struct rtpp_minfo *mself)
84
4
{
85
4
    struct rtpp_dtls_priv *pvt;
86
87
4
    pvt = mod_rzmalloc(sizeof(*pvt), PVT_RCOFFS(pvt));
88
4
    if (pvt == NULL) {
89
0
        goto e0;
90
0
    }
91
4
    pvt->ctx = SSL_CTX_new(DTLS_method());
92
4
    if (pvt->ctx == NULL) {
93
0
        ERR_clear_error();
94
0
        goto e1;
95
0
    }
96
4
    pvt->cert = tls_set_selfsigned_ec(pvt->ctx, cn, ecname);
97
4
    if (pvt->cert == NULL) {
98
0
        ERR_clear_error();
99
0
        goto e2;
100
0
    }
101
4
    tls_set_verify_client(pvt->ctx);
102
4
    if (SSL_CTX_set_tlsext_use_srtp(pvt->ctx, srtp_profiles) != 0) {
103
0
        ERR_clear_error();
104
0
        goto e3;
105
0
    }
106
4
    if (rtpp_dtls_fp_gen(pvt->cert, pvt->fingerprint,
107
4
      sizeof(pvt->fingerprint)) != 0) {
108
0
        goto e3;
109
0
    }
110
4
    pvt->pub.fingerprint = pvt->fingerprint;
111
4
    pvt->pub.newconn = &rtpp_dtls_newconn;
112
4
    pvt->cfsp = cfsp;
113
4
    pvt->mself = mself;
114
4
    CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)rtpp_dtls_dtor, pvt);
115
4
    return (&(pvt->pub));
116
0
e3:
117
0
    X509_free(pvt->cert);
118
0
e2:
119
0
    SSL_CTX_free(pvt->ctx);
120
0
e1:
121
0
    mod_free(pvt);
122
0
e0:
123
0
    return (NULL);
124
0
}
125
126
struct rtpp_dtls_conn *
127
rtpp_dtls_newconn(struct rtpp_dtls *self, struct rtpp_stream *dtls_strmp)
128
24.3k
{
129
24.3k
    struct rtpp_dtls_priv *pvt;
130
24.3k
    struct rtpp_dtls_conn *conn;
131
132
24.3k
    PUB2PVT(self, pvt);
133
134
24.3k
    conn = rtpp_dtls_conn_ctor(pvt->cfsp, pvt->ctx, dtls_strmp, pvt->mself);
135
24.3k
    return (conn);
136
24.3k
}
137
138
#ifndef OPENSSL_VERSION_MAJOR
139
#define OPENSSL_VERSION_MAJOR 1
140
#endif
141
142
static uint32_t
143
dtls_rand_u32(void)
144
4
{
145
4
    uint32_t v;
146
147
4
    v = 0;
148
4
    assert(RAND_bytes((unsigned char *)&v, sizeof(v)) == 1);
149
4
    return v;
150
4
}
151
152
static int
153
verify_trust_all(int ok, X509_STORE_CTX *ctx)
154
0
{
155
0
    (void)ok;
156
0
    (void)ctx;
157
158
0
    return 1;    /* We trust the certificate from peer */
159
0
}
160
161
static void
162
tls_set_verify_client(SSL_CTX *ctx)
163
4
{
164
165
4
    SSL_CTX_set_verify_depth(ctx, 0);
166
4
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
167
4
      verify_trust_all);
168
4
}
169
170
static X509 *
171
tls_generate_cert(const char *cn)
172
4
{
173
4
    X509 *cert;
174
4
    X509_NAME *subj;
175
176
4
    cert = X509_new();
177
4
    if (!cert)
178
0
        goto e0;
179
180
4
    if (!X509_set_version(cert, 2))
181
0
        goto e1;
182
183
4
    if (!ASN1_INTEGER_set(X509_get_serialNumber(cert), dtls_rand_u32()))
184
0
        goto e1;
185
186
4
    subj = X509_NAME_new();
187
4
    if (!subj)
188
0
        goto e1;
189
190
4
    if (!X509_NAME_add_entry_by_txt(subj, "CN", MBSTRING_ASC,
191
4
        (unsigned char *)cn, (int)strlen(cn), -1, 0))
192
0
        goto e2;
193
194
4
    if (!X509_set_issuer_name(cert, subj) ||
195
4
      !X509_set_subject_name(cert, subj))
196
0
        goto e2;
197
198
4
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
199
4
    if (!X509_gmtime_adj(X509_getm_notBefore(cert), -3600*24*365) ||
200
4
      !X509_gmtime_adj(X509_getm_notAfter(cert),   3600*24*365*10))
201
0
        goto e2;
202
#else
203
    if (!X509_gmtime_adj(X509_get_notBefore(cert), -3600*24*365) ||
204
      !X509_gmtime_adj(X509_get_notAfter(cert),   3600*24*365*10))
205
        goto e2;
206
#endif
207
208
4
    X509_NAME_free(subj);
209
4
    return (cert);
210
0
e2:
211
0
    X509_NAME_free(subj);
212
0
e1:
213
0
    X509_free(cert);
214
0
e0:
215
0
    return (NULL);
216
0
}
217
218
static X509 *
219
tls_set_selfsigned_ec(SSL_CTX *ctx, const char *cn, const char *curve_n)
220
4
{
221
4
#if OPENSSL_VERSION_MAJOR < 3
222
4
    EC_KEY *eckey;
223
4
    int eccgrp;
224
4
#endif
225
4
    EVP_PKEY *key;
226
4
    X509 *cert;
227
4
    int r;
228
229
#if OPENSSL_VERSION_MAJOR >= 3
230
    key = EVP_EC_gen(curve_n);
231
    if (!key) {
232
        goto e0;
233
    }
234
#else
235
4
    key = EVP_PKEY_new();
236
4
    if (!key)
237
0
        goto e0;
238
239
4
    eccgrp = OBJ_txt2nid(curve_n);
240
4
    if (eccgrp == NID_undef)
241
0
        goto e1;
242
243
4
    eckey = EC_KEY_new_by_curve_name(eccgrp);
244
4
    if (!eckey)
245
0
        goto e1;
246
247
4
    if (!EC_KEY_generate_key(eckey))
248
0
        goto e2;
249
250
4
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
251
4
    EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
252
#else
253
    EC_KEY_set_asn1_flag(eckey, 0);
254
#endif
255
256
4
    if (!EVP_PKEY_set1_EC_KEY(key, eckey))
257
0
        goto e2;
258
4
#endif /* OPENSSL_VERSION_MAJOR */
259
260
4
    cert = tls_generate_cert(cn);
261
4
    if (cert == NULL)
262
0
        goto e2;
263
264
4
    if (!X509_set_pubkey(cert, key))
265
0
        goto e3;
266
267
4
    if (!X509_sign(cert, key, EVP_sha256()))
268
0
        goto e3;
269
270
4
    r = SSL_CTX_use_certificate(ctx, cert);
271
4
    if (r != 1)
272
0
        goto e3;
273
274
4
    r = SSL_CTX_use_PrivateKey(ctx, key);
275
4
    if (r != 1)
276
0
        goto e3;
277
278
4
#if OPENSSL_VERSION_MAJOR < 3
279
4
    EC_KEY_free(eckey);
280
4
#endif
281
4
    EVP_PKEY_free(key);
282
4
    return cert;
283
0
e3:
284
0
    X509_free(cert);
285
0
e2:
286
0
#if OPENSSL_VERSION_MAJOR < 3
287
0
    EC_KEY_free(eckey);
288
0
e1:
289
0
#endif
290
0
    EVP_PKEY_free(key);
291
0
e0:
292
0
    return (NULL);
293
0
}