reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
DtlsSocket.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#ifdef USE_SSL
6
7#include <iostream>
8#ifdef WIN32
9#include <winsock2.h> // struct timeval
10#else
11#include <sys/time.h>
12#endif
13#include "rutil/ResipAssert.h"
14#include <ctype.h>
15#include <string.h>
16
17#include "DtlsFactory.hxx"
18#include "DtlsSocket.hxx"
19
20#include <utility>
21
22using namespace std;
23using namespace dtls;
24
25// Our local timers
27{
28 public:
29 DtlsSocketTimer(unsigned int seq,DtlsSocket *socket): DtlsTimer(seq),mSocket(socket){}
31 {
32 }
33
34 void expired()
35 {
36 mSocket->expired(this);
37 }
38 private:
39 DtlsSocket *mSocket;
40};
41
42int dummy_cb(int d, X509_STORE_CTX *x)
43{
44 return 1;
45}
46
47DtlsSocket::DtlsSocket(std::unique_ptr<DtlsSocketContext> socketContext, DtlsFactory* factory, enum SocketType type):
48 mSocketContext(std::move(socketContext)),
49 mFactory(factory),
50 mSsl(newSsl(factory, type)),
51 mInBio(SSL_get_rbio(mSsl)),
52 mOutBio(SSL_get_wbio(mSsl)),
53 mSocketType(type),
54 mHandshakeCompleted(false),
55 mHandshakeFailed(false),
56 mCreated(std::chrono::steady_clock::now())
57{
58 mSocketContext->setDtlsSocket(this);
59}
60
61DtlsSocket::DtlsSocket(std::unique_ptr<DtlsSocketContext> socketContext, DtlsFactory* factory, SSL* acceptedSsl, const std::string& peer):
62 mSocketContext(std::move(socketContext)),
63 mFactory(factory),
64 mSsl(acceptedSsl),
65 mInBio(SSL_get_rbio(acceptedSsl)),
66 mOutBio(SSL_get_wbio(acceptedSsl)),
67 mSocketType(Server),
68 mHandshakeCompleted(false),
69 mHandshakeFailed(false),
70 mCreated(std::chrono::steady_clock::now()),
71 mCookiePeer(peer)
72{
73 mSocketContext->setDtlsSocket(this);
74
75 // DTLSv1_listen left the SSL doing cookie exchange, so the cookie callbacks may still be
76 // asked to check one (eg. for a retransmitted ClientHello)
77 SSL_set_ex_data(mSsl, DtlsFactory::cookiePeerIndex(), &mCookiePeer);
78}
79
80SSL*
81DtlsSocket::newSsl(DtlsFactory* factory, SocketType type)
82{
83 resip_assert(factory->mContext);
84 SSL* ssl=SSL_new(factory->mContext);
85 resip_assert(ssl!=0);
86
87 switch(type)
88 {
89 case Client:
90 SSL_set_connect_state(ssl);
91 break;
92 case Server:
93 SSL_set_accept_state(ssl);
94 SSL_set_verify(ssl,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, dummy_cb);
95 break;
96 default:
97 resip_assert(0);
98 }
99
100 // Datagrams are passed in and out through memory BIOs: an empty one reads as -1 with the
101 // retry flag set, so OpenSSL wants more input rather than seeing the end of the stream
102 SSL_set_bio(ssl, BIO_new(BIO_s_mem()), BIO_new(BIO_s_mem()));
103
104 // A memory BIO can't tell OpenSSL the MTU, so it would fall back to its minimum (small
105 // records): set it, and don't let OpenSSL query it (which also keeps it through SSL_clear)
106 SSL_set_options(ssl, SSL_OP_NO_QUERY_MTU);
107 DTLS_set_link_mtu(ssl, (long)factory->mMtu);
108 return ssl;
109}
110
112{
113 if(mReadTimer) mReadTimer->invalidate();
114
115 // Free the SSL - note: this also free's the BIO's. No SSL_shutdown(): the close_notify it
116 // writes would only go to the memory BIO freed here, never to the peer, and before the
117 // handshake has completed it just leaves an error on this thread's queue.
118 SSL_free(mSsl);
119}
120
121void
123{
124 // The timer has fired, so nothing will fire it again (the timer context still holds it while
125 // it fires)
126 if(timer == mReadTimer.get())
127 {
128 mReadTimer.reset();
129 }
130
131 handleTimeout();
132}
133
134void
136{
137 resip_assert(mSocketType == Client);
138
139 doHandshakeIteration();
140}
141
142bool
143DtlsSocket::handlePacketMaybe(const unsigned char* bytes, size_t len)
144{
146
147 if(pType!=DtlsFactory::dtls)
148 return false;
149
150 int r;
151 BIO_reset(mInBio);
152 BIO_reset(mOutBio);
153
154 r=BIO_write(mInBio,bytes,(int)len);
155 resip_assert(r==(int)len); // Can't happen
156
157 // Note: we must catch any below exceptions--if there are any
158 if(mHandshakeCompleted)
159 {
160 handlePacketAfterHandshake();
161 }
162 else
163 {
164 doHandshakeIteration();
165 }
166
167 return true;
168}
169
170void
171DtlsSocket::handleTimeout()
172{
173 if(mHandshakeCompleted || mHandshakeFailed)
174 return;
175
176 if(serverHandshakeTimeLeft() <= std::chrono::steady_clock::duration::zero())
177 {
178 mHandshakeFailed = true;
179 mSocketContext->handshakeFailed("DTLS handshake not completed in time");
180 scheduleTimer(); // clears the timer
181 return;
182 }
183
184 BIO_reset(mInBio);
185 BIO_reset(mOutBio);
186
187 // Retransmits the last flight if OpenSSL's timer has expired (doubling it each time), and
188 // fails once OpenSSL has retransmitted as many times as it allows
189 ERR_clear_error();
190 if(DTLSv1_handle_timeout(mSsl) < 0)
191 {
192 char errbuf[1024];
193 errbuf[0]=0;
194 ERR_error_string_n(ERR_peek_error(),errbuf,sizeof(errbuf));
195 mHandshakeFailed = true;
196 mSocketContext->handshakeFailed(errbuf[0] ? errbuf : "DTLS handshake timed out");
197 ERR_clear_error();
198 }
199
200 writeOutput();
201 scheduleTimer();
202}
203
204void
205DtlsSocket::handlePacketAfterHandshake()
206{
207 // No application data is expected over DTLS-SRTP, but reading processes what the peer sends
208 // after the handshake: eg. its last flight again if it didn't get our final one, which OpenSSL
209 // answers by retransmitting ours
210 ERR_clear_error();
211 unsigned char buffer[2048];
212 while(SSL_read(mSsl, buffer, sizeof(buffer)) > 0)
213 {
214 }
215 ERR_clear_error();
216
217 writeOutput();
218}
219
220void
221DtlsSocket::writeOutput()
222{
223 // The memory BIO holds everything OpenSSL wrote - perhaps several datagrams, run together. Send
224 // it as datagrams of whole DTLS records (RFC 6347 4.1.1: a datagram can hold several), each no
225 // larger than the MTU, which OpenSSL fits each record to. A record is a 13 byte header -
226 // content type, version, epoch, sequence number, then its length - and that many bytes.
227 unsigned char *outBioData;
228 int outBioLen=BIO_get_mem_data(mOutBio,&outBioData);
229 const size_t len = outBioLen > 0 ? (size_t)outBioLen : 0;
230 const size_t mtu = mFactory->mMtu;
231 size_t datagramStart = 0;
232 size_t pos = 0;
233 while(pos + 13 <= len)
234 {
235 const size_t recordLen = 13 + ((size_t)outBioData[pos + 11] << 8 | outBioData[pos + 12]);
236 if(pos + recordLen > len)
237 {
238 break; // can't happen: OpenSSL only writes whole records; the rest is sent as it is
239 }
240 if(pos > datagramStart && pos + recordLen - datagramStart > mtu)
241 {
242 mSocketContext->write(outBioData + datagramStart, (unsigned int)(pos - datagramStart));
243 datagramStart = pos;
244 }
245 pos += recordLen;
246 }
247 if(len > datagramStart)
248 {
249 mSocketContext->write(outBioData + datagramStart, (unsigned int)(len - datagramStart));
250 }
251}
252
253std::chrono::steady_clock::duration
254DtlsSocket::serverHandshakeTimeLeft() const
255{
256 if(mSocketType != Server || mFactory->mServerHandshakeTimeout == 0)
257 {
258 return (std::chrono::steady_clock::duration::max)(); // (parenthesized: Windows' max macro)
259 }
260 return std::chrono::seconds(mFactory->mServerHandshakeTimeout) - getAge();
261}
262
263void
264DtlsSocket::scheduleTimer()
265{
266 // Replaces any timer set before: the timer context frees an invalidated timer when it's due
267 if(mReadTimer)
268 {
269 mReadTimer->invalidate();
270 mReadTimer.reset();
271 }
272
273 // OpenSSL runs the retransmission timer while the handshake is in progress (starting at 1
274 // second and doubling); fire ours when it expires
275 struct timeval tv;
276 if(!mHandshakeCompleted && !mHandshakeFailed && DTLSv1_get_timeout(mSsl, &tv) == 1)
277 {
278 unsigned int waitMs = (unsigned int)tv.tv_sec * 1000 + ((unsigned int)tv.tv_usec + 999) / 1000;
279 // A server socket's handshake fails when its time is up, if that's sooner
280 const std::chrono::steady_clock::duration timeLeft = serverHandshakeTimeLeft();
281 if(timeLeft != (std::chrono::steady_clock::duration::max)())
282 {
283 const long long timeLeftMs = std::chrono::duration_cast<std::chrono::milliseconds>(timeLeft).count() + 1;
284 if(timeLeftMs < (long long)waitMs)
285 {
286 waitMs = timeLeftMs > 0 ? (unsigned int)timeLeftMs : 1;
287 }
288 }
289 mReadTimer = std::make_shared<DtlsSocketTimer>(0, this);
290 mReadTimer->setLock(mSocketContext->timerLock());
291 mFactory->mTimerContext->addTimer(mReadTimer, waitMs > 0 ? waitMs : 1);
292 }
293}
294
295void
296DtlsSocket::doHandshakeIteration()
297{
298 int r;
299 char errbuf[1024];
300 int sslerr;
301
302 if(mHandshakeCompleted || mHandshakeFailed)
303 return;
304
305 // OpenSSL requires this thread's error queue to be empty before the call, since
306 // SSL_get_error() checks it first (the handshake state machine currently clears it
307 // itself, but that isn't documented)
308 ERR_clear_error();
309 r=SSL_do_handshake(mSsl);
310 errbuf[0]=0;
311 ERR_error_string_n(ERR_peek_error(),errbuf,sizeof(errbuf));
312
313 // Now handle handshake errors */
314 switch(sslerr=SSL_get_error(mSsl,r))
315 {
316 case SSL_ERROR_NONE:
317 mHandshakeCompleted = true;
318 mSocketContext->handshakeCompleted();
319 break;
320 case SSL_ERROR_WANT_READ:
321 // Waiting for the peer's next flight (any we've just written goes out below)
322 break;
323 default:
324 cerr << "SSL error " << sslerr << endl;
325
326 mHandshakeFailed = true;
327 mSocketContext->handshakeFailed(errbuf);
328 // Don't leave this failure's errors on the queue: the next OpenSSL call on this thread
329 // that checks SSL_get_error() without clearing it first would take them as its own
330 ERR_clear_error();
331 // Note: need to fall through to propagate alerts, if any
332 break;
333 }
334
335 writeOutput();
336 scheduleTimer();
337}
338
339static bool
340equalsIgnoreCase(const char* a, const char* b)
341{
342 for(; *a && *b; a++, b++)
343 {
344 if(tolower((unsigned char)*a) != tolower((unsigned char)*b))
345 return false;
346 }
347 return *a == *b;
348}
349
350// The RFC 8122 hash function textual names we accept: those of the IANA registry,
351// less md2 and md5, which aren't safe to authenticate a certificate with
352static const EVP_MD*
353fingerprintDigest(const char* hashFunction)
354{
355 if(!hashFunction) return 0;
356 if(equalsIgnoreCase(hashFunction, "sha-1")) return EVP_sha1();
357 if(equalsIgnoreCase(hashFunction, "sha-224")) return EVP_sha224();
358 if(equalsIgnoreCase(hashFunction, "sha-256")) return EVP_sha256();
359 if(equalsIgnoreCase(hashFunction, "sha-384")) return EVP_sha384();
360 if(equalsIgnoreCase(hashFunction, "sha-512")) return EVP_sha512();
361 return 0;
362}
363
364bool
366{
367 return fingerprintDigest(hashFunction) != 0;
368}
369
370bool
371DtlsSocket::getRemoteFingerprint(const char* hashFunction, char *fingerprint, size_t fingerprintSize)
372{
373 const EVP_MD* digest = fingerprintDigest(hashFunction);
374 if(!digest)
375 return false;
376
377 X509 *x;
378#if OPENSSL_VERSION_NUMBER < 0x30000000L
379 x=SSL_get_peer_certificate(mSsl);
380#else
381 x=SSL_get1_peer_certificate(mSsl);
382#endif
383 if(!x) // No certificate
384 return false;
385
386 bool computed = computeFingerprint(x, digest, fingerprint, fingerprintSize);
387 X509_free(x);
388 return computed;
389}
390
391bool
392DtlsSocket::checkFingerprint(const char* hashFunction, const char* fingerprint)
393{
394 char fprint[EVP_MAX_MD_SIZE * 3];
395
396 // The whole fingerprint must match; its hex digits may be in either case (RFC 8122 section 5)
397 return fingerprint &&
398 getRemoteFingerprint(hashFunction, fprint, sizeof(fprint)) &&
399 equalsIgnoreCase(fprint, fingerprint);
400}
401
402void
404{
405 mFactory->getMyCertFingerprint(fingerprint);
406}
407
408// Maps the SRTP protection profile DTLS negotiated to libsrtp's - returns false if there
409// isn't one, or libsrtp doesn't support it (the AES-GCM profiles need libsrtp built with GCM)
410static bool
411negotiatedSrtpProfile(SRTP_PROTECTION_PROFILE* negotiated, srtp_profile_t& profile)
412{
413 if(!negotiated)
414 return false;
415
416 switch(negotiated->id)
417 {
418 case SRTP_AES128_CM_SHA1_80: profile = srtp_profile_aes128_cm_sha1_80; break;
419 case SRTP_AES128_CM_SHA1_32: profile = srtp_profile_aes128_cm_sha1_32; break;
420 case SRTP_AEAD_AES_128_GCM: profile = srtp_profile_aead_aes_128_gcm; break;
421 case SRTP_AEAD_AES_256_GCM: profile = srtp_profile_aead_aes_256_gcm; break;
422 default: return false;
423 }
424
425 srtp_crypto_policy_t policy;
426 return srtp_crypto_policy_set_from_profile_for_rtp(&policy, profile) == srtp_err_status_ok &&
427 srtp_crypto_policy_set_from_profile_for_rtcp(&policy, profile) == srtp_err_status_ok;
428}
429
432{
433 //TODO: probably an exception candidate
434 resip_assert(mHandshakeCompleted);
435
436 SrtpSessionKeys keys;
437
438 srtp_profile_t profile;
440 {
441 return keys;
442 }
443 unsigned int keyLen = srtp_profile_get_master_key_length(profile);
444 unsigned int saltLen = srtp_profile_get_master_salt_length(profile);
445
446 // RFC 5764 section 4.2: client key, server key, client salt, server salt
447 unsigned char material[2 * SRTP_MAX_KEY_LEN];
448 size_t materialLen = 2 * (keyLen + saltLen);
449 if(materialLen > sizeof(material) ||
450 !SSL_export_keying_material(
451 mSsl,
452 material,
453 materialLen,
454 "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0))
455 {
456 return keys;
457 }
458
459 size_t offset = 0;
460
461 keys.clientMasterKey.assign(material + offset, material + offset + keyLen);
462 offset += keys.clientMasterKey.size();
463 keys.serverMasterKey.assign(material + offset, material + offset + keyLen);
464 offset += keys.serverMasterKey.size();
465 keys.clientMasterSalt.assign(material + offset, material + offset + saltLen);
466 offset += keys.clientMasterSalt.size();
467 keys.serverMasterSalt.assign(material + offset, material + offset + saltLen);
468 offset += keys.serverMasterSalt.size();
469
470 OPENSSL_cleanse(material, sizeof(material));
471 return keys;
472}
473
474SRTP_PROTECTION_PROFILE*
476{
477 //TODO: probably an exception candidate
478 resip_assert(mHandshakeCompleted);
479 return SSL_get_selected_srtp_profile(mSsl);
480}
481
482void
483DtlsSocket::computeFingerprint(X509 *cert, char *fingerprint)
484{
485 bool computed = computeFingerprint(cert, EVP_sha256(), fingerprint, FingerprintSize);
486 resip_assert(computed);
487}
488
489bool
490DtlsSocket::computeFingerprint(X509 *cert, const EVP_MD* digest, char *fingerprint, size_t fingerprintSize)
491{
492 unsigned char md[EVP_MAX_MD_SIZE];
493 unsigned int n;
494
495 if(X509_digest(cert,digest,md,&n) != 1 || n == 0 ||
496 fingerprintSize < n * 3) // 2 hex digits and a colon (or the terminating null) per byte
497 {
498 return false;
499 }
500
501 static const char hex[] = "0123456789ABCDEF";
502 for(unsigned int i=0;i<n;i++)
503 {
504 *fingerprint++ = hex[md[i] >> 4];
505 *fingerprint++ = hex[md[i] & 0x0f];
506 *fingerprint++ = (i < n-1) ? ':' : 0;
507 }
508 return true;
509}
510
511// Fills in a policy for one direction's keys, from the negotiated profile
512static void
513initSrtpPolicy(srtp_policy_t& policy, srtp_profile_t profile, const std::vector<unsigned char>& key, const std::vector<unsigned char>& salt)
514{
515 memset(&policy, 0, sizeof(srtp_policy_t));
516 policy.window_size = 128;
517 policy.allow_repeat_tx = 1;
518
519 uint8_t* keyAndSalt = new uint8_t[SRTP_MAX_KEY_LEN];
520 memcpy(keyAndSalt, key.data(), key.size());
521 memcpy(keyAndSalt + key.size(), salt.data(), salt.size());
522 policy.key = keyAndSalt;
523
524 // Can't fail: negotiatedSrtpProfile has checked libsrtp supports the profile
525 srtp_crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile);
526 srtp_crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile);
527 policy.next = NULL;
528}
529
530bool
531DtlsSocket::createSrtpSessionPolicies(srtp_policy_t& outboundPolicy, srtp_policy_t& inboundPolicy)
532{
533 resip_assert(mHandshakeCompleted);
534
535 srtp_profile_t profile;
537 {
538 return false;
539 }
540
542 if(srtp_key.clientMasterKey.empty())
543 {
544 return false;
545 }
546
547 srtp_policy_t client_policy;
548 initSrtpPolicy(client_policy, profile, srtp_key.clientMasterKey, srtp_key.clientMasterSalt);
549 srtp_policy_t server_policy;
550 initSrtpPolicy(server_policy, profile, srtp_key.serverMasterKey, srtp_key.serverMasterSalt);
551
552 if (mSocketType == Client)
553 {
554 client_policy.ssrc.type = ssrc_any_outbound;
555 outboundPolicy = client_policy;
556
557 server_policy.ssrc.type = ssrc_any_inbound;
558 inboundPolicy = server_policy;
559 }
560 else
561 {
562 server_policy.ssrc.type = ssrc_any_outbound;
563 outboundPolicy = server_policy;
564
565 client_policy.ssrc.type = ssrc_any_inbound;
566 inboundPolicy = client_policy;
567 }
568
569 OPENSSL_cleanse(srtp_key.clientMasterKey.data(), srtp_key.clientMasterKey.size());
570 OPENSSL_cleanse(srtp_key.serverMasterKey.data(), srtp_key.serverMasterKey.size());
571 OPENSSL_cleanse(srtp_key.clientMasterSalt.data(), srtp_key.clientMasterSalt.size());
572 OPENSSL_cleanse(srtp_key.serverMasterSalt.data(), srtp_key.serverMasterSalt.size());
573 return true;
574}
575
576DtlsListener::DtlsListener(DtlsFactory* factory) :
577 mFactory(factory),
578 mSsl(0)
579{
580}
581
583{
584 if(mSsl) SSL_free(mSsl);
585}
586
588DtlsListener::handlePacket(const unsigned char* bytes, size_t len, const std::string& peer,
589 std::vector<unsigned char>& response,
590 const std::function<std::unique_ptr<DtlsSocketContext>()>& makeContext)
591{
592 response.clear();
593 if(len == 0 || DtlsFactory::demuxPacket(bytes, len) != DtlsFactory::dtls)
594 {
595 return 0;
596 }
597
598 if(!mSsl)
599 {
600 mSsl = DtlsSocket::newSsl(mFactory, DtlsSocket::Server);
601 SSL_set_ex_data(mSsl, DtlsFactory::cookiePeerIndex(), &mPeer);
602 }
603 mPeer = peer;
604
605 BIO* inBio = SSL_get_rbio(mSsl);
606 BIO* outBio = SSL_get_wbio(mSsl);
607 BIO_reset(inBio);
608 BIO_reset(outBio);
609 int r = BIO_write(inBio, bytes, (int)len);
610 resip_assert(r == (int)len); // Can't happen
611
612 // Answers a ClientHello without a valid cookie for peer with a HelloVerifyRequest, keeping
613 // nothing: returns 1 only for a ClientHello with a valid cookie
614 ERR_clear_error();
615 BIO_ADDR* address = BIO_ADDR_new();
616 r = DTLSv1_listen(mSsl, address);
617 BIO_ADDR_free(address);
618
619 unsigned char* out = 0;
620 long outLen = BIO_get_mem_data(outBio, &out);
621 if(outLen > 0)
622 {
623 response.assign(out, out + outLen);
624 }
625
626 if(r <= 0)
627 {
628 // Not a ClientHello with a valid cookie (r is 0), or one OpenSSL couldn't handle (r < 0,
629 // so start again with a fresh SSL). Don't leave its errors for the next caller on this thread.
630 ERR_clear_error();
631 if(r < 0)
632 {
633 SSL_free(mSsl);
634 mSsl = 0;
635 }
636 return 0;
637 }
638
639 // The peer has proved it receives at its address: the SSL, holding its ClientHello, becomes
640 // the new server socket's, which carries on the handshake
641 DtlsSocket* socket = new DtlsSocket(makeContext(), mFactory, mSsl, peer);
642 mSsl = 0;
643 socket->doHandshakeIteration();
644 return socket;
645}
646
647#endif
648/* ====================================================================
649
650 Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
651 Copyright (c) 2007-2008, Eric Rescorla and Derek MacDonald
652 All rights reserved.
653
654 Redistribution and use in source and binary forms, with or without
655 modification, are permitted provided that the following conditions are
656 met:
657
658 1. Redistributions of source code must retain the above copyright
659 notice, this list of conditions and the following disclaimer.
660
661 2. Redistributions in binary form must reproduce the above copyright
662 notice, this list of conditions and the following disclaimer in the
663 documentation and/or other materials provided with the distribution.
664
665 3. None of the contributors names may be used to endorse or promote
666 products derived from this software without specific prior written
667 permission.
668
669 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
670 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
671 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
672 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
673 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
674 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
675 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
676 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
677 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
678 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
679 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
680
681 ==================================================================== */
struct x509_st X509
struct ssl_st SSL
static const EVP_MD * fingerprintDigest(const char *hashFunction)
static bool equalsIgnoreCase(const char *a, const char *b)
static void initSrtpPolicy(srtp_policy_t &policy, srtp_profile_t profile, const std::vector< unsigned char > &key, const std::vector< unsigned char > &salt)
int dummy_cb(int d, X509_STORE_CTX *x)
static bool negotiatedSrtpProfile(SRTP_PROTECTION_PROFILE *negotiated, srtp_profile_t &profile)
static Data digest("digest")
#define resip_assert(x)
This file needs to work for both C and C++ code.
void getMyCertFingerprint(char *fingerprint)
static PacketType demuxPacket(const unsigned char *buf, size_t len)
DtlsSocket * handlePacket(const unsigned char *bytes, size_t len, const std::string &peer, std::vector< unsigned char > &response, const std::function< std::unique_ptr< DtlsSocketContext >()> &makeContext)
DtlsSocketTimer(unsigned int seq, DtlsSocket *socket)
std::chrono::steady_clock::duration getAge() const
static const size_t FingerprintSize
bool createSrtpSessionPolicies(srtp_policy_t &outboundPolicy, srtp_policy_t &inboundPolicy)
static void computeFingerprint(X509 *cert, char *fingerprint)
static bool isFingerprintHashFunctionSupported(const char *hashFunction)
bool checkFingerprint(const char *hashFunction, const char *fingerprint)
SRTP_PROTECTION_PROFILE * getSrtpProfile()
bool getRemoteFingerprint(const char *hashFunction, char *fingerprint, size_t fingerprintSize)
void expired(DtlsSocketTimer *)
void getMyCertFingerprint(char *fingerprint)
bool handlePacketMaybe(const unsigned char *bytes, size_t len)
SrtpSessionKeys getSrtpSessionKeys()
std::vector< unsigned char > serverMasterSalt
std::vector< unsigned char > clientMasterKey
std::vector< unsigned char > clientMasterSalt
std::vector< unsigned char > serverMasterKey
unsigned char uint8_t
Definition stdint.h:83