cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
dtls.c
Go to the documentation of this file.
1
9#include "webrtc_internal.h"
10
11#include <openssl/ec.h>
12#include <openssl/evp.h>
13#include <openssl/x509.h>
14#include <pthread.h>
15#include <stdio.h>
16#include <string.h>
17
22#define CWIST_DTLS_MTU 1200
23
37 *cert_out = NULL;
38 *pkey_out = NULL;
39
41 if (!kctx)
42 return -1;
45 return -1;
46 }
47 EVP_PKEY *pkey = NULL;
48 if (EVP_PKEY_keygen(kctx, &pkey) <= 0) {
50 return -1;
51 }
53
54 X509 *cert = X509_new();
55 if (!cert) {
56 EVP_PKEY_free(pkey);
57 return -1;
58 }
59 X509_set_version(cert, 2);
62 X509_gmtime_adj(X509_getm_notAfter(cert), 60L * 60L * 24L * 30);
63 X509_set_pubkey(cert, pkey);
64 X509_NAME *name = X509_get_subject_name(cert);
65 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"cwist-webrtc", -1, -1, 0);
66 X509_set_issuer_name(cert, name);
67 if (X509_sign(cert, pkey, EVP_sha256()) == 0) {
68 X509_free(cert);
69 EVP_PKEY_free(pkey);
70 return -1;
71 }
72 *cert_out = cert;
73 *pkey_out = pkey;
74 return 0;
75}
76
90int cwist_dtls_fingerprint(X509 *cert, char *out, size_t cap) {
91 uint8_t der[2048];
92 int der_len = i2d_X509(cert, NULL);
93 if (der_len <= 0 || (size_t)der_len > sizeof(der))
94 return -1;
95 uint8_t *p = der;
96 i2d_X509(cert, &p);
98 unsigned int dlen = 0;
99 if (!EVP_Digest(der, (size_t)der_len, digest, &dlen, EVP_sha256(), NULL))
100 return -1;
101 size_t off = 0;
102 for (unsigned int i = 0; i < dlen && off + 3 < cap; i++)
103 off += (size_t)snprintf(out + off, cap - off, "%s%02X", i ? ":" : "", digest[i]);
104 return off > 0 && off < cap ? 0 : -1;
105}
106
120SSL_CTX *cwist_dtls_ctx_new(int is_server, X509 *cert, EVP_PKEY *pkey) {
122 if (!ctx)
123 return NULL;
125 if (is_server) {
126 if (SSL_CTX_use_certificate(ctx, cert) != 1 || SSL_CTX_use_PrivateKey(ctx, pkey) != 1 ||
127 SSL_CTX_check_private_key(ctx) != 1) {
128 SSL_CTX_free(ctx);
129 return NULL;
130 }
131 } else {
132 /* Peer fingerprint verification is optional at MVP; the test pins the
133 * expected fingerprint via the SDP exchange. */
135 }
136 return ctx;
137}
138
142unsigned int cwist_dtls_link_mtu(void) {
143 return CWIST_DTLS_MTU;
144}
145
146/* ---- datagram BIO ----
147 *
148 * DTLS needs datagram semantics: one BIO_read returns exactly one datagram and
149 * one BIO_write is exactly one datagram. A memory BIO is a byte stream, so
150 * records written back to back get concatenated and a fixed-size read can cut
151 * one in half across two UDP packets. This BIO keeps the boundaries and also
152 * skips the extra copy through the memory buffer: reads hand over the datagram
153 * the event loop is processing, writes go straight to the ctx send batch. */
154
155static BIO_METHOD *g_dgram_method;
156static pthread_once_t g_dgram_once = PTHREAD_ONCE_INIT;
157
159static int dgram_bio_read(BIO *bio, char *out, int outl) {
160 struct cwist_webrtc_conn *conn = BIO_get_data(bio);
162 if (!conn || !conn->dtls_in) {
164 return -1;
165 }
166 size_t n = conn->dtls_in_len;
167 if (outl < 0 || n > (size_t)outl)
168 n = outl < 0 ? 0 : (size_t)outl; /* DTLS drops a truncated datagram. */
169 memcpy(out, conn->dtls_in, n);
170 conn->dtls_in = NULL;
171 conn->dtls_in_len = 0;
172 return (int)n;
173}
174
176static int dgram_bio_write(BIO *bio, const char *in, int inl) {
177 struct cwist_webrtc_conn *conn = BIO_get_data(bio);
179 if (!conn || inl < 0) return -1;
180 cwist_webrtc_conn_dtls_out(conn, (const uint8_t *)in, (size_t)inl);
181 return inl;
182}
183
186static long dgram_bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
187 (void)bio;
188 (void)num;
189 (void)ptr;
190 return cmd == BIO_CTRL_FLUSH ? 1 : 0;
191}
192
194static int dgram_bio_create(BIO *bio) {
195 BIO_set_init(bio, 1);
196 return 1;
197}
198
200static void dgram_method_init(void) {
201 BIO_METHOD *m = BIO_meth_new(BIO_get_new_index() | BIO_TYPE_SOURCE_SINK, "cwist-webrtc-dgram");
202 if (!m) return;
203 if (!BIO_meth_set_read(m, dgram_bio_read) || !BIO_meth_set_write(m, dgram_bio_write) ||
204 !BIO_meth_set_ctrl(m, dgram_bio_ctrl) || !BIO_meth_set_create(m, dgram_bio_create)) {
206 return;
207 }
208 g_dgram_method = m;
209}
210
212 pthread_once(&g_dgram_once, dgram_method_init);
213 if (!g_dgram_method) return NULL;
214 BIO *bio = BIO_new(g_dgram_method);
215 if (bio) BIO_set_data(bio, conn);
216 return bio;
217}
int cwist_dtls_fingerprint(X509 *cert, char *out, size_t cap)
Compute the SHA-256 fingerprint of a certificate in SDP format.
Definition dtls.c:90
int cwist_dtls_generate_cert(X509 **cert_out, EVP_PKEY **pkey_out)
Generate an ephemeral self-signed ECDSA certificate for DTLS.
Definition dtls.c:36
SSL_CTX * cwist_dtls_ctx_new(int is_server, X509 *cert, EVP_PKEY *pkey)
Create a DTLS SSL_CTX for the client or server role.
Definition dtls.c:120
unsigned int cwist_dtls_link_mtu(void)
Return the DTLS link MTU in bytes.
Definition dtls.c:142
BIO * cwist_dtls_bio_new(struct cwist_webrtc_conn *conn)
Datagram BIO for conn: reads return conn->dtls_in once, writes go to cwist_webrtc_conn_dtls_out() one...
Definition dtls.c:211
#define CWIST_DTLS_MTU
DTLS record/link MTU assumed for the media path (bytes). Used to size outgoing DTLS records so they f...
Definition dtls.c:22
mbedTLS TLS backend: EVP subset (HMAC digest tags, AES-256-CBC).
#define EVP_MAX_MD_SIZE
Definition evp.h:23
#define EVP_sha256
Definition evp.h:25
size_t cap
Definition otel.c:56
#define SSL_VERIFY_NONE
Definition ssl.h:80
#define SSL_CTX_check_private_key
Definition ssl.h:113
#define SSL_CTX_new
Definition ssl.h:98
#define SSL_CTX_free
Definition ssl.h:99
#define SSL_CTX_set_verify
Definition ssl.h:124
struct cwist_mtls_ctx SSL_CTX
Definition ssl.h:43
#define SSL_CTX_set_min_proto_version
Definition ssl.h:106
One peer: ICE state, DTLS session, SCTP association.
const uint8_t * dtls_in
void cwist_webrtc_conn_dtls_out(struct cwist_webrtc_conn *conn, const uint8_t *data, size_t len)
Queue one datagram to the conn's peer (owner thread).
Definition webrtc.c:554
Internal types and cross-file helpers for the WebRTC DataChannel module (ICE-lite + DTLS + SCTP over ...