dtls_srtp.c 40.4 KB
Newer Older
johan's avatar
johan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2006-2013 Belledonne Communications, Grenoble

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/


#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/dtls_srtp.h"

24
#ifdef _WIN32
johan's avatar
johan committed
25 26 27
#include <malloc.h>
#endif

28
#ifdef HAVE_DTLS
johan's avatar
johan committed
29 30

#include <polarssl/ssl.h>
31 32 33
#include <polarssl/entropy.h>
#include <polarssl/ctr_drbg.h>
#include <polarssl/ssl_cookie.h>
34
#include <polarssl/ssl_cache.h>
35 36 37
#include <polarssl/sha1.h>
#include <polarssl/sha256.h>
#include <polarssl/sha512.h>
johan's avatar
johan committed
38 39 40 41 42 43 44 45




typedef struct _DtlsPolarsslContexts {
	x509_crt crt;
	ssl_context ssl;
	entropy_context entropy;
46
	ctr_drbg_context ctr_drbg;
johan's avatar
johan committed
47
	ssl_cookie_ctx cookie_ctx;
48
	pk_context pkey;
jehan's avatar
jehan committed
49
	ms_mutex_t ssl_context_mutex;
50 51
//	ssl_session saved_session;
//	ssl_cache_context cache;
johan's avatar
johan committed
52 53 54 55 56 57 58 59 60 61 62
} DtlsPolarsslContext;

/**
 * incoming DTLS message are stored in a chain buffer to feed polarssl handshake when needed
 */
typedef struct _DtlsRawPacket {
	unsigned char *data;
	size_t length;
	void *next;
} DtlsRawPacket;

63 64 65 66
/* DTLS only allow use of AES128 so we have 16 bytes key and 14 byte salt in any case */
#define DTLS_SRTP_KEY_LEN 16
#define DTLS_SRTP_SALT_LEN 14

johan's avatar
johan committed
67 68
#define DTLS_STATUS_CONTEXT_NOT_READY 0
#define DTLS_STATUS_CONTEXT_READY 1
johan's avatar
johan committed
69
#define DTLS_STATUS_HANDSHAKE_OVER 2
johan's avatar
johan committed
70 71 72

#define READ_TIMEOUT_MS 1000

jehan's avatar
jehan committed
73
struct _MSDtlsSrtpContext{
74
	MSMediaStreamSessions *stream_sessions;
johan's avatar
johan committed
75 76
	MSDtlsSrtpRole role; /**< can be unset(at init on caller side), client or server */
	char peer_fingerprint[256]; /**< used to store peer fingerprint passed through SDP */
77 78 79 80 81 82 83

	RtpTransportModifier *rtp_modifier;
	RtpTransportModifier *rtcp_modifier;

	DtlsPolarsslContext *rtp_dtls_context; /**< a structure containing all contexts needed by polarssl for RTP channel */
	DtlsPolarsslContext *rtcp_dtls_context; /**< a structure containing all contexts needed by polarssl for RTCP channel */

johan's avatar
johan committed
84 85
	uint8_t rtp_channel_status; /**< channel status : DTLS_STATUS_CONTEXT_NOT_READY, DTLS_STATUS_CONTEXT_READY, DTLS_STATUS_HANDSHAKE_OVER */
	uint8_t rtcp_channel_status; /**< channel status : DTLS_STATUS_CONTEXT_NOT_READY, DTLS_STATUS_CONTEXT_READY, DTLS_STATUS_HANDSHAKE_OVER */
86 87 88 89 90 91

	DtlsRawPacket *rtp_incoming_buffer; /**< buffer of incoming DTLS packet to be read by polarssl callback */
	DtlsRawPacket *rtcp_incoming_buffer; /**< buffer of incoming DTLS packet to be read by polarssl callback */

	uint64_t rtp_time_reference; /**< an epoch in ms, used to manage retransmission when we are client */
	uint64_t rtcp_time_reference; /**< an epoch in ms, used to manage retransmission when we are client */
jehan's avatar
jehan committed
92
};
johan's avatar
johan committed
93

johan's avatar
johan committed
94 95 96 97 98 99
/***********************************************/
/***** LOCAL FUNCTIONS                     *****/
/***********************************************/

/**************************/
/**** Helper functions ****/
100
static ORTP_INLINE uint64_t get_timeval_in_millis(void) {
johan's avatar
johan committed
101 102 103 104 105
	struct timeval t;
	ortp_gettimeofday(&t,NULL);
	return (1000LL*t.tv_sec)+(t.tv_usec/1000LL);
}

106 107 108 109 110 111 112 113 114 115 116 117 118
/**
 * @Brief Compute the certificate fingerprint(hash of DER formated certificate)
 * 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)
 * However, peer may provide a fingerprint generated with another hash function(indicated at the fingerprint header).
 * In case certificate and fingerprint hash function differs, issue a warning and use the fingerprint one
 *
 * @param[in]	certificate		Certificate we shall compute the fingerprint
 * @param[in]	peer_fingerprint	Fingerprint received from peer, check its header to get the hash function used to generate it
 *
 * @return 0 if the fingerprint doesn't match, 1 is they do.
 */
static uint8_t ms_dtls_srtp_check_certificate_fingerprint(const x509_crt *certificate, const char *peer_fingerprint) {
	unsigned char fingerprint[256]; /* maximum length of the fingerprint for sha-512: 8+3*64+1 so we're good with 256 bytes buffer */
johan's avatar
johan committed
119 120 121
	unsigned char buffer[64]; /* buffer is max length of returned hash, which is 64 in case we use sha-512 */
	size_t hash_length = 0;
	char hash_alg_string[8]; /* buffer to store the string description of the algo, longest is SHA-512(7 chars + null termination) */
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
	md_type_t hash_function = POLARSSL_MD_NONE;

	/* get Hash algorithm used from peer fingerprint */
	if (strncasecmp(peer_fingerprint, "sha-1 ", 6) ==0 ) {
		sha1(certificate->raw.p, certificate->raw.len, buffer);
		hash_length = 20;
		memcpy(hash_alg_string, "sha-1", 6);
		hash_function = POLARSSL_MD_SHA1;
	} else if (strncasecmp(peer_fingerprint, "sha-224 ", 8) ==0 ){
		sha256(certificate->raw.p, certificate->raw.len, buffer, 1); /* last argument is a boolean, indicate to output sha-224 and not sha-256 */
		hash_length = 28;
		memcpy(hash_alg_string, "sha-224", 8);
		hash_function = POLARSSL_MD_SHA224;
	} else if (strncasecmp(peer_fingerprint, "sha-256 ", 8) ==0 ){
		sha256(certificate->raw.p, certificate->raw.len, buffer, 0);
		hash_length = 32;
		memcpy(hash_alg_string, "sha-256", 8);
		hash_function = POLARSSL_MD_SHA256;
	} else if (strncasecmp(peer_fingerprint, "sha-384 ", 8) ==0 ){
		sha512(certificate->raw.p, certificate->raw.len, buffer, 1); /* last argument is a boolean, indicate to output sha-384 and not sha-512 */
		hash_length = 48;
		memcpy(hash_alg_string, "sha-384", 8);
		hash_function = POLARSSL_MD_SHA384;
	} else if (strncasecmp(peer_fingerprint, "sha-512 ", 8) ==0 ){
		sha512(certificate->raw.p, certificate->raw.len, buffer, 1); /* last argument is a boolean, indicate to output sha-384 and not sha-512 */
		hash_length = 64;
		memcpy(hash_alg_string, "sha-512", 8);
		hash_function = POLARSSL_MD_SHA512;
	} else { /* we have an unknown hash function: return null */
		ms_error("DTLS-SRTP received invalid peer fingerprint, hash function unknown");
		return 0;
	}
154

155 156 157
	/* check that hash function used match the one used for certificate signature */
	if (hash_function != certificate->sig_md) {
		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");
johan's avatar
johan committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171
	}

	if (hash_length>0) {
		int i;
		int fingerprint_index = strlen(hash_alg_string);
		char prefix=' ';
		sprintf((char *)fingerprint, "%s", hash_alg_string);
		for (i=0; i<hash_length; i++, fingerprint_index+=3) {
			sprintf((char *)(fingerprint+fingerprint_index),"%c%02X", prefix,buffer[i]);
			prefix=':';
		}
		*(fingerprint+fingerprint_index) = '\0';
	}

172 173 174 175 176 177 178
	/* compare fingerprints */
	if (strncasecmp((const char *)fingerprint, peer_fingerprint, strlen((const char *)fingerprint)) == 0) {
		return 1;
	} else {
		ms_error("DTLS Handshake successful but fingerprints differ received : %s computed %s", peer_fingerprint, fingerprint);
		return 0;
	}
johan's avatar
johan committed
179 180
}

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
/**
 * Convert a polarssl defined value for SRTP protection profile to the mediastreamer enumeration of SRTP protection profile
 * @param[in]	dtls_srtp_protection_profile	A DTLS-SRTP protection profile defined by polarssl
 * @return the matching profile defined in mediatream.h
 */
static MSCryptoSuite ms_polarssl_dtls_srtp_protection_profile_to_ms_crypto_suite(enum DTLS_SRTP_protection_profiles dtls_srtp_protection_profile) {
	switch(dtls_srtp_protection_profile) {
		case SRTP_AES128_CM_HMAC_SHA1_80:
			return MS_AES_128_SHA1_80;
		case SRTP_AES128_CM_HMAC_SHA1_32:
			return MS_AES_128_SHA1_32;
		case SRTP_NULL_HMAC_SHA1_80:
			return MS_NO_CIPHER_SHA1_80;
		case SRTP_NULL_HMAC_SHA1_32: /* this profile is defined in DTLS-SRTP rfc but not implemented by libsrtp */
			return MS_CRYPTO_SUITE_INVALID;
		default:
			return MS_CRYPTO_SUITE_INVALID;
johan's avatar
johan committed
198
	}
199
}
johan's avatar
johan committed
200

jehan's avatar
jehan committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
static void schedule_rtp(struct _RtpTransportModifier *t) {
	MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data;
	/* it is not a dtls packet, but manage anyway the retransmission timer */
	if (ctx->role == MSDtlsSrtpRoleIsClient) { /* only if we are client */
		uint64_t current_time = get_timeval_in_millis();
		if (ctx->rtp_time_reference>0) { /* only when retransmission timer is armed */
			if (current_time - ctx->rtp_time_reference > READ_TIMEOUT_MS) {
				ms_message("DTLS repeating rtp ssl_handshake for context [%p]",ctx);
				ms_mutex_lock(&ctx->rtp_dtls_context->ssl_context_mutex);
				ssl_handshake(&(ctx->rtp_dtls_context->ssl));
				ms_mutex_unlock(&ctx->rtp_dtls_context->ssl_context_mutex);
				ctx->rtp_time_reference = get_timeval_in_millis();
			}
		}
	}

}
static void schedule_rtcp(struct _RtpTransportModifier *t) {
	MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data;
	if (ctx->role == MSDtlsSrtpRoleIsClient) { /* only if we are client */
		uint64_t current_time = get_timeval_in_millis();
		if (ctx->rtcp_time_reference>0) { /* only when retransmission timer is armed */
			if (current_time - ctx->rtcp_time_reference > READ_TIMEOUT_MS) {
				ms_message("DTLS repeating rtcp ssl_handshake for context [%p]",ctx);
				ms_mutex_lock(&ctx->rtcp_dtls_context->ssl_context_mutex);
				ssl_handshake(&(ctx->rtcp_dtls_context->ssl));
				ms_mutex_unlock(&ctx->rtcp_dtls_context->ssl_context_mutex);
				ctx->rtcp_time_reference = get_timeval_in_millis();
			}
		}

	}
}
234 235
/**
 * Check if the incoming message is a DTLS packet.
236 237
 * If it is, store it in the context incoming buffer and call the polarssl function wich will process it.
 * This function also manages the client retransmission timer
238
 *
239 240 241
 * @param[in] 		msg	the incoming message
 * @param[in/out]	ctx	the context containing the incoming buffer to store the DTLS packet
 * @param[out]		ret	the value returned by the polarssl function processing the packet(ssl_handshake)
242
 * @param[in]		is_rtp	TRUE if we are dealing with a RTP channel packet, FALSE for RTCP channel
243 244
 * @return TRUE if packet is a DTLS one, false otherwise
 */
245
static bool_t ms_dtls_srtp_process_dtls_packet(mblk_t *msg, MSDtlsSrtpContext *ctx, int *ret, bool_t is_rtp) {
246
	size_t msgLength = msgdsize(msg);
247 248
	uint64_t *time_reference = (is_rtp == TRUE)?&(ctx->rtp_time_reference):&(ctx->rtcp_time_reference);
	ssl_context *ssl = (is_rtp == TRUE)?&(ctx->rtp_dtls_context->ssl):&(ctx->rtcp_dtls_context->ssl);
jehan's avatar
jehan committed
249
	ms_mutex_t *mutex = (is_rtp == TRUE)?&ctx->rtp_dtls_context->ssl_context_mutex:&ctx->rtcp_dtls_context->ssl_context_mutex;
250 251
	uint8_t channel_status = (is_rtp == TRUE)?(ctx->rtp_channel_status):(ctx->rtcp_channel_status);

252
	// check if incoming message length is compatible with potential DTLS message
johan's avatar
johan committed
253
	if (msgLength<RTP_FIXED_HEADER_SIZE) {
254
		return FALSE;
johan's avatar
johan committed
255 256 257 258
	}

	/* check if it is a DTLS packet (first byte B as 19 < B < 64) rfc5764 section 5.1.2 */
	if ((*(msg->b_rptr)>19) && (*(msg->b_rptr)<64)) {
259 260

		DtlsRawPacket *incoming_dtls_packet;
261 262
		RtpSession *rtp_session = ctx->stream_sessions->rtp_session;
		OrtpStream *ortp_stream = is_rtp?&rtp_session->rtp.gs:&rtp_session->rtcp.gs;
263 264
		incoming_dtls_packet = (DtlsRawPacket *)ms_malloc0(sizeof(DtlsRawPacket));
		//DtlsRawPacket *incoming_dtls_packet = (DtlsRawPacket *)ms_malloc0(sizeof(DtlsRawPacket));
johan's avatar
johan committed
265 266 267 268
		incoming_dtls_packet->next=NULL;
		incoming_dtls_packet->data=(unsigned char *)ms_malloc(msgLength);
		incoming_dtls_packet->length=msgLength;
		memcpy(incoming_dtls_packet->data, msg->b_rptr, msgLength);
269

270 271 272 273
		/*required by webrtc in server case when ice is not completed yet*/
		if (!rtp_session->use_connect){
			struct sockaddr *addr = NULL;
			socklen_t addrlen;
274 275
			addr = (struct sockaddr *)&msg->net_addr;
			addrlen = msg->net_addrlen;
276 277 278 279 280 281 282
			if (ortp_stream->socket>0 && rtp_session->symmetric_rtp){
				/* store the sender rtp address to do symmetric DTLS */
				memcpy(&ortp_stream->rem_addr,addr,addrlen);
				ortp_stream->rem_addrlen=addrlen;
			}
		}

johan's avatar
johan committed
283 284
		ms_message("DTLS Receive %s packet len %d sessions: %p rtp session %p ssl state is %x", is_rtp==TRUE?"RTP":"RTCP", (int)msgLength, ctx->stream_sessions, ctx->stream_sessions->rtp_session, ssl->state);

johan's avatar
johan committed
285
		/* store the packet in the incoming buffer */
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
		if (is_rtp == TRUE) {
			if (ctx->rtp_incoming_buffer==NULL) { /* buffer is empty */
				ctx->rtp_incoming_buffer = incoming_dtls_packet;
			} else { /* queue it at the end of current buffer */
				DtlsRawPacket *last_packet = ctx->rtp_incoming_buffer;
				while (last_packet->next != NULL) last_packet = last_packet->next;
				last_packet->next = incoming_dtls_packet;
			}
		} else {
			if (ctx->rtcp_incoming_buffer==NULL) { /* buffer is empty */
				ctx->rtcp_incoming_buffer = incoming_dtls_packet;
			} else { /* queue it at the end of current buffer */
				DtlsRawPacket *last_packet = ctx->rtcp_incoming_buffer;
				while (last_packet->next != NULL) last_packet = last_packet->next;
				last_packet->next = incoming_dtls_packet;
			}
johan's avatar
johan committed
302
		}
303
		
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
		/* while DTLS handshake is on going route DTLS packets to polarssl engine through ssl_handshake() */
		if (ssl->state != SSL_HANDSHAKE_OVER) {
			/* role is unset but we receive a packet: we are caller and shall initialise as server and then process the incoming packet */
			if (ctx->role == MSDtlsSrtpRoleUnset) {
				ms_dtls_srtp_set_role(ctx, MSDtlsSrtpRoleIsServer); /* this call will update role and complete server setup */
			}
			ms_mutex_lock(mutex);
			/* process the packet and store result */
			*ret = ssl_handshake(ssl);

			/* when we are server, we may issue a hello verify, so reset session, keep cookies(transport id) and expect an other Hello from client */
			if (*ret==POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED) {
				ssl_session_reset(ssl);
				ssl_set_client_transport_id(ssl, (const unsigned char *)(&(ctx->stream_sessions->rtp_session->snd.ssrc)), 4);
			}
319

320 321 322 323 324 325 326 327 328 329 330
			/* if we are client, manage the retransmission timer, unless the handshake is already over */
			if (ctx->role == MSDtlsSrtpRoleIsClient && channel_status != DTLS_STATUS_HANDSHAKE_OVER) {
				*time_reference = get_timeval_in_millis();
			}
			ms_mutex_unlock(mutex);
		} else { /* when DTLS handshake is over, route DTLS packets to polarssl engine through ssl_read() */
			/* we need a buffer to store the message read even if we don't use it */
			unsigned char *buf = ms_malloc(msgLength+1);
			ms_mutex_lock(mutex);
			*ret = ssl_read(ssl, buf, msgLength);
			ms_mutex_unlock(mutex);
331
		}
332

333 334
		return TRUE;
	}
335

336 337 338 339
	return FALSE;

}

340 341
static void ms_dtls_srtp_check_channels_status(MSDtlsSrtpContext *ctx) {

johan's avatar
johan committed
342 343
	if (((ctx->rtp_channel_status == DTLS_STATUS_HANDSHAKE_OVER) && (rtp_session_rtcp_mux_enabled(ctx->stream_sessions->rtp_session)))
		|| ((ctx->rtp_channel_status == DTLS_STATUS_HANDSHAKE_OVER) && (ctx->rtcp_channel_status == DTLS_STATUS_HANDSHAKE_OVER))) {
344 345 346 347 348 349
		OrtpEventData *eventData;
		OrtpEvent *ev;
		/* send event */
		ev=ortp_event_new(ORTP_EVENT_DTLS_ENCRYPTION_CHANGED);
		eventData=ortp_event_get_data(ev);
		eventData->info.dtls_stream_encrypted=1;
350
		rtp_session_dispatch_event(ctx->stream_sessions->rtp_session, ev);
johan's avatar
johan committed
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
		ms_message("DTLS Event dispatched to all: secrets are on for this stream");
	} 
}

/********************************************/
/**** polarssl DTLS packet I/O functions ****/

/**
* Send a DTLS packet via RTP.
*
* DTLS calls this method to send a DTLS packet via the RTP session.
*
* @param ctx
*    Pointer to the MSDtlsSrtpContext structure.
* @param data
*    Points to DTLS message to send.
* @param length
*    The length in bytes of the data
* @return
*    length of data sent
*/
static int ms_dtls_srtp_rtp_sendData (void *ctx, const unsigned char *data, size_t length ){
	MSDtlsSrtpContext *context = (MSDtlsSrtpContext *)ctx;
	RtpSession *session = context->stream_sessions->rtp_session;
	RtpTransport *rtpt=NULL;
	mblk_t *msg;
	int ret;

	ms_message("DTLS Send RTP packet len %d sessions: %p rtp session %p", (int)length, context->stream_sessions, context->stream_sessions->rtp_session);

	/* get RTP transport from session */
	rtp_session_get_transports(session,&rtpt,NULL);

	/* generate message from raw data */
385
	msg = rtp_session_create_packet_raw((uint8_t *)data, length);
johan's avatar
johan committed
386

387
	ret = meta_rtp_transport_modifier_inject_packet_to_send(rtpt, context->rtp_modifier, msg , 0);
johan's avatar
johan committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

	freemsg(msg);
	return ret;
}

/**
* Send a DTLS packet via RTCP.
*
* DTLS calls this method to send a DTLS packet via the RTCP session.
*
* @param ctx
*    Pointer to the MSDtlsSrtpContext structure.
* @param data
*    Points to DTLS message to send.
* @param length
*    The length in bytes of the data
* @return
*    length of data sent
*/
static int ms_dtls_srtp_rtcp_sendData (void *ctx, const unsigned char *data, size_t length ){
	MSDtlsSrtpContext *context = (MSDtlsSrtpContext *)ctx;
	RtpSession *session = context->stream_sessions->rtp_session;
	RtpTransport *rtcpt=NULL;
	mblk_t *msg;
	int ret;

	ms_message("DTLS Send RTCP packet len %d sessions: %p rtp session %p", (int)length, context->stream_sessions, context->stream_sessions->rtp_session);

	/* get RTCP transport from session */
	rtp_session_get_transports(session,NULL,&rtcpt);

	/* generate message from raw data */
420
	msg = rtp_session_create_packet_raw((uint8_t *)data, length);
johan's avatar
johan committed
421

422
	ret = meta_rtp_transport_modifier_inject_packet_to_send(rtcpt, context->rtcp_modifier, msg , 0);
johan's avatar
johan committed
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
	freemsg(msg);

	return ret;
}


static int ms_dtls_srtp_rtp_DTLSread (void *ctx, unsigned char *buf, size_t len) {
	MSDtlsSrtpContext *context = (MSDtlsSrtpContext *)ctx;

	/* do we have something in the incoming buffer */
	if (context->rtp_incoming_buffer == NULL) {
		return POLARSSL_ERR_NET_WANT_READ;
	} else { /* read the first packet in the buffer and delete it */
		DtlsRawPacket *next_packet = context->rtp_incoming_buffer->next;
		size_t dataLength = context->rtp_incoming_buffer->length;
		memcpy(buf, context->rtp_incoming_buffer->data, dataLength);
		ms_free(context->rtp_incoming_buffer->data);
		ms_free(context->rtp_incoming_buffer);
		context->rtp_incoming_buffer = next_packet;

		return dataLength;
444 445 446
	}
}

johan's avatar
johan committed
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
static int ms_dtls_srtp_rtcp_DTLSread (void *ctx, unsigned char *buf, size_t len) {
	MSDtlsSrtpContext *context = (MSDtlsSrtpContext *)ctx;

	/* do we have something in the incoming buffer */
	if (context->rtcp_incoming_buffer == NULL) {
		return POLARSSL_ERR_NET_WANT_READ;
	} else { /* read the first packet in the buffer and delete it */
		DtlsRawPacket *next_packet = context->rtcp_incoming_buffer->next;
		size_t dataLength = context->rtcp_incoming_buffer->length;
		memcpy(buf, context->rtcp_incoming_buffer->data, dataLength);
		ms_free(context->rtcp_incoming_buffer->data);
		ms_free(context->rtcp_incoming_buffer);
		context->rtcp_incoming_buffer = next_packet;

		return dataLength;
	}
}


static int ms_dtls_srtp_rtp_DTLSread_timeout (void *ctx, unsigned char *buf, size_t len, uint32_t timeout) {
	return ms_dtls_srtp_rtp_DTLSread(ctx, buf, len); /* ms_dtls_srtp_DTLSread is non blocking */
}

static int ms_dtls_srtp_rtcp_DTLSread_timeout (void *ctx, unsigned char *buf, size_t len, uint32_t timeout) {
	return ms_dtls_srtp_rtcp_DTLSread(ctx, buf, len); /* ms_dtls_srtp_DTLSread is non blocking */
}


/*******************************************************/
/**** Transport Modifier Sender/Receiver functions  ****/

478 479 480 481 482 483 484
static int ms_dtls_srtp_rtp_process_on_receive(struct _RtpTransportModifier *t, mblk_t *msg){
	MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data;

	int ret;
	size_t msgLength = msgdsize(msg);

	/* check if we have an on-going handshake */
485
	if (ctx->rtp_channel_status == DTLS_STATUS_CONTEXT_NOT_READY) {
486 487 488 489 490 491 492 493
		return msgLength;
	}

	// check incoming message length
	if (msgLength<RTP_FIXED_HEADER_SIZE) {
		return msgLength;
	}

494
	/* check if it is a DTLS packet and process it */
495
	if (ms_dtls_srtp_process_dtls_packet(msg, ctx, &ret, TRUE) == TRUE){
496
		
497
		if ((ret==0) && (ctx->rtp_channel_status == DTLS_STATUS_CONTEXT_READY)) { /* handshake is over, give the keys to srtp : 128 bits client write - 128 bits server write - 112 bits client salt - 112 server salt */
498 499
			MSCryptoSuite agreed_srtp_protection_profile = MS_CRYPTO_SUITE_INVALID;

500
			ctx->rtp_channel_status = DTLS_STATUS_HANDSHAKE_OVER;
johan's avatar
johan committed
501

502
			/* check the srtp profile get selected during handshake */
503
			agreed_srtp_protection_profile = ms_polarssl_dtls_srtp_protection_profile_to_ms_crypto_suite(ssl_get_dtls_srtp_protection_profile(&(ctx->rtp_dtls_context->ssl)));
504
			if ( agreed_srtp_protection_profile == MS_CRYPTO_SUITE_INVALID) {
505
				ms_message("DTLS Handshake successful but unable to agree on srtp_profile to use");
johan's avatar
johan committed
506
			} else {
507
				if (ms_dtls_srtp_check_certificate_fingerprint(ssl_get_peer_cert(&(ctx->rtp_dtls_context->ssl)), (const char *)(ctx->peer_fingerprint)) == 1) {
508
					uint8_t *key = (uint8_t *)ms_malloc0(256);
509
					ms_message("DTLS Handshake on RTP channel successful and fingerprints match, srtp protection profile %d", ctx->rtp_dtls_context->ssl.chosen_dtls_srtp_profile);
510

511
					ctx->rtp_time_reference = 0; /* unarm the timer */
512 513 514

					if (ctx->role == MSDtlsSrtpRoleIsServer) {
						/* reception(client write) key and salt +16bits padding */
515 516
						memcpy(key, ctx->rtp_dtls_context->ssl.dtls_srtp_keys, DTLS_SRTP_KEY_LEN);
						memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN);
517
						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);
518
						/* emission(server write) key and salt +16bits padding */
519 520
						memcpy(key, ctx->rtp_dtls_context->ssl.dtls_srtp_keys+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN);
						memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN);
521
						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);
522 523
					} else if (ctx->role == MSDtlsSrtpRoleIsClient){ /* this enpoint act as DTLS client */
						/* emission(client write) key and salt +16bits padding */
524 525
						memcpy(key, ctx->rtp_dtls_context->ssl.dtls_srtp_keys, DTLS_SRTP_KEY_LEN);
						memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN);
526
						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);
527
						/* reception(server write) key and salt +16bits padding */
528 529
						memcpy(key, ctx->rtp_dtls_context->ssl.dtls_srtp_keys+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN);
						memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN);
530
						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);
531 532 533
					}

					ms_free(key);
534

535
					ms_dtls_srtp_check_channels_status(ctx);
536
				}
johan's avatar
johan committed
537
			}
538 539 540 541 542

			if (ctx->role != MSDtlsSrtpRoleIsServer) { /* close the connection only if we are client, if we are server, the client may ask again for last packets */
				ret = ssl_close_notify( &(ctx->rtp_dtls_context->ssl) );
			}

johan's avatar
johan committed
543 544 545 546 547 548 549
		}
		return 0;
	}
	return msgLength;
}

static int ms_dtls_srtp_rtcp_process_on_receive(struct _RtpTransportModifier *t, mblk_t *msg)  {
550 551 552 553 554 555 556 557 558 559
	MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data;

	int ret;
	size_t msgLength = msgdsize(msg);

	// check incoming message length
	if (msgLength<RTP_FIXED_HEADER_SIZE) {
		return msgLength;
	}

560 561 562 563 564
	/* check if we have an on-going handshake */
	if (ctx->rtp_channel_status == DTLS_STATUS_CONTEXT_NOT_READY) {
		return msgLength;
	}

565
	/* check if it is a DTLS packet and process it */
566
	if (ms_dtls_srtp_process_dtls_packet(msg, ctx, &ret, FALSE) == TRUE){
567

568
		if ((ret==0) && (ctx->rtcp_channel_status == DTLS_STATUS_CONTEXT_READY)) { /* rtcp handshake is over, give the keys to srtp : 128 bits client write - 128 bits server write - 112 bits client salt - 112 server salt */
569 570
			uint8_t *key = (uint8_t *)ms_malloc0(256);

571 572
			MSCryptoSuite agreed_srtp_protection_profile = MS_CRYPTO_SUITE_INVALID;

573
			ctx->rtcp_channel_status = DTLS_STATUS_HANDSHAKE_OVER;
574

575
			/* check the srtp profile get selected during handshake */
576
			agreed_srtp_protection_profile = ms_polarssl_dtls_srtp_protection_profile_to_ms_crypto_suite(ssl_get_dtls_srtp_protection_profile(&(ctx->rtcp_dtls_context->ssl)));
577
			if ( agreed_srtp_protection_profile == MS_CRYPTO_SUITE_INVALID) {
578
				ms_error("DTLS RTCP Handshake successful but unable to agree on srtp_profile to use");
579
			} else {
580
				if (ms_dtls_srtp_check_certificate_fingerprint(ssl_get_peer_cert(&(ctx->rtcp_dtls_context->ssl)), (const char *)(ctx->peer_fingerprint)) == 1) {
581

582
					ms_message("DTLS RTCP Handshake successful and fingerprints match, srtp protection profile %d", ctx->rtcp_dtls_context->ssl.chosen_dtls_srtp_profile);
583

584
					ctx->rtcp_time_reference = 0; /* unarm the timer */
585 586

					if (ctx->role == MSDtlsSrtpRoleIsServer) {
587
						/* reception(client write) key and salt +16bits padding */
588 589
						memcpy(key, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys, DTLS_SRTP_KEY_LEN);
						memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN);
590
						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);
591
						/* emission(server write) key and salt +16bits padding */
592 593
						memcpy(key, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN);
						memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN);
594
						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);
595 596
					} else if (ctx->role == MSDtlsSrtpRoleIsClient){ /* this enpoint act as DTLS client */
						/* emission(client write) key and salt +16bits padding */
597 598
						memcpy(key, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys, DTLS_SRTP_KEY_LEN);
						memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN, DTLS_SRTP_SALT_LEN);
599
						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);
600
						/* reception(server write) key and salt +16bits padding */
601 602
						memcpy(key, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+DTLS_SRTP_KEY_LEN, DTLS_SRTP_KEY_LEN);
						memcpy(key + DTLS_SRTP_KEY_LEN, ctx->rtcp_dtls_context->ssl.dtls_srtp_keys+2*DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN, DTLS_SRTP_SALT_LEN);
603
						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);
604 605
					}

606
					ms_free(key);
607

608
					ms_dtls_srtp_check_channels_status(ctx);
609 610
				}
			}
611
			ret = ssl_close_notify( &(ctx->rtcp_dtls_context->ssl) );
612 613
		}

614 615
		return 0;
	} 
johan's avatar
johan committed
616 617 618
	return msgdsize(msg);
}

johan's avatar
johan committed
619 620 621 622 623 624 625 626 627 628 629 630 631 632
static int ms_dtls_srtp_rtp_process_on_send(struct _RtpTransportModifier *t, mblk_t *msg){
	return msgdsize(msg);
}
static int ms_dtls_srtp_rtcp_process_on_send(struct _RtpTransportModifier *t, mblk_t *msg)  {
	return msgdsize(msg);
}

/**************************************/
/**** session management functions ****/
static void ms_dtls_srtp_transport_modifier_destroy(RtpTransportModifier *tp)  {
	ms_free(tp);
}

static int ms_dtls_srtp_transport_modifier_new(MSDtlsSrtpContext* ctx, RtpTransportModifier **rtpt, RtpTransportModifier **rtcpt ) {
johan's avatar
johan committed
633 634 635 636 637
	if (rtpt){
		*rtpt=ms_new0(RtpTransportModifier,1);
		(*rtpt)->data=ctx; /* back link to get access to the other fields of the OrtoZrtpContext from the RtpTransportModifier structure */
		(*rtpt)->t_process_on_send=ms_dtls_srtp_rtp_process_on_send;
		(*rtpt)->t_process_on_receive=ms_dtls_srtp_rtp_process_on_receive;
jehan's avatar
jehan committed
638
		(*rtpt)->t_process_on_schedule=schedule_rtp;
johan's avatar
johan committed
639 640 641 642 643 644 645
		(*rtpt)->t_destroy=ms_dtls_srtp_transport_modifier_destroy;
	}
	if (rtcpt){
		*rtcpt=ms_new0(RtpTransportModifier,1);
		(*rtcpt)->data=ctx; /* back link to get access to the other fields of the OrtoZrtpContext from the RtpTransportModifier structure */
		(*rtcpt)->t_process_on_send=ms_dtls_srtp_rtcp_process_on_send;
		(*rtcpt)->t_process_on_receive=ms_dtls_srtp_rtcp_process_on_receive;
jehan's avatar
jehan committed
646
		(*rtcpt)->t_process_on_schedule=schedule_rtcp;
johan's avatar
johan committed
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
		(*rtcpt)->t_destroy=ms_dtls_srtp_transport_modifier_destroy;
	}
	return 0;
}



static void ms_dtls_srtp_set_transport(MSDtlsSrtpContext *userData, RtpSession *s)  {
	RtpTransport *rtpt=NULL,*rtcpt=NULL;
	RtpTransportModifier *rtp_modifier, *rtcp_modifier;

	rtp_session_get_transports(s,&rtpt,&rtcpt);

	ms_dtls_srtp_transport_modifier_new(userData, &rtp_modifier,&rtcp_modifier);

	meta_rtp_transport_append_modifier(rtpt, rtp_modifier);
	meta_rtp_transport_append_modifier(rtcpt, rtcp_modifier);

	/* save transport modifier into context, needed to inject packets generated by DTLS */
	userData->rtp_modifier = rtp_modifier;
667
	userData->rtcp_modifier = rtcp_modifier;
johan's avatar
johan committed
668 669
}

johan's avatar
johan committed
670
static int ms_dtls_srtp_initialise_polarssl_dtls_context(DtlsPolarsslContext *dtlsContext, MSDtlsSrtpParams *params, RtpSession *s){
johan's avatar
johan committed
671 672 673 674
	int ret;
	enum DTLS_SRTP_protection_profiles dtls_srtp_protection_profiles[2] = {SRTP_AES128_CM_HMAC_SHA1_80, SRTP_AES128_CM_HMAC_SHA1_32};
	
	memset( &(dtlsContext->ssl), 0, sizeof( ssl_context ) );
675
	//memset( &(dtlsContext->saved_session), 0, sizeof( ssl_session ) );
johan's avatar
johan committed
676
	ssl_cookie_init( &(dtlsContext->cookie_ctx) );
677 678
	x509_crt_init( &(dtlsContext->crt) );
	entropy_init( &(dtlsContext->entropy) );
679
	ctr_drbg_init( &(dtlsContext->ctr_drbg), entropy_func, &(dtlsContext->entropy), NULL, 0 );
johan's avatar
johan committed
680 681
	
	/* initialise certificate */
682 683
	ret = x509_crt_parse( &(dtlsContext->crt), (const unsigned char *) params->pem_certificate, strlen( params->pem_certificate ) );
	if( ret < 0 ) {
johan's avatar
johan committed
684
		return ret;
685
	}
johan's avatar
johan committed
686 687
	
	ret =  pk_parse_key( &(dtlsContext->pkey), (const unsigned char *) params->pem_pkey, strlen( params->pem_pkey ), NULL, 0 );
688
	if( ret != 0 ) {
johan's avatar
johan committed
689
		return ret;
690
	}
johan's avatar
johan committed
691 692 693

	/* ssl setup */
	ssl_init(&(dtlsContext->ssl));
694
	if( ret < 0 ) {
johan's avatar
johan committed
695
		return ret;
696
	}
johan's avatar
johan committed
697 698 699 700 701 702 703 704 705 706

	if (params->role == MSDtlsSrtpRoleIsClient) {
		ssl_set_endpoint(&(dtlsContext->ssl), SSL_IS_CLIENT);
	} else if (params->role == MSDtlsSrtpRoleIsServer) {
		ssl_set_endpoint(&(dtlsContext->ssl), SSL_IS_SERVER);
	}
	ssl_set_transport(&(dtlsContext->ssl), SSL_TRANSPORT_DATAGRAM);
	ssl_set_dtls_srtp_protection_profiles(  &(dtlsContext->ssl), dtls_srtp_protection_profiles, 2 ); /* TODO: get param from caller to select available profiles */

	/* set CA chain */
707
	ssl_set_authmode( &(dtlsContext->ssl), SSL_VERIFY_OPTIONAL ); /* this will force server to send his certificate to client as we need it to compute the fingerprint */
johan's avatar
johan committed
708
	ssl_set_rng(  &(dtlsContext->ssl), ctr_drbg_random, &(dtlsContext->ctr_drbg) );
709
	ssl_set_ca_chain( &(dtlsContext->ssl), &(dtlsContext->crt), NULL, NULL );
johan's avatar
johan committed
710 711 712
	ssl_set_own_cert( &(dtlsContext->ssl), &(dtlsContext->crt), &(dtlsContext->pkey) );
	if (params->role == MSDtlsSrtpRoleIsServer) {
		ssl_cookie_setup( &(dtlsContext->cookie_ctx), ctr_drbg_random, &(dtlsContext->ctr_drbg) );
713 714
		ssl_set_dtls_cookies( &(dtlsContext->ssl), ssl_cookie_write, ssl_cookie_check, &(dtlsContext->cookie_ctx) );
		ssl_session_reset( &(dtlsContext->ssl) );
johan's avatar
johan committed
715 716 717
		ssl_set_client_transport_id(&(dtlsContext->ssl), (const unsigned char *)(&(s->snd.ssrc)), 4);
	}

jehan's avatar
jehan committed
718 719
	ms_mutex_init(&dtlsContext->ssl_context_mutex, NULL);

johan's avatar
johan committed
720
	return 0;
721 722 723

}

johan's avatar
johan committed
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740
/***********************************************/
/***** EXPORTED FUNCTIONS                  *****/
/***********************************************/
/**** Private to mediastreamer2 functions ****/
/* header declared in voip/private.h */
void ms_dtls_srtp_set_stream_sessions(MSDtlsSrtpContext *dtls_context, MSMediaStreamSessions *stream_sessions) {
	if (dtls_context!=NULL) {
		dtls_context->stream_sessions = stream_sessions;
	}
}

/**** Public functions ****/
/* header declared in include/mediastreamer2/dtls_srtp.h */
bool_t ms_dtls_srtp_available(){return TRUE;}

void ms_dtls_srtp_set_peer_fingerprint(MSDtlsSrtpContext *context, const char *peer_fingerprint) {
	if (context) {
johan's avatar
johan committed
741 742 743 744 745 746 747
		size_t peer_fingerprint_length = strlen(peer_fingerprint)+1; // include the null termination
		if (peer_fingerprint_length>sizeof(context->peer_fingerprint)) {
			memcpy(context->peer_fingerprint, peer_fingerprint, sizeof(context->peer_fingerprint));
			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));
		} else {
			memcpy(context->peer_fingerprint, peer_fingerprint, peer_fingerprint_length);
		}
johan's avatar
johan committed
748 749 750 751 752
	}
}

void ms_dtls_srtp_set_role(MSDtlsSrtpContext *context, MSDtlsSrtpRole role) {
	if (context) {
jehan's avatar
jehan committed
753 754 755 756 757 758 759 760 761
		ms_mutex_lock(&context->rtp_dtls_context->ssl_context_mutex);
		ms_mutex_lock(&context->rtcp_dtls_context->ssl_context_mutex);

		if (context->role != role) {
			/*role has changed reseting*/
			ssl_session_reset( &(context->rtp_dtls_context->ssl) );
			ssl_session_reset( &(context->rtcp_dtls_context->ssl) );
		}

johan's avatar
johan committed
762
		/* if role is isServer and was Unset, we must complete the server setup */
jehan's avatar
jehan committed
763
		if (((context->role == MSDtlsSrtpRoleIsClient) || (context->role == MSDtlsSrtpRoleUnset)) && (role == MSDtlsSrtpRoleIsServer)) {
johan's avatar
johan committed
764 765 766 767 768 769 770 771 772 773 774 775 776 777
			ssl_set_endpoint(&(context->rtp_dtls_context->ssl), SSL_IS_SERVER);
			ssl_cookie_setup( &(context->rtp_dtls_context->cookie_ctx), ctr_drbg_random, &(context->rtp_dtls_context->ctr_drbg) );
			ssl_set_dtls_cookies( &(context->rtp_dtls_context->ssl), ssl_cookie_write, ssl_cookie_check, &(context->rtp_dtls_context->cookie_ctx) );
			ssl_set_client_transport_id(&(context->rtp_dtls_context->ssl), (const unsigned char *)(&(context->stream_sessions->rtp_session->snd.ssrc)), 4);
			//ssl_cache_init( &(context->rtp_dtls_context->cache) );
			//ssl_set_session_cache( &(context->rtp_dtls_context->ssl), ssl_cache_get, &(context->rtp_dtls_context->cache), ssl_cache_set, &(context->rtp_dtls_context->cache) );

			ssl_set_endpoint(&(context->rtcp_dtls_context->ssl), SSL_IS_SERVER);
			ssl_cookie_setup( &(context->rtcp_dtls_context->cookie_ctx), ctr_drbg_random, &(context->rtcp_dtls_context->ctr_drbg) );
			ssl_set_dtls_cookies( &(context->rtcp_dtls_context->ssl), ssl_cookie_write, ssl_cookie_check, &(context->rtcp_dtls_context->cookie_ctx) );
			ssl_set_client_transport_id(&(context->rtcp_dtls_context->ssl), (const unsigned char *)(&(context->stream_sessions->rtp_session->snd.ssrc)), 4);
			//ssl_cache_init( &(context->rtcp_dtls_context->cache) );
			//ssl_set_session_cache( &(context->rtcp_dtls_context->ssl), ssl_cache_get, &(context->rtcp_dtls_context->cache), ssl_cache_set, &(context->rtcp_dtls_context->cache) );
		}
jehan's avatar
jehan committed
778 779 780 781
		ms_message("DTLS set role from [%s] to [%s] for context [%p]"
				,context->role==MSDtlsSrtpRoleIsServer?"server":(context->role==MSDtlsSrtpRoleIsClient?"client":"unset role")
				,role==MSDtlsSrtpRoleIsServer?"server":(role==MSDtlsSrtpRoleIsClient?"client":"unset role")
				,context);
johan's avatar
johan committed
782
		context->role = role;
jehan's avatar
jehan committed
783 784 785
		ms_mutex_unlock(&context->rtp_dtls_context->ssl_context_mutex);
		ms_mutex_unlock(&context->rtcp_dtls_context->ssl_context_mutex);

johan's avatar
johan committed
786 787 788 789
	}
}

MSDtlsSrtpContext* ms_dtls_srtp_context_new(MSMediaStreamSessions *sessions, MSDtlsSrtpParams *params) {
790
	MSDtlsSrtpContext *userData;
791
	RtpSession *s = sessions->rtp_session;
johan's avatar
johan committed
792
	int ret;
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807

	/* Create and init the polar ssl DTLS contexts */
	DtlsPolarsslContext *rtp_dtls_context = ms_new0(DtlsPolarsslContext,1);
	DtlsPolarsslContext *rtcp_dtls_context = ms_new0(DtlsPolarsslContext,1);

	ms_message("Creating DTLS-SRTP engine on session [%p] as %s", s, params->role==MSDtlsSrtpRoleIsServer?"server":(params->role==MSDtlsSrtpRoleIsClient?"client":"unset role"));

	/* create and link user data */
	userData=ms_new0(MSDtlsSrtpContext,1);
	userData->rtp_dtls_context=rtp_dtls_context;
	userData->rtcp_dtls_context=rtcp_dtls_context;
	userData->role = params->role;
	userData->rtp_time_reference = 0;
	userData->rtcp_time_reference = 0;

808
	userData->stream_sessions=sessions;
809 810 811 812 813 814 815 816
	userData->rtp_channel_status = 0;
	userData->rtcp_channel_status = 0;
	userData->rtp_incoming_buffer = NULL;
	userData->rtcp_incoming_buffer = NULL;
	userData->rtp_channel_status = DTLS_STATUS_CONTEXT_NOT_READY;
	userData->rtcp_channel_status = DTLS_STATUS_CONTEXT_NOT_READY;
	ms_dtls_srtp_set_transport(userData, s);

johan's avatar
johan committed
817 818 819 820 821 822 823 824 825 826
	ret = ms_dtls_srtp_initialise_polarssl_dtls_context(rtp_dtls_context, params, s);
	if (ret!=0) {
		ms_error("DTLS init error : rtp polarssl context init returned -0x%0x on stream session [%p]", -ret, sessions);
		return NULL;
	}
	ret = ms_dtls_srtp_initialise_polarssl_dtls_context(rtcp_dtls_context, params, s);
	if (ret!=0) {
		ms_error("DTLS init error : rtcp polarssl context init returned -0x%0x on stream session [%p]", -ret, sessions);
		return NULL;
	}
827

johan's avatar
johan committed
828
	/* set ssl transport functions */
jehan's avatar
jehan committed
829 830
	ssl_set_bio_timeout( &(rtp_dtls_context->ssl), userData, ms_dtls_srtp_rtp_sendData, ms_dtls_srtp_rtp_DTLSread, ms_dtls_srtp_rtp_DTLSread_timeout, READ_TIMEOUT_MS);
	ssl_set_bio_timeout( &(rtcp_dtls_context->ssl), userData, ms_dtls_srtp_rtcp_sendData, ms_dtls_srtp_rtcp_DTLSread, ms_dtls_srtp_rtcp_DTLSread_timeout, READ_TIMEOUT_MS);
johan's avatar
johan committed
831

832 833
	userData->rtp_channel_status = DTLS_STATUS_CONTEXT_READY;
	userData->rtcp_channel_status = DTLS_STATUS_CONTEXT_READY;
johan's avatar
johan committed
834

835
	return userData;
johan's avatar
johan committed
836 837 838 839 840 841 842
}

void ms_dtls_srtp_start(MSDtlsSrtpContext* context) {
	if (context == NULL ) {
		ms_warning("DTLS start but no context\n");
		return;
	}
johan's avatar
johan committed
843 844
	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");

johan's avatar
johan committed
845 846
	/* if we are client, start the handshake(send a clientHello) */
	if (context->role == MSDtlsSrtpRoleIsClient) {
jehan's avatar
jehan committed
847
		ms_mutex_lock(&context->rtp_dtls_context->ssl_context_mutex);
848 849 850
		ssl_set_endpoint(&(context->rtp_dtls_context->ssl), SSL_IS_CLIENT);
		ssl_handshake(&(context->rtp_dtls_context->ssl));
		context->rtp_time_reference = get_timeval_in_millis(); /* arm the timer for retransmission */
jehan's avatar
jehan committed
851
		ms_mutex_unlock(&context->rtp_dtls_context->ssl_context_mutex);
johan's avatar
johan committed
852 853 854 855 856 857 858 859
		/* We shall start handshake on RTCP channel too only if RTCP mux is not enabled */
		if (!rtp_session_rtcp_mux_enabled(context->stream_sessions->rtp_session)) {
			ms_mutex_lock(&context->rtcp_dtls_context->ssl_context_mutex);
			ssl_set_endpoint(&(context->rtcp_dtls_context->ssl), SSL_IS_CLIENT);
			ssl_handshake(&(context->rtcp_dtls_context->ssl));
			context->rtcp_time_reference = get_timeval_in_millis(); /* arm the timer for retransmission */
			ms_mutex_unlock(&context->rtcp_dtls_context->ssl_context_mutex);
		}
johan's avatar
johan committed
860 861 862 863 864
	}

}

void ms_dtls_srtp_context_destroy(MSDtlsSrtpContext *ctx) {
johan's avatar
johan committed
865 866 867 868 869 870 871 872
	/* clean polarssl contexts */
	if (ctx->rtp_dtls_context) {
		x509_crt_free( &(ctx->rtp_dtls_context->crt) );
		ssl_free( &(ctx->rtp_dtls_context->ssl) );
		ctr_drbg_free( &(ctx->rtp_dtls_context->ctr_drbg) );
		entropy_free( &(ctx->rtp_dtls_context->entropy) );
		pk_free( &(ctx->rtp_dtls_context->pkey) );
		ssl_cookie_free( &(ctx->rtp_dtls_context->cookie_ctx) );
jehan's avatar
jehan committed
873
		ms_mutex_destroy(&ctx->rtp_dtls_context->ssl_context_mutex);
johan's avatar
johan committed
874 875 876 877 878 879 880 881 882
		ms_free(ctx->rtp_dtls_context);
	}
	if (ctx->rtcp_dtls_context) {
		x509_crt_free( &(ctx->rtcp_dtls_context->crt) );
		ssl_free( &(ctx->rtcp_dtls_context->ssl) );
		ctr_drbg_free( &(ctx->rtcp_dtls_context->ctr_drbg) );
		entropy_free( &(ctx->rtcp_dtls_context->entropy) );
		pk_free( &(ctx->rtcp_dtls_context->pkey) );
		ssl_cookie_free( &(ctx->rtcp_dtls_context->cookie_ctx) );
jehan's avatar
jehan committed
883
		ms_mutex_destroy(&ctx->rtcp_dtls_context->ssl_context_mutex);
johan's avatar
johan committed
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
		ms_free(ctx->rtcp_dtls_context);
	}
	/* clean incoming buffers */
	while (ctx->rtp_incoming_buffer!=NULL) {
		DtlsRawPacket *next_packet = ctx->rtp_incoming_buffer->next;
		ms_free(ctx->rtp_incoming_buffer->data);
		ms_free(ctx->rtp_incoming_buffer);
		ctx->rtp_incoming_buffer = next_packet;
	}
	while (ctx->rtcp_incoming_buffer!=NULL) {
		DtlsRawPacket *next_packet = ctx->rtcp_incoming_buffer->next;
		ms_free(ctx->rtcp_incoming_buffer->data);
		ms_free(ctx->rtcp_incoming_buffer);
		ctx->rtcp_incoming_buffer = next_packet;
	}

	ms_free(ctx);
johan's avatar
johan committed
901 902 903
	ms_message("DTLS-SRTP context destroyed");
}

904
#else /* HAVE_DTLS */
johan's avatar
johan committed
905

johan's avatar
johan committed
906
bool_t ms_dtls_srtp_available(){return FALSE;}
johan's avatar
johan committed
907

908 909 910 911
MSDtlsSrtpContext* ms_dtls_srtp_context_new(MSMediaStreamSessions *sessions, MSDtlsSrtpParams *params) {
	return NULL;
}

johan's avatar
johan committed
912 913 914 915 916 917
void ms_dtls_srtp_start(MSDtlsSrtpContext* context) {
}

void ms_dtls_srtp_context_destroy(MSDtlsSrtpContext *ctx) {
}

918 919 920 921 922 923 924 925
void ms_dtls_srtp_set_role(MSDtlsSrtpContext *context, MSDtlsSrtpRole role) {
}

void ms_dtls_srtp_set_peer_fingerprint(MSDtlsSrtpContext *context, const char *peer_fingerprint) {
}

void ms_dtls_srtp_set_stream_sessions(MSDtlsSrtpContext *dtls_context, MSMediaStreamSessions *stream_sessions) {
	return;
johan's avatar
johan committed
926 927
}

928
#endif /* HAVE_DTLS */