1 /*
2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006-2013 Belledonne Communications, Grenoble
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 */
19 
20 
21 #include "mediastreamer2/mediastream.h"
22 #include "mediastreamer2/dtls_srtp.h"
23 
24 #ifdef _WIN32
25 #include <malloc.h>
26 #endif
27 
28 #include "bctoolbox/crypto.h"
29 
30 
31 
32 typedef struct _DtlsBcToolBoxContexts {
33 	bctbx_x509_certificate_t *crt;
34 	bctbx_ssl_config_t *ssl_config;
35 	bctbx_ssl_context_t *ssl;
36 	bctbx_rng_context_t *rng;
37 	bctbx_signing_key_t *pkey;
38 	ms_mutex_t ssl_context_mutex;
39 } DtlsBcToolBoxContext;
40 
41 /**
42  * incoming DTLS message are stored in a chain buffer to feed polarssl handshake when needed
43  */
44 typedef struct _DtlsRawPacket {
45 	unsigned char *data;
46 	size_t length;
47 	void *next;
48 } DtlsRawPacket;
49 
50 /* DTLS only allow use of AES128 so we have 16 bytes key and 14 byte salt in any case */
51 #define DTLS_SRTP_KEY_LEN 16
52 #define DTLS_SRTP_SALT_LEN 14
53 
54 #define DTLS_STATUS_CONTEXT_NOT_READY 0
55 #define DTLS_STATUS_CONTEXT_READY 1
56 #define DTLS_STATUS_HANDSHAKE_ONGOING 2
57 #define DTLS_STATUS_HANDSHAKE_OVER 3
58 
59 #define READ_TIMEOUT_MS 1000
60 
61 struct _MSDtlsSrtpContext{
62 	MSMediaStreamSessions *stream_sessions;
63 	MSDtlsSrtpRole role; /**< can be unset(at init on caller side), client or server */
64 	char peer_fingerprint[256]; /**< used to store peer fingerprint passed through SDP */
65 
66 	RtpTransportModifier *rtp_modifier;
67 	RtpTransportModifier *rtcp_modifier;
68 
69 	DtlsBcToolBoxContext *rtp_dtls_context; /**< a structure containing all contexts needed by polarssl for RTP channel */
70 	DtlsBcToolBoxContext *rtcp_dtls_context; /**< a structure containing all contexts needed by polarssl for RTCP channel */
71 
72 	uint8_t rtp_channel_status; /**< channel status : DTLS_STATUS_CONTEXT_NOT_READY, DTLS_STATUS_CONTEXT_READY, DTLS_STATUS_HANDSHAKE_ONGOING, DTLS_STATUS_HANDSHAKE_OVER */
73 	uint8_t rtcp_channel_status; /**< channel status : DTLS_STATUS_CONTEXT_NOT_READY, DTLS_STATUS_CONTEXT_READY, DTLS_STATUS_HANDSHAKE_ONGOING, DTLS_STATUS_HANDSHAKE_OVER */
74 
75 	DtlsRawPacket *rtp_incoming_buffer; /**< buffer of incoming DTLS packet to be read by polarssl callback */
76 	DtlsRawPacket *rtcp_incoming_buffer; /**< buffer of incoming DTLS packet to be read by polarssl callback */
77 
78 	uint64_t rtp_time_reference; /**< an epoch in ms, used to manage retransmission when we are client */
79 	uint64_t rtcp_time_reference; /**< an epoch in ms, used to manage retransmission when we are client */
80 };
81 
82 /***********************************************/
83 /***** LOCAL FUNCTIONS                     *****/
84 /***********************************************/
85 /*** DtlsBcToolBox context create/dstroy ***/
86 
ms_dtls_srtp_bctbx_context_new(void)87 DtlsBcToolBoxContext *ms_dtls_srtp_bctbx_context_new(void) {
88 	// allocate the memory
89 	DtlsBcToolBoxContext *ctx = ms_new0(DtlsBcToolBoxContext,1);
90 
91 	// create and initialise the requested fields
92 	ctx->rng = bctbx_rng_context_new();
93 	ctx->pkey = bctbx_signing_key_new();
94 	ctx->crt = bctbx_x509_certificate_new();
95 	ctx->ssl_config = bctbx_ssl_config_new();
96 	ctx->ssl = bctbx_ssl_context_new();
97 	ms_mutex_init(&(ctx->ssl_context_mutex), NULL);
98 
99 	return ctx;
100 }
101 
ms_dtls_srtp_bctbx_context_free(DtlsBcToolBoxContext * ctx)102 void ms_dtls_srtp_bctbx_context_free(DtlsBcToolBoxContext *ctx) {
103 	if (ctx != NULL) {
104 		bctbx_rng_context_free(ctx->rng);
105 		bctbx_signing_key_free(ctx->pkey);
106 		bctbx_x509_certificate_free(ctx->crt);
107 		bctbx_ssl_context_free(ctx->ssl);
108 		bctbx_ssl_config_free(ctx->ssl_config);
109 		ms_mutex_destroy(&(ctx->ssl_context_mutex));
110 
111 		ms_free(ctx);
112 	}
113 }
114 
115 
116 /**************************/
117 /**** Helper functions ****/
get_timeval_in_millis(void)118 static ORTP_INLINE uint64_t get_timeval_in_millis(void) {
119 	struct timeval t;
120 	ortp_gettimeofday(&t,NULL);
121 	return (1000LL*t.tv_sec)+(t.tv_usec/1000LL);
122 }
123 
124 /**
125  * @Brief Compute the certificate fingerprint(hash of DER formated certificate)
126  * hash function to use shall be the same used by certificate signature(this is a way to ensure that the hash function is available at both ends as they already agreed on certificate)
127  * However, peer may provide a fingerprint generated with another hash function(indicated at the fingerprint header).
128  * In case certificate and fingerprint hash function differs, issue a warning and use the fingerprint one
129  *
130  * @param[in]	certificate		Certificate we shall compute the fingerprint
131  * @param[in]	peer_fingerprint	Fingerprint received from peer, check its header to get the hash function used to generate it
132  *
133  * @return 0 if the fingerprint doesn't match, 1 is they do.
134  */
ms_dtls_srtp_check_certificate_fingerprint(const bctbx_x509_certificate_t * certificate,const char * peer_fingerprint)135 static uint8_t ms_dtls_srtp_check_certificate_fingerprint(const bctbx_x509_certificate_t *certificate, const char *peer_fingerprint) {
136 	char fingerprint[256]; /* maximum length of the fingerprint for sha-512: 8+3*64+1 so we're good with 256 bytes buffer */
137 	bctbx_md_type_t hash_function = BCTBX_MD_UNDEFINED;
138 	bctbx_md_type_t certificate_signature_hash_function = BCTBX_MD_UNDEFINED;
139 	int32_t ret = 0;
140 
141 	/* get Hash algorithm used from peer fingerprint */
142 	if (strncasecmp(peer_fingerprint, "sha-1 ", 6) ==0 ) {
143 		hash_function = BCTBX_MD_SHA1;
144 	} else if (strncasecmp(peer_fingerprint, "sha-224 ", 8) ==0 ){
145 		hash_function = BCTBX_MD_SHA224;
146 	} else if (strncasecmp(peer_fingerprint, "sha-256 ", 8) ==0 ){
147 		hash_function = BCTBX_MD_SHA256;
148 	} else if (strncasecmp(peer_fingerprint, "sha-384 ", 8) ==0 ){
149 		hash_function = BCTBX_MD_SHA384;
150 	} else if (strncasecmp(peer_fingerprint, "sha-512 ", 8) ==0 ){
151 		hash_function = BCTBX_MD_SHA512;
152 	} else { /* we have an unknown hash function: return null */
153 		ms_error("DTLS-SRTP received invalid peer fingerprint, hash function unknown");
154 		return 0;
155 	}
156 
157 	/* retrieve the one used for the certificate signature */
158 	bctbx_x509_certificate_get_signature_hash_function(certificate, &certificate_signature_hash_function);
159 
160 	/* check that hash function used match the one used for certificate signature */
161 	if (hash_function != certificate_signature_hash_function) {
162 		ms_warning("DTLS-SRTP peer fingerprint generated using a different hash function that the one used for certificate signature, peer is nasty but lucky we have the hash function required anyway");
163 	}
164 
165 	/* compute the fingerprint using the requested hash function */
166 	ret = bctbx_x509_certificate_get_fingerprint(certificate, fingerprint, 255, hash_function);
167 	if (ret <= 0) {
168 		ms_error("DTLS Handshake successful but unable to compute peer certificate fingerprint : bctoolbox returns [-0x%x]", -ret);
169 	}
170 
171 	/* compare fingerprints */
172 	if (strncasecmp((const char *)fingerprint, peer_fingerprint, strlen((const char *)fingerprint)) == 0) {
173 		return 1;
174 	} else {
175 		ms_error("DTLS Handshake successful but fingerprints differ received : %s computed %s", peer_fingerprint, fingerprint);
176 		return 0;
177 	}
178 }
179 
180 /**
181  * Convert a bctoolbox defined value for SRTP protection profile to the mediastreamer enumeration of SRTP protection profile
182  * @param[in]	dtls_srtp_protection_profile	A DTLS-SRTP protection profile defined by polarssl
183  * @return the matching profile defined in mediatream.h
184  */
ms_dtls_srtp_bctbx_protection_profile_to_ms_crypto_suite(bctbx_dtls_srtp_profile_t dtls_srtp_protection_profile)185 static MSCryptoSuite ms_dtls_srtp_bctbx_protection_profile_to_ms_crypto_suite(bctbx_dtls_srtp_profile_t dtls_srtp_protection_profile) {
186 	switch(dtls_srtp_protection_profile) {
187 		case BCTBX_SRTP_AES128_CM_HMAC_SHA1_80:
188 			return MS_AES_128_SHA1_80;
189 		case BCTBX_SRTP_AES128_CM_HMAC_SHA1_32:
190 			return MS_AES_128_SHA1_32;
191 		case BCTBX_SRTP_NULL_HMAC_SHA1_80:
192 			return MS_NO_CIPHER_SHA1_80;
193 		case BCTBX_SRTP_NULL_HMAC_SHA1_32: /* this profile is defined in DTLS-SRTP rfc but not implemented by libsrtp */
194 			return MS_CRYPTO_SUITE_INVALID;
195 		default:
196 			return MS_CRYPTO_SUITE_INVALID;
197 	}
198 }
199 
schedule_rtp(struct _RtpTransportModifier * t)200 static void schedule_rtp(struct _RtpTransportModifier *t) {
201 	MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data;
202 	/* it is not a dtls packet, but manage anyway the retransmission timer */
203 	if (ctx->role == MSDtlsSrtpRoleIsClient) { /* only if we are client */
204 		uint64_t current_time = get_timeval_in_millis();
205 		if (ctx->rtp_time_reference>0) { /* only when retransmission timer is armed */
206 			if (current_time - ctx->rtp_time_reference > READ_TIMEOUT_MS) {
207 				ms_message("DTLS repeating rtp ssl_handshake for context [%p]",ctx);
208 				ms_mutex_lock(&ctx->rtp_dtls_context->ssl_context_mutex);
209 				bctbx_ssl_handshake(ctx->rtp_dtls_context->ssl);
210 				ms_mutex_unlock(&ctx->rtp_dtls_context->ssl_context_mutex);
211 				ctx->rtp_time_reference = get_timeval_in_millis();
212 			}
213 		}
214 	}
215 
216 }
schedule_rtcp(struct _RtpTransportModifier * t)217 static void schedule_rtcp(struct _RtpTransportModifier *t) {
218 	MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data;
219 	if (ctx->role == MSDtlsSrtpRoleIsClient) { /* only if we are client */
220 		uint64_t current_time = get_timeval_in_millis();
221 		if (ctx->rtcp_time_reference>0) { /* only when retransmission timer is armed */
222 			if (current_time - ctx->rtcp_time_reference > READ_TIMEOUT_MS) {
223 				ms_message("DTLS repeating rtcp ssl_handshake for context [%p]",ctx);
224 				ms_mutex_lock(&ctx->rtcp_dtls_context->ssl_context_mutex);
225 				bctbx_ssl_handshake(ctx->rtcp_dtls_context->ssl);
226 				ms_mutex_unlock(&ctx->rtcp_dtls_context->ssl_context_mutex);
227 				ctx->rtcp_time_reference = get_timeval_in_millis();
228 			}
229 		}
230 
231 	}
232 }
233 /**
234  * Check if the incoming message is a DTLS packet.
235  * If it is, store it in the context incoming buffer and call the polarssl function wich will process it.
236  * This function also manages the client retransmission timer
237  *
238  * @param[in] 		msg	the incoming message
239  * @param[in/out]	ctx	the context containing the incoming buffer to store the DTLS packet
240  * @param[out]		ret	the value returned by the polarssl function processing the packet(ssl_handshake)
241  * @param[in]		is_rtp	TRUE if we are dealing with a RTP channel packet, FALSE for RTCP channel
242  * @return TRUE if packet is a DTLS one, false otherwise
243  */
ms_dtls_srtp_process_dtls_packet(mblk_t * msg,MSDtlsSrtpContext * ctx,int * ret,bool_t is_rtp)244 static bool_t ms_dtls_srtp_process_dtls_packet(mblk_t *msg, MSDtlsSrtpContext *ctx, int *ret, bool_t is_rtp) {
245 	size_t msgLength = msgdsize(msg);
246 	uint64_t *time_reference = (is_rtp == TRUE)?&(ctx->rtp_time_reference):&(ctx->rtcp_time_reference);
247 	bctbx_ssl_context_t *ssl = (is_rtp == TRUE)?ctx->rtp_dtls_context->ssl:ctx->rtcp_dtls_context->ssl;
248 	ms_mutex_t *mutex = (is_rtp == TRUE)?&ctx->rtp_dtls_context->ssl_context_mutex:&ctx->rtcp_dtls_context->ssl_context_mutex;
249 	uint8_t channel_status = (is_rtp == TRUE)?(ctx->rtp_channel_status):(ctx->rtcp_channel_status);
250 
251 	// check if incoming message length is compatible with potential DTLS message
252 	if (msgLength<RTP_FIXED_HEADER_SIZE) {
253 		return FALSE;
254 	}
255 
256 	/* check if it is a DTLS packet (first byte B as 19 < B < 64) rfc5764 section 5.1.2 */
257 	if ((*(msg->b_rptr)>19) && (*(msg->b_rptr)<64)) {
258 
259 		DtlsRawPacket *incoming_dtls_packet;
260 		incoming_dtls_packet = (DtlsRawPacket *)ms_malloc0(sizeof(DtlsRawPacket));
261 		incoming_dtls_packet->next=NULL;
262 		incoming_dtls_packet->data=(unsigned char *)ms_malloc(msgLength);
263 		incoming_dtls_packet->length=msgLength;
264 		memcpy(incoming_dtls_packet->data, msg->b_rptr, msgLength);
265 
266 		/*required by webrtc in server case when ice is not completed yet*/
267 		/* no more required because change is performed by ice.c once a check list is ready rtp_session_update_remote_sock_addr(rtp_session, msg,is_rtp,FALSE);*/
268 
269 		ms_message("DTLS Receive %s packet len %d sessions: %p rtp session %p", is_rtp==TRUE?"RTP":"RTCP", (int)msgLength, ctx->stream_sessions, ctx->stream_sessions->rtp_session);
270 
271 		/* store the packet in the incoming buffer */
272 		if (is_rtp == TRUE) {
273 			if (ctx->rtp_incoming_buffer==NULL) { /* buffer is empty */
274 				ctx->rtp_incoming_buffer = incoming_dtls_packet;
275 			} else { /* queue it at the end of current buffer */
276 				DtlsRawPacket *last_packet = ctx->rtp_incoming_buffer;
277 				while (last_packet->next != NULL) last_packet = last_packet->next;
278 				last_packet->next = incoming_dtls_packet;
279 			}
280 		} else {
281 			if (ctx->rtcp_incoming_buffer==NULL) { /* buffer is empty */
282 				ctx->rtcp_incoming_buffer = incoming_dtls_packet;
283 			} else { /* queue it at the end of current buffer */
284 				DtlsRawPacket *last_packet = ctx->rtcp_incoming_buffer;
285 				while (last_packet->next != NULL) last_packet = last_packet->next;
286 				last_packet->next = incoming_dtls_packet;
287 			}
288 		}
289 
290 		/* while DTLS handshake is on going route DTLS packets to bctoolbox engine through ssl_handshake() */
291 		if (channel_status != DTLS_STATUS_HANDSHAKE_OVER) {
292 			/* role is unset but we receive a packet: we are caller and shall initialise as server and then process the incoming packet */
293 			if (ctx->role == MSDtlsSrtpRoleUnset) {
294 				ms_dtls_srtp_set_role(ctx, MSDtlsSrtpRoleIsServer); /* this call will update role and complete server setup */
295 				ms_dtls_srtp_start(ctx); /* complete the ssl setup and change channel_status to DTLS_STATUS_HANDSHAKE_ONGOING on both RTP and RTCP channel*/
296 			}
297 			ms_mutex_lock(mutex);
298 			/* process the packet and store result */
299 			*ret = bctbx_ssl_handshake(ssl);
300 
301 			/* if we are client, manage the retransmission timer */
302 			if (ctx->role == MSDtlsSrtpRoleIsClient) {
303 				*time_reference = get_timeval_in_millis();
304 			}
305 			ms_mutex_unlock(mutex);
306 		} else { /* when DTLS handshake is over, route DTLS packets to bctoolbox engine through ssl_read() */
307 			/* we need a buffer to store the message read even if we don't use it */
308 			unsigned char *buf = ms_malloc(msgLength+1);
309 			ms_mutex_lock(mutex);
310 			*ret = bctbx_ssl_read(ssl, buf, msgLength);
311 			ms_mutex_unlock(mutex);
312 		}
313 
314 		/* report the error in logs only when different than requested read(waiting for data) */
315 		if (*ret<0 && *ret != BCTBX_ERROR_NET_WANT_READ) {
316 			char err_str[512];
317 			err_str[0]='\0';
318 			bctbx_strerror(*ret, err_str, 512);
319 			ms_warning("DTLS handhake returns -0x%x : %s [on sessions: %p rtp session %p]", -*ret, err_str, ctx->stream_sessions, ctx->stream_sessions->rtp_session);
320 		}
321 
322 		return TRUE;
323 	}
324 
325 	return FALSE;
326 
327 }
328 
ms_dtls_srtp_check_channels_status(MSDtlsSrtpContext * ctx)329 static void ms_dtls_srtp_check_channels_status(MSDtlsSrtpContext *ctx) {
330 
331 	if (((ctx->rtp_channel_status == DTLS_STATUS_HANDSHAKE_OVER) && (rtp_session_rtcp_mux_enabled(ctx->stream_sessions->rtp_session)))
332 		|| ((ctx->rtp_channel_status == DTLS_STATUS_HANDSHAKE_OVER) && (ctx->rtcp_channel_status == DTLS_STATUS_HANDSHAKE_OVER))) {
333 		OrtpEventData *eventData;
334 		OrtpEvent *ev;
335 		/* send event */
336 		ev=ortp_event_new(ORTP_EVENT_DTLS_ENCRYPTION_CHANGED);
337 		eventData=ortp_event_get_data(ev);
338 		eventData->info.dtls_stream_encrypted=1;
339 		rtp_session_dispatch_event(ctx->stream_sessions->rtp_session, ev);
340 		ms_message("DTLS Event dispatched to all: secrets are on for this stream");
341 	}
342 }
343 
344 /********************************************/
345 /**** polarssl DTLS packet I/O functions ****/
346 
347 /**
348 * Send a DTLS packet via RTP.
349 *
350 * DTLS calls this method to send a DTLS packet via the RTP session.
351 *
352 * @param ctx
353 *    Pointer to the MSDtlsSrtpContext structure.
354 * @param data
355 *    Points to DTLS message to send.
356 * @param length
357 *    The length in bytes of the data
358 * @return
359 *    length of data sent
360 */
ms_dtls_srtp_rtp_sendData(void * ctx,const unsigned char * data,size_t length)361 static int ms_dtls_srtp_rtp_sendData (void *ctx, const unsigned char *data, size_t length ){
362 	MSDtlsSrtpContext *context = (MSDtlsSrtpContext *)ctx;
363 	RtpSession *session = context->stream_sessions->rtp_session;
364 	RtpTransport *rtpt=NULL;
365 	mblk_t *msg;
366 	int ret;
367 
368 	ms_message("DTLS Send RTP packet len %d sessions: %p rtp session %p", (int)length, context->stream_sessions, context->stream_sessions->rtp_session);
369 
370 	/* get RTP transport from session */
371 	rtp_session_get_transports(session,&rtpt,NULL);
372 
373 	/* generate message from raw data */
374 	msg = rtp_session_create_packet_raw((uint8_t *)data, length);
375 
376 	ret = meta_rtp_transport_modifier_inject_packet_to_send(rtpt, context->rtp_modifier, msg , 0);
377 
378 	freemsg(msg);
379 	return ret;
380 }
381 
382 /**
383 * Send a DTLS packet via RTCP.
384 *
385 * DTLS calls this method to send a DTLS packet via the RTCP session.
386 *
387 * @param ctx
388 *    Pointer to the MSDtlsSrtpContext structure.
389 * @param data
390 *    Points to DTLS message to send.
391 * @param length
392 *    The length in bytes of the data
393 * @return
394 *    length of data sent
395 */
ms_dtls_srtp_rtcp_sendData(void * ctx,const unsigned char * data,size_t length)396 static int ms_dtls_srtp_rtcp_sendData (void *ctx, const unsigned char *data, size_t length ){
397 	MSDtlsSrtpContext *context = (MSDtlsSrtpContext *)ctx;
398 	RtpSession *session = context->stream_sessions->rtp_session;
399 	RtpTransport *rtcpt=NULL;
400 	mblk_t *msg;
401 	int ret;
402 
403 	ms_message("DTLS Send RTCP packet len %d sessions: %p rtp session %p", (int)length, context->stream_sessions, context->stream_sessions->rtp_session);
404 
405 	/* get RTCP transport from session */
406 	rtp_session_get_transports(session,NULL,&rtcpt);
407 
408 	/* generate message from raw data */
409 	msg = rtp_session_create_packet_raw((uint8_t *)data, length);
410 
411 	ret = meta_rtp_transport_modifier_inject_packet_to_send(rtcpt, context->rtcp_modifier, msg , 0);
412 	freemsg(msg);
413 
414 	return ret;
415 }
416 
417 
ms_dtls_srtp_rtp_DTLSread(void * ctx,unsigned char * buf,size_t len)418 static int ms_dtls_srtp_rtp_DTLSread (void *ctx, unsigned char *buf, size_t len) {
419 	MSDtlsSrtpContext *context = (MSDtlsSrtpContext *)ctx;
420 
421 	/* do we have something in the incoming buffer */
422 	if (context->rtp_incoming_buffer == NULL) {
423 		return BCTBX_ERROR_NET_WANT_READ;
424 	} else { /* read the first packet in the buffer and delete it */
425 		DtlsRawPacket *next_packet = context->rtp_incoming_buffer->next;
426 		size_t dataLength = context->rtp_incoming_buffer->length;
427 		memcpy(buf, context->rtp_incoming_buffer->data, dataLength);
428 		ms_free(context->rtp_incoming_buffer->data);
429 		ms_free(context->rtp_incoming_buffer);
430 		context->rtp_incoming_buffer = next_packet;
431 
432 		return (int)dataLength;
433 	}
434 }
435 
ms_dtls_srtp_rtcp_DTLSread(void * ctx,unsigned char * buf,size_t len)436 static int ms_dtls_srtp_rtcp_DTLSread (void *ctx, unsigned char *buf, size_t len) {
437 	MSDtlsSrtpContext *context = (MSDtlsSrtpContext *)ctx;
438 
439 	/* do we have something in the incoming buffer */
440 	if (context->rtcp_incoming_buffer == NULL) {
441 		return BCTBX_ERROR_NET_WANT_READ;
442 	} else { /* read the first packet in the buffer and delete it */
443 		DtlsRawPacket *next_packet = context->rtcp_incoming_buffer->next;
444 		size_t dataLength = context->rtcp_incoming_buffer->length;
445 		memcpy(buf, context->rtcp_incoming_buffer->data, dataLength);
446 		ms_free(context->rtcp_incoming_buffer->data);
447 		ms_free(context->rtcp_incoming_buffer);
448 		context->rtcp_incoming_buffer = next_packet;
449 
450 		return (int)dataLength;
451 	}
452 }
453 
454 
455 //static int ms_dtls_srtp_rtp_DTLSread_timeout (void *ctx, unsigned char *buf, size_t len, uint32_t timeout) {
456 //	return ms_dtls_srtp_rtp_DTLSread(ctx, buf, len); /* ms_dtls_srtp_DTLSread is non blocking */
457 //}
458 
459 //static int ms_dtls_srtp_rtcp_DTLSread_timeout (void *ctx, unsigned char *buf, size_t len, uint32_t timeout) {
460 //	return ms_dtls_srtp_rtcp_DTLSread(ctx, buf, len); /* ms_dtls_srtp_DTLSread is non blocking */
461 //}
462 
463 
464 /*******************************************************/
465 /**** Transport Modifier Sender/Receiver functions  ****/
466 
ms_dtls_srtp_rtp_process_on_receive(struct _RtpTransportModifier * t,mblk_t * msg)467 static int ms_dtls_srtp_rtp_process_on_receive(struct _RtpTransportModifier *t, mblk_t *msg){
468 	MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data;
469 
470 	int ret;
471 	size_t msgLength = msgdsize(msg);
472 
473 	/* check if we have an on-going handshake */
474 	if (ctx->rtp_channel_status == DTLS_STATUS_CONTEXT_NOT_READY) {
475 		return (int)msgLength;
476 	}
477 
478 	// check incoming message length
479 	if (msgLength<RTP_FIXED_HEADER_SIZE) {
480 		return (int)msgLength;
481 	}
482 
483 	/* check if it is a DTLS packet and process it */
484 	if (ms_dtls_srtp_process_dtls_packet(msg, ctx, &ret, TRUE) == TRUE){
485 
486 		if ((ret==0) && (ctx->rtp_channel_status == DTLS_STATUS_HANDSHAKE_ONGOING)) { /* handshake is over, give the keys to srtp : 128 bits client write - 128 bits server write - 112 bits client salt - 112 server salt */
487 			MSCryptoSuite agreed_srtp_protection_profile = MS_CRYPTO_SUITE_INVALID;
488 
489 			ctx->rtp_channel_status = DTLS_STATUS_HANDSHAKE_OVER;
490 
491 			/* check the srtp profile get selected during handshake */
492 			agreed_srtp_protection_profile = ms_dtls_srtp_bctbx_protection_profile_to_ms_crypto_suite(bctbx_ssl_get_dtls_srtp_protection_profile(ctx->rtp_dtls_context->ssl));
493 			if ( agreed_srtp_protection_profile == MS_CRYPTO_SUITE_INVALID) {
494 				ms_message("DTLS Handshake successful but unable to agree on srtp_profile to use");
495 			} else {
496 				if (ms_dtls_srtp_check_certificate_fingerprint(bctbx_ssl_get_peer_certificate(ctx->rtp_dtls_context->ssl), (const char *)(ctx->peer_fingerprint)) == 1) {
497 					char dtls_srtp_key_material[128];
498 					size_t dtls_srt_key_material_length = 128;
499 					uint8_t *key = (uint8_t *)ms_malloc0(256);
500 					ms_message("DTLS Handshake on RTP channel successful and fingerprints match, srtp protection profile %d", agreed_srtp_protection_profile);
501 
502 					ctx->rtp_time_reference = 0; /* unarm the timer */
503 					ret = bctbx_ssl_get_dtls_srtp_key_material(ctx->rtp_dtls_context->ssl, dtls_srtp_key_material, &dtls_srt_key_material_length);
504 					if (ret < 0) {
505 						ms_error("DTLS RTP Handshake : Unable to retrieve DTLS SRTP key material [-0x%x]", -ret);
506 						return 0;
507 					}
508 
509 					if (ctx->role == MSDtlsSrtpRoleIsServer) {
510 						/* reception(client write) key and salt +16bits padding */
511 						memcpy(key, dtls_srtp_key_material, DTLS_SRTP_KEY_LEN);
512 						memcpy(key + DTLS_SRTP_KEY_LEN, dtls_srtp_key_material+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN);
513 						ms_media_stream_sessions_set_srtp_recv_key(ctx->stream_sessions, agreed_srtp_protection_profile, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTP_STREAM);
514 						/* emission(server write) key and salt +16bits padding */
515 						memcpy(key, dtls_srtp_key_material+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN);
516 						memcpy(key + DTLS_SRTP_KEY_LEN, dtls_srtp_key_material+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN);
517 						ms_media_stream_sessions_set_srtp_send_key(ctx->stream_sessions, agreed_srtp_protection_profile, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTP_STREAM);
518 					} else if (ctx->role == MSDtlsSrtpRoleIsClient){ /* this enpoint act as DTLS client */
519 						/* emission(client write) key and salt +16bits padding */
520 						memcpy(key, dtls_srtp_key_material, DTLS_SRTP_KEY_LEN);
521 						memcpy(key + DTLS_SRTP_KEY_LEN, dtls_srtp_key_material+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN);
522 						ms_media_stream_sessions_set_srtp_send_key(ctx->stream_sessions, agreed_srtp_protection_profile, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTP_STREAM);
523 						/* reception(server write) key and salt +16bits padding */
524 						memcpy(key, dtls_srtp_key_material+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN);
525 						memcpy(key + DTLS_SRTP_KEY_LEN, dtls_srtp_key_material+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN);
526 						ms_media_stream_sessions_set_srtp_recv_key(ctx->stream_sessions, agreed_srtp_protection_profile, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTP_STREAM);
527 					}
528 
529 					ms_free(key);
530 
531 					ms_dtls_srtp_check_channels_status(ctx);
532 				}
533 			}
534 
535 			if (ctx->role != MSDtlsSrtpRoleIsServer) { /* close the connection only if we are client, if we are server, the client may ask again for last packets */
536 				/*FireFox version 43 requires DTLS channel to be kept openned, probably a bug in FireFox ret = ssl_close_notify( &(ctx->rtp_dtls_context->ssl) );*/
537 
538 			}
539 
540 		}
541 		return 0;
542 	}
543 	return (int)msgLength;
544 }
545 
ms_dtls_srtp_rtcp_process_on_receive(struct _RtpTransportModifier * t,mblk_t * msg)546 static int ms_dtls_srtp_rtcp_process_on_receive(struct _RtpTransportModifier *t, mblk_t *msg)  {
547 	MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data;
548 
549 	int ret;
550 	size_t msgLength = msgdsize(msg);
551 
552 	// check incoming message length
553 	if (msgLength<RTP_FIXED_HEADER_SIZE) {
554 		return (int)msgLength;
555 	}
556 
557 	/* check if we have an on-going handshake */
558 	if (ctx->rtp_channel_status == DTLS_STATUS_CONTEXT_NOT_READY) {
559 		return (int)msgLength;
560 	}
561 
562 	/* check if it is a DTLS packet and process it */
563 	if (ms_dtls_srtp_process_dtls_packet(msg, ctx, &ret, FALSE) == TRUE){
564 
565 		if ((ret==0) && (ctx->rtcp_channel_status == DTLS_STATUS_HANDSHAKE_ONGOING)) { /* rtcp handshake is over, give the keys to srtp : 128 bits client write - 128 bits server write - 112 bits client salt - 112 server salt */
566 			MSCryptoSuite agreed_srtp_protection_profile = MS_CRYPTO_SUITE_INVALID;
567 
568 			ctx->rtcp_channel_status = DTLS_STATUS_HANDSHAKE_OVER;
569 
570 			/* check the srtp profile get selected during handshake */
571 			agreed_srtp_protection_profile = ms_dtls_srtp_bctbx_protection_profile_to_ms_crypto_suite(bctbx_ssl_get_dtls_srtp_protection_profile(ctx->rtcp_dtls_context->ssl));
572 			if ( agreed_srtp_protection_profile == MS_CRYPTO_SUITE_INVALID) {
573 				ms_error("DTLS RTCP Handshake successful but unable to agree on srtp_profile to use");
574 			} else {
575 				if (ms_dtls_srtp_check_certificate_fingerprint(bctbx_ssl_get_peer_certificate(ctx->rtcp_dtls_context->ssl), (const char *)(ctx->peer_fingerprint)) == 1) {
576 					char dtls_srtp_key_material[128];
577 					size_t dtls_srt_key_material_length = 128;
578 					uint8_t *key = (uint8_t *)ms_malloc0(256);
579 
580 					ms_message("DTLS RTCP Handshake successful and fingerprints match, srtp protection profile %d", agreed_srtp_protection_profile);
581 
582 					ctx->rtcp_time_reference = 0; /* unarm the timer */
583 
584 					ret = bctbx_ssl_get_dtls_srtp_key_material(ctx->rtcp_dtls_context->ssl, dtls_srtp_key_material, &dtls_srt_key_material_length);
585 					if (ret < 0) {
586 						ms_error("DTLS RTCP Handshake : Unable to retrieve DTLS SRTP key material [-0x%x]", -ret);
587 						return 0;
588 					}
589 
590 					if (ctx->role == MSDtlsSrtpRoleIsServer) {
591 						/* reception(client write) key and salt +16bits padding */
592 						memcpy(key, dtls_srtp_key_material, DTLS_SRTP_KEY_LEN);
593 						memcpy(key + DTLS_SRTP_KEY_LEN, dtls_srtp_key_material+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN);
594 						ms_media_stream_sessions_set_srtp_recv_key(ctx->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTCP_STREAM);
595 						/* emission(server write) key and salt +16bits padding */
596 						memcpy(key, dtls_srtp_key_material+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN);
597 						memcpy(key + DTLS_SRTP_KEY_LEN, dtls_srtp_key_material+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN);
598 						ms_media_stream_sessions_set_srtp_send_key(ctx->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTCP_STREAM);
599 					} else if (ctx->role == MSDtlsSrtpRoleIsClient){ /* this enpoint act as DTLS client */
600 						/* emission(client write) key and salt +16bits padding */
601 						memcpy(key, dtls_srtp_key_material, DTLS_SRTP_KEY_LEN);
602 						memcpy(key + DTLS_SRTP_KEY_LEN, dtls_srtp_key_material+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN);
603 						ms_media_stream_sessions_set_srtp_send_key(ctx->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTCP_STREAM);
604 						/* reception(server write) key and salt +16bits padding */
605 						memcpy(key, dtls_srtp_key_material+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN);
606 						memcpy(key + DTLS_SRTP_KEY_LEN, dtls_srtp_key_material+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN);
607 						ms_media_stream_sessions_set_srtp_recv_key(ctx->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, MSSRTP_RTCP_STREAM);
608 					}
609 
610 					ms_free(key);
611 
612 					ms_dtls_srtp_check_channels_status(ctx);
613 				}
614 			}
615 
616 			if (ctx->role != MSDtlsSrtpRoleIsServer) { /* close the connection only if we are client, if we are server, the client may ask again for last packets */
617 			/*FireFox version 43 requires DTLS channel to be kept openned, probably a bug in FireFox  ret = ssl_close_notify( &(ctx->rtcp_dtls_context->ssl) );*/
618 			}
619 		}
620 
621 		return 0;
622 	}
623 	return (int)msgdsize(msg);
624 }
625 
ms_dtls_srtp_rtp_process_on_send(struct _RtpTransportModifier * t,mblk_t * msg)626 static int ms_dtls_srtp_rtp_process_on_send(struct _RtpTransportModifier *t, mblk_t *msg){
627 	return (int)msgdsize(msg);
628 }
ms_dtls_srtp_rtcp_process_on_send(struct _RtpTransportModifier * t,mblk_t * msg)629 static int ms_dtls_srtp_rtcp_process_on_send(struct _RtpTransportModifier *t, mblk_t *msg)  {
630 	return (int)msgdsize(msg);
631 }
632 
633 /**************************************/
634 /**** session management functions ****/
ms_dtls_srtp_transport_modifier_destroy(RtpTransportModifier * tp)635 static void ms_dtls_srtp_transport_modifier_destroy(RtpTransportModifier *tp)  {
636 	ms_free(tp);
637 }
638 
ms_dtls_srtp_transport_modifier_new(MSDtlsSrtpContext * ctx,RtpTransportModifier ** rtpt,RtpTransportModifier ** rtcpt)639 static int ms_dtls_srtp_transport_modifier_new(MSDtlsSrtpContext* ctx, RtpTransportModifier **rtpt, RtpTransportModifier **rtcpt ) {
640 	if (rtpt){
641 		*rtpt=ms_new0(RtpTransportModifier,1);
642 		(*rtpt)->data=ctx; /* back link to get access to the other fields of the OrtoZrtpContext from the RtpTransportModifier structure */
643 		(*rtpt)->t_process_on_send=ms_dtls_srtp_rtp_process_on_send;
644 		(*rtpt)->t_process_on_receive=ms_dtls_srtp_rtp_process_on_receive;
645 		(*rtpt)->t_process_on_schedule=schedule_rtp;
646 		(*rtpt)->t_destroy=ms_dtls_srtp_transport_modifier_destroy;
647 	}
648 	if (rtcpt){
649 		*rtcpt=ms_new0(RtpTransportModifier,1);
650 		(*rtcpt)->data=ctx; /* back link to get access to the other fields of the OrtoZrtpContext from the RtpTransportModifier structure */
651 		(*rtcpt)->t_process_on_send=ms_dtls_srtp_rtcp_process_on_send;
652 		(*rtcpt)->t_process_on_receive=ms_dtls_srtp_rtcp_process_on_receive;
653 		(*rtcpt)->t_process_on_schedule=schedule_rtcp;
654 		(*rtcpt)->t_destroy=ms_dtls_srtp_transport_modifier_destroy;
655 	}
656 	return 0;
657 }
658 
659 
660 
ms_dtls_srtp_set_transport(MSDtlsSrtpContext * userData,RtpSession * s)661 static void ms_dtls_srtp_set_transport(MSDtlsSrtpContext *userData, RtpSession *s)  {
662 	RtpTransport *rtpt=NULL,*rtcpt=NULL;
663 	RtpTransportModifier *rtp_modifier, *rtcp_modifier;
664 
665 	rtp_session_get_transports(s,&rtpt,&rtcpt);
666 
667 	ms_dtls_srtp_transport_modifier_new(userData, &rtp_modifier,&rtcp_modifier);
668 
669 	meta_rtp_transport_append_modifier(rtpt, rtp_modifier);
670 	meta_rtp_transport_append_modifier(rtcpt, rtcp_modifier);
671 
672 	/* save transport modifier into context, needed to inject packets generated by DTLS */
673 	userData->rtp_modifier = rtp_modifier;
674 	userData->rtcp_modifier = rtcp_modifier;
675 }
676 
ms_dtls_srtp_initialise_bctbx_dtls_context(DtlsBcToolBoxContext * dtlsContext,MSDtlsSrtpParams * params,RtpSession * s)677 static int ms_dtls_srtp_initialise_bctbx_dtls_context(DtlsBcToolBoxContext *dtlsContext, MSDtlsSrtpParams *params, RtpSession *s){
678 	int ret;
679 	bctbx_dtls_srtp_profile_t dtls_srtp_protection_profiles[2] = {BCTBX_SRTP_AES128_CM_HMAC_SHA1_80, BCTBX_SRTP_AES128_CM_HMAC_SHA1_32};
680 
681 	/* initialise certificate */
682 	ret = bctbx_x509_certificate_parse( dtlsContext->crt, (const char *) params->pem_certificate, strlen( params->pem_certificate )+1 );
683 	if( ret < 0 ) {
684 		return ret;
685 	}
686 
687 	ret =  bctbx_signing_key_parse( dtlsContext->pkey, (const char *) params->pem_pkey, strlen( params->pem_pkey )+1, NULL, 0 );
688 	if( ret != 0 ) {
689 		return ret;
690 	}
691 
692 	/* configure ssl */
693 	if (params->role == MSDtlsSrtpRoleIsClient) {
694 		bctbx_ssl_config_defaults(dtlsContext->ssl_config, BCTBX_SSL_IS_CLIENT, BCTBX_SSL_TRANSPORT_DATAGRAM);
695 	} else { /* configure it by default as server, nothing is actually performed until we start the channel but this helps to get correct defaults settings */
696 		bctbx_ssl_config_defaults(dtlsContext->ssl_config, BCTBX_SSL_IS_SERVER, BCTBX_SSL_TRANSPORT_DATAGRAM);
697 	}
698 
699 	bctbx_ssl_config_set_dtls_srtp_protection_profiles(  dtlsContext->ssl_config, dtls_srtp_protection_profiles, 2 ); /* TODO: get param from caller to select available profiles */
700 
701 	bctbx_ssl_config_set_rng(dtlsContext->ssl_config, (int (*)(void *, unsigned char *, size_t))bctbx_rng_get, dtlsContext->rng);
702 
703 	/* set certificates */
704 	/* this will force server to send his certificate to client as we need it to compute the fingerprint even if we won't verify it */
705 	bctbx_ssl_config_set_authmode(dtlsContext->ssl_config, BCTBX_SSL_VERIFY_OPTIONAL);
706 	bctbx_ssl_config_set_own_cert( dtlsContext->ssl_config, dtlsContext->crt, dtlsContext->pkey );
707 	/* This is useless as peer would certainly be a self signed certificate and we won't verify it but avoid runtime warnings */
708 	bctbx_ssl_config_set_ca_chain(dtlsContext->ssl_config, dtlsContext->crt);
709 
710 	/* we are not ready yet to actually start the ssl context, this will be done by calling bctbx_ssl_setup when stream starts */
711 	return 0;
712 
713 }
714 
715 /***********************************************/
716 /***** EXPORTED FUNCTIONS                  *****/
717 /***********************************************/
718 /**** Private to mediastreamer2 functions ****/
719 /* header declared in voip/private.h */
ms_dtls_srtp_set_stream_sessions(MSDtlsSrtpContext * dtls_context,MSMediaStreamSessions * stream_sessions)720 void ms_dtls_srtp_set_stream_sessions(MSDtlsSrtpContext *dtls_context, MSMediaStreamSessions *stream_sessions) {
721 	if (dtls_context!=NULL) {
722 		dtls_context->stream_sessions = stream_sessions;
723 	}
724 }
725 
726 /**** Public functions ****/
727 /* header declared in include/mediastreamer2/dtls_srtp.h */
ms_dtls_srtp_available()728 bool_t ms_dtls_srtp_available(){
729 	return ms_srtp_supported()  && bctbx_dtls_srtp_supported();
730 }
731 
ms_dtls_srtp_set_peer_fingerprint(MSDtlsSrtpContext * context,const char * peer_fingerprint)732 void ms_dtls_srtp_set_peer_fingerprint(MSDtlsSrtpContext *context, const char *peer_fingerprint) {
733 	if (context) {
734 		size_t peer_fingerprint_length = strlen(peer_fingerprint)+1; // include the null termination
735 		if (peer_fingerprint_length>sizeof(context->peer_fingerprint)) {
736 			memcpy(context->peer_fingerprint, peer_fingerprint, sizeof(context->peer_fingerprint));
737 			ms_error("DTLS-SRTP received from SDP INVITE a peer fingerprint %d bytes length wich is longer than maximum storage %d bytes", (int)peer_fingerprint_length, (int)sizeof(context->peer_fingerprint));
738 		} else {
739 			memcpy(context->peer_fingerprint, peer_fingerprint, peer_fingerprint_length);
740 		}
741 	}
742 }
743 
ms_dtls_srtp_set_role(MSDtlsSrtpContext * context,MSDtlsSrtpRole role)744 void ms_dtls_srtp_set_role(MSDtlsSrtpContext *context, MSDtlsSrtpRole role) {
745 	if (context) {
746 		ms_mutex_lock(&context->rtp_dtls_context->ssl_context_mutex);
747 		ms_mutex_lock(&context->rtcp_dtls_context->ssl_context_mutex);
748 
749 		/* if role has changed and handshake already setup and going, reset the session */
750 		if (context->role != role && context->rtp_channel_status == DTLS_STATUS_HANDSHAKE_ONGOING ) {
751 			bctbx_ssl_session_reset( context->rtp_dtls_context->ssl );
752 		}
753 		if (context->role != role && context->rtcp_channel_status == DTLS_STATUS_HANDSHAKE_ONGOING ) {
754 			bctbx_ssl_session_reset( context->rtcp_dtls_context->ssl );
755 		}
756 
757 		/* if role is isServer and was Unset, we must complete the server setup */
758 		if (((context->role == MSDtlsSrtpRoleIsClient) || (context->role == MSDtlsSrtpRoleUnset)) && (role == MSDtlsSrtpRoleIsServer)) {
759 			bctbx_ssl_config_set_endpoint(context->rtp_dtls_context->ssl_config, BCTBX_SSL_IS_SERVER);
760 
761 			bctbx_ssl_config_set_endpoint(context->rtcp_dtls_context->ssl_config, BCTBX_SSL_IS_SERVER);
762 		}
763 		ms_message("DTLS set role from [%s] to [%s] for context [%p]"
764 				,context->role==MSDtlsSrtpRoleIsServer?"server":(context->role==MSDtlsSrtpRoleIsClient?"client":"unset role")
765 				,role==MSDtlsSrtpRoleIsServer?"server":(role==MSDtlsSrtpRoleIsClient?"client":"unset role")
766 				,context);
767 		context->role = role;
768 		ms_mutex_unlock(&context->rtp_dtls_context->ssl_context_mutex);
769 		ms_mutex_unlock(&context->rtcp_dtls_context->ssl_context_mutex);
770 
771 	}
772 }
773 
ms_dtls_srtp_context_new(MSMediaStreamSessions * sessions,MSDtlsSrtpParams * params)774 MSDtlsSrtpContext* ms_dtls_srtp_context_new(MSMediaStreamSessions *sessions, MSDtlsSrtpParams *params) {
775 	MSDtlsSrtpContext *userData;
776 	RtpSession *s = sessions->rtp_session;
777 	int ret;
778 
779 	/* Create and init the polar ssl DTLS contexts */
780 	DtlsBcToolBoxContext *rtp_dtls_context = ms_dtls_srtp_bctbx_context_new();
781 	DtlsBcToolBoxContext *rtcp_dtls_context = ms_dtls_srtp_bctbx_context_new();
782 
783 	ms_message("Creating DTLS-SRTP engine on session [%p] as %s", s, params->role==MSDtlsSrtpRoleIsServer?"server":(params->role==MSDtlsSrtpRoleIsClient?"client":"unset role"));
784 
785 	/* create and link user data */
786 	userData=ms_new0(MSDtlsSrtpContext,1);
787 	userData->rtp_dtls_context=rtp_dtls_context;
788 	userData->rtcp_dtls_context=rtcp_dtls_context;
789 	userData->role = params->role;
790 	userData->rtp_time_reference = 0;
791 	userData->rtcp_time_reference = 0;
792 
793 	userData->stream_sessions=sessions;
794 	userData->rtp_channel_status = 0;
795 	userData->rtcp_channel_status = 0;
796 	userData->rtp_incoming_buffer = NULL;
797 	userData->rtcp_incoming_buffer = NULL;
798 	userData->rtp_channel_status = DTLS_STATUS_CONTEXT_NOT_READY;
799 	userData->rtcp_channel_status = DTLS_STATUS_CONTEXT_NOT_READY;
800 	ms_dtls_srtp_set_transport(userData, s);
801 
802 	ret = ms_dtls_srtp_initialise_bctbx_dtls_context(rtp_dtls_context, params, s);
803 	if (ret!=0) {
804 		ms_error("DTLS init error : rtp bctoolbox context init returned -0x%0x on stream session [%p]", -ret, sessions);
805 		return NULL;
806 	}
807 	ret = ms_dtls_srtp_initialise_bctbx_dtls_context(rtcp_dtls_context, params, s);
808 	if (ret!=0) {
809 		ms_error("DTLS init error : rtcp bctoolbox context init returned -0x%0x on stream session [%p]", -ret, sessions);
810 		return NULL;
811 	}
812 
813 	/* set ssl transport functions */
814 	bctbx_ssl_set_io_callbacks( rtp_dtls_context->ssl, userData, ms_dtls_srtp_rtp_sendData, ms_dtls_srtp_rtp_DTLSread);
815 	bctbx_ssl_set_io_callbacks( rtcp_dtls_context->ssl, userData, ms_dtls_srtp_rtcp_sendData, ms_dtls_srtp_rtcp_DTLSread);
816 
817 	userData->rtp_channel_status = DTLS_STATUS_CONTEXT_READY;
818 	userData->rtcp_channel_status = DTLS_STATUS_CONTEXT_READY;
819 
820 	return userData;
821 }
822 
ms_dtls_srtp_start(MSDtlsSrtpContext * context)823 void ms_dtls_srtp_start(MSDtlsSrtpContext* context) {
824 	if (context == NULL ) {
825 		ms_warning("DTLS start but no context\n");
826 		return;
827 	}
828 	ms_message("DTLS start stream on stream sessions [%p], RCTP mux is %s", context->stream_sessions, rtp_session_rtcp_mux_enabled(context->stream_sessions->rtp_session)?"enabled":"disabled");
829 
830 	/* if we are client, start the handshake(send a clientHello) */
831 	if (context->role == MSDtlsSrtpRoleIsClient) {
832 		ms_mutex_lock(&context->rtp_dtls_context->ssl_context_mutex);
833 		bctbx_ssl_config_set_endpoint(context->rtp_dtls_context->ssl_config, BCTBX_SSL_IS_CLIENT);
834 		/* complete ssl setup*/
835 		bctbx_ssl_context_setup(context->rtp_dtls_context->ssl, context->rtp_dtls_context->ssl_config);
836 		/* and start the handshake */
837 		bctbx_ssl_handshake(context->rtp_dtls_context->ssl);
838 		context->rtp_time_reference = get_timeval_in_millis(); /* arm the timer for retransmission */
839 		context->rtp_channel_status = DTLS_STATUS_HANDSHAKE_ONGOING;
840 		ms_mutex_unlock(&context->rtp_dtls_context->ssl_context_mutex);
841 		/* We shall start handshake on RTCP channel too only if RTCP mux is not enabled */
842 		if (!rtp_session_rtcp_mux_enabled(context->stream_sessions->rtp_session)) {
843 			ms_mutex_lock(&context->rtcp_dtls_context->ssl_context_mutex);
844 			bctbx_ssl_config_set_endpoint(context->rtcp_dtls_context->ssl_config, BCTBX_SSL_IS_CLIENT);
845 			/* complete ssl setup*/
846 			bctbx_ssl_context_setup(context->rtcp_dtls_context->ssl, context->rtcp_dtls_context->ssl_config);
847 			/* and start the handshake */
848 			bctbx_ssl_handshake(context->rtcp_dtls_context->ssl);
849 			context->rtcp_time_reference = get_timeval_in_millis(); /* arm the timer for retransmission */
850 			context->rtcp_channel_status = DTLS_STATUS_HANDSHAKE_ONGOING;
851 			ms_mutex_unlock(&context->rtcp_dtls_context->ssl_context_mutex);
852 		}
853 	}
854 
855 	/* if we are server and we didn't started yet the DTLS engine, do it now */
856 	if (context->role == MSDtlsSrtpRoleIsServer) {
857 		if (context->rtp_channel_status == DTLS_STATUS_CONTEXT_READY) {
858 			ms_mutex_lock(&context->rtp_dtls_context->ssl_context_mutex);
859 			bctbx_ssl_config_set_endpoint(context->rtp_dtls_context->ssl_config, BCTBX_SSL_IS_SERVER);
860 			/* complete ssl setup*/
861 			bctbx_ssl_context_setup(context->rtp_dtls_context->ssl, context->rtp_dtls_context->ssl_config);
862 			context->rtp_channel_status = DTLS_STATUS_HANDSHAKE_ONGOING;
863 			ms_mutex_unlock(&context->rtp_dtls_context->ssl_context_mutex);
864 
865 			/* We shall start server on RTCP channel too only if RTCP mux is not enabled */
866 			if (!rtp_session_rtcp_mux_enabled(context->stream_sessions->rtp_session) && context->rtcp_channel_status == DTLS_STATUS_CONTEXT_READY) {
867 				ms_mutex_lock(&context->rtcp_dtls_context->ssl_context_mutex);
868 				bctbx_ssl_config_set_endpoint(context->rtcp_dtls_context->ssl_config, BCTBX_SSL_IS_SERVER);
869 				/* complete ssl setup*/
870 				bctbx_ssl_context_setup(context->rtcp_dtls_context->ssl, context->rtcp_dtls_context->ssl_config);
871 				context->rtcp_channel_status = DTLS_STATUS_HANDSHAKE_ONGOING;
872 				ms_mutex_unlock(&context->rtcp_dtls_context->ssl_context_mutex);
873 			}
874 		}
875 	}
876 
877 }
878 
ms_dtls_srtp_context_destroy(MSDtlsSrtpContext * ctx)879 void ms_dtls_srtp_context_destroy(MSDtlsSrtpContext *ctx) {
880 	/* clean bctoolbox contexts */
881 	ms_dtls_srtp_bctbx_context_free(ctx->rtp_dtls_context);
882 	ms_dtls_srtp_bctbx_context_free(ctx->rtcp_dtls_context);
883 
884 	/* clean incoming buffers */
885 	while (ctx->rtp_incoming_buffer!=NULL) {
886 		DtlsRawPacket *next_packet = ctx->rtp_incoming_buffer->next;
887 		ms_free(ctx->rtp_incoming_buffer->data);
888 		ms_free(ctx->rtp_incoming_buffer);
889 		ctx->rtp_incoming_buffer = next_packet;
890 	}
891 	while (ctx->rtcp_incoming_buffer!=NULL) {
892 		DtlsRawPacket *next_packet = ctx->rtcp_incoming_buffer->next;
893 		ms_free(ctx->rtcp_incoming_buffer->data);
894 		ms_free(ctx->rtcp_incoming_buffer);
895 		ctx->rtcp_incoming_buffer = next_packet;
896 	}
897 
898 	ms_free(ctx);
899 	ms_message("DTLS-SRTP context destroyed");
900 }
901