Commit daa314ae authored by Simon Morlat's avatar Simon Morlat

rework SRTP in order to allow reconfiguration of an srtp session.

parent 393857c0
...@@ -249,6 +249,7 @@ if test "${srtp_prefix}" != "none" ; then ...@@ -249,6 +249,7 @@ if test "${srtp_prefix}" != "none" ; then
LIBS=$LIBS_save LIBS=$LIBS_save
fi fi
AC_DEFINE(HAVE_SRTP, 1, [Defined when srtp support is compiled]) AC_DEFINE(HAVE_SRTP, 1, [Defined when srtp support is compiled])
ORTP_DEFS="$ORTP_DEFS -DORTP_HAVE_SRTP"
else else
AC_MSG_NOTICE([Could not find libsrtp headers or lib, cryto transport disabled.]) AC_MSG_NOTICE([Could not find libsrtp headers or lib, cryto transport disabled.])
SRTP_CFLAGS= SRTP_CFLAGS=
...@@ -289,8 +290,9 @@ AM_CONDITIONAL(LIBBZRTP,test x$zrtp != xfalse) ...@@ -289,8 +290,9 @@ AM_CONDITIONAL(LIBBZRTP,test x$zrtp != xfalse)
if test $debug_enabled = "yes"; then if test $debug_enabled = "yes"; then
ORTP_DEFS="$ORTP_DEFS -DORTP_DEBUG_MODE -g" ORTP_DEFS="$ORTP_DEFS -DORTP_DEBUG_MODE"
CFLAGS=`echo $CFLAGS | sed 's/-O.//'` CFLAGS=`echo $CFLAGS | sed 's/-O.//'`
CFLAGS="$CFLAGS -g"
fi fi
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#ifndef ortp_srtp_h #ifndef ortp_srtp_h
#define ortp_srtp_h #define ortp_srtp_h
#ifdef HAVE_SRTP #if defined(HAVE_SRTP) || defined(ORTP_HAVE_SRTP)
#if defined(ANDROID) || defined(WINAPI_FAMILY_PHONE_APP) #if defined(ANDROID) || defined(WINAPI_FAMILY_PHONE_APP)
// Android and Windows phone don't use make install // Android and Windows phone don't use make install
#include <srtp.h> #include <srtp.h>
...@@ -29,14 +29,12 @@ ...@@ -29,14 +29,12 @@
#endif #endif
#else #else
typedef void* srtp_t; typedef void* srtp_t;
typedef int err_status_t; typedef int err_status_t;
typedef int srtp_policy_t; typedef struct srtp_policy srtp_policy_t;
#endif #endif
#include <ortp/rtpsession.h>
/*srtp defines all this stuff*/ /*srtp defines all this stuff*/
#undef PACKAGE_BUGREPORT #undef PACKAGE_BUGREPORT
#undef PACKAGE_NAME #undef PACKAGE_NAME
...@@ -44,6 +42,10 @@ typedef int srtp_policy_t; ...@@ -44,6 +42,10 @@ typedef int srtp_policy_t;
#undef PACKAGE_TARNAME #undef PACKAGE_TARNAME
#undef PACKAGE_VERSION #undef PACKAGE_VERSION
#include <ortp/rtpsession.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C"{ extern "C"{
#endif #endif
...@@ -52,18 +54,21 @@ enum ortp_srtp_crypto_suite_t { ...@@ -52,18 +54,21 @@ enum ortp_srtp_crypto_suite_t {
AES_128_SHA1_80 = 1, AES_128_SHA1_80 = 1,
AES_128_SHA1_32, AES_128_SHA1_32,
AES_128_NO_AUTH, AES_128_NO_AUTH,
NO_CIPHER_SHA1_80 NO_CIPHER_SHA1_80,
AES_256_SHA1_80,
AES_256_SHA1_32
}; };
ORTP_PUBLIC err_status_t ortp_srtp_init(void); ORTP_PUBLIC err_status_t ortp_srtp_init(void);
ORTP_PUBLIC err_status_t ortp_srtp_create(srtp_t *session, const srtp_policy_t *policy); ORTP_PUBLIC err_status_t ortp_srtp_create(srtp_t *session, const srtp_policy_t *policy);
ORTP_PUBLIC err_status_t ortp_srtp_dealloc(srtp_t session); ORTP_PUBLIC err_status_t ortp_srtp_dealloc(srtp_t session);
ORTP_PUBLIC err_status_t ortp_srtp_add_stream(srtp_t session, const srtp_policy_t *policy); ORTP_PUBLIC err_status_t ortp_srtp_add_stream(srtp_t session, const srtp_policy_t *policy);
ORTP_PUBLIC err_status_t ortp_srtp_remove_stream(srtp_t session, uint32_t ssrc);
ORTP_PUBLIC err_status_t ortp_crypto_get_random(uint8_t *tmp, int size); ORTP_PUBLIC err_status_t ortp_crypto_get_random(uint8_t *tmp, int size);
ORTP_PUBLIC bool_t ortp_srtp_supported(void); ORTP_PUBLIC bool_t ortp_srtp_supported(void);
ORTP_PUBLIC int srtp_transport_new(srtp_t srtp, RtpTransport **rtpt, RtpTransport **rtcpt ); ORTP_PUBLIC int srtp_transport_new(srtp_t srtp, RtpTransport **rtpt, RtpTransport **rtcpt );
ORTP_PUBLIC void srtp_transport_destroy(RtpTransport *tp);
ORTP_PUBLIC srtp_t ortp_srtp_create_configure_session(enum ortp_srtp_crypto_suite_t suite, uint32_t ssrc, const char* snd_key, const char* rcv_key); ORTP_PUBLIC srtp_t ortp_srtp_create_configure_session(enum ortp_srtp_crypto_suite_t suite, uint32_t ssrc, const char* snd_key, const char* rcv_key);
ORTP_PUBLIC void ortp_srtp_shutdown(void); ORTP_PUBLIC void ortp_srtp_shutdown(void);
......
...@@ -376,7 +376,7 @@ ORTP_PUBLIC int rtp_session_set_remote_addr(RtpSession *session,const char *addr ...@@ -376,7 +376,7 @@ ORTP_PUBLIC int rtp_session_set_remote_addr(RtpSession *session,const char *addr
a valid socket (potentially connect()ed )to be used by the RtpSession */ a valid socket (potentially connect()ed )to be used by the RtpSession */
ORTP_PUBLIC void rtp_session_set_sockets(RtpSession *session, int rtpfd, int rtcpfd); ORTP_PUBLIC void rtp_session_set_sockets(RtpSession *session, int rtpfd, int rtcpfd);
ORTP_PUBLIC void rtp_session_set_transports(RtpSession *session, RtpTransport *rtptr, RtpTransport *rtcptr); ORTP_PUBLIC void rtp_session_set_transports(RtpSession *session, RtpTransport *rtptr, RtpTransport *rtcptr);
ORTP_PUBLIC void rtp_session_get_transports(RtpSession *session, RtpTransport **rtptr, RtpTransport **rtcptr);
/*those methods are provided for people who wants to send non-RTP messages using the RTP/RTCP sockets */ /*those methods are provided for people who wants to send non-RTP messages using the RTP/RTCP sockets */
ORTP_PUBLIC ortp_socket_t rtp_session_get_rtp_socket(const RtpSession *session); ORTP_PUBLIC ortp_socket_t rtp_session_get_rtp_socket(const RtpSession *session);
ORTP_PUBLIC ortp_socket_t rtp_session_get_rtcp_socket(const RtpSession *session); ORTP_PUBLIC ortp_socket_t rtp_session_get_rtcp_socket(const RtpSession *session);
......
...@@ -4,7 +4,7 @@ exec_prefix=@exec_prefix@ ...@@ -4,7 +4,7 @@ exec_prefix=@exec_prefix@
includedir=@includedir@ includedir=@includedir@
Name: oRTP Name: oRTP
Description: Implement the RFC3550 (RTP) with a easy to use API with high and low level access. Description: Implement the RFC3550 (RTP) with a easy to use API with high and low level access.
Version: @ORTP_PKGCONFIG_VERSION@ Version: @ORTP_PKGCONFIG_VERSION@
Libs: -L@libdir@ -lortp @ORTPDEPS_LIBS@ Libs: -L@libdir@ -lortp @ORTPDEPS_LIBS@
Cflags: -I@includedir@ @ORTPDEPS_CFLAGS@ Cflags: -I@includedir@ @ORTPDEPS_CFLAGS@
...@@ -30,48 +30,86 @@ ...@@ -30,48 +30,86 @@
#undef PACKAGE_VERSION #undef PACKAGE_VERSION
#include "ortp/ortp_srtp.h" #include "ortp/ortp_srtp.h"
#include "rtpsession_priv.h" #include "rtpsession_priv.h"
#ifdef HAVE_SRTP #ifdef HAVE_SRTP
#if defined(ANDROID) || defined(WINAPI_FAMILY_PHONE_APP)
// Android and Windows phone don't use make install
#include <srtp_priv.h>
#else
#include <srtp/srtp_priv.h>
#endif
#include "ortp/b64.h" #include "ortp/b64.h"
#define SRTP_PAD_BYTES (SRTP_MAX_TRAILER_LEN + 4) #define SRTP_PAD_BYTES (SRTP_MAX_TRAILER_LEN + 4)
static int srtp_sendto(RtpTransport *t, mblk_t *m, int flags, const struct sockaddr *to, socklen_t tolen){ static int srtp_sendto(RtpTransport *t, mblk_t *m, int flags, const struct sockaddr *to, socklen_t tolen){
srtp_t srtp=(srtp_t)t->data; srtp_t srtp=(srtp_t)t->data;
int slen; int slen;
err_status_t err; err_status_t err;
rtp_header_t *header=(rtp_header_t*)m->b_rptr;
/* enlarge the buffer for srtp to write its data */ /* enlarge the buffer for srtp to write its data */
slen=msgdsize(m); slen=msgdsize(m);
msgpullup(m,slen+SRTP_PAD_BYTES);
err=srtp_protect(srtp,m->b_rptr,&slen); /*only encrypt real RTP packets*/
if (err==err_status_ok){ if (slen>RTP_FIXED_HEADER_SIZE && header->version==2){
return sendto(t->session->rtp.socket,(void*)m->b_rptr,slen,flags,to,tolen); msgpullup(m,slen+SRTP_PAD_BYTES);
} err=srtp_protect(srtp,m->b_rptr,&slen);
ortp_error("srtp_protect() failed (%d)", err); if (err==err_status_ok){
return sendto(t->session->rtp.socket,(void*)m->b_rptr,slen,flags,to,tolen);
}
ortp_error("srtp_protect() failed (%d)", err);
}else return sendto(t->session->rtp.socket,(void*)m->b_rptr,slen,flags,to,tolen);
return -1; return -1;
} }
static srtp_stream_ctx_t * find_other_ssrc(srtp_t srtp, uint32_t ssrc){
srtp_stream_ctx_t *stream;
for (stream=srtp->stream_list;stream!=NULL;stream=stream->next){
if (stream->ssrc!=ssrc) return stream;
}
return stream;
}
/*
* The ssrc_any_inbound feature of the libsrtp is not working good.
* It cannot be changed dynamically nor removed.
* As a result we prefer not to use it, but instead the recv stream is configured with a dummy SSRC value.
* When the first packet arrives, or when the SSRC changes, then we change the ssrc value inside the srtp stream context,
* so that the stream that was configured with the dummy SSRC value becomes now fully valid.
*/
static void update_recv_stream(RtpSession *session, srtp_t srtp, uint32_t new_ssrc){
uint32_t send_ssrc=rtp_session_get_send_ssrc(session);
srtp_stream_ctx_t *recvstream=find_other_ssrc(srtp,htonl(send_ssrc));
if (recvstream){
recvstream->ssrc=new_ssrc;
}
}
static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){
srtp_t srtp=(srtp_t)t->data; srtp_t srtp=(srtp_t)t->data;
int err; int err;
int slen; int slen;
err=rtp_session_rtp_recv_abstract(t->session->rtp.socket,m,flags,from,fromlen); err=rtp_session_rtp_recv_abstract(t->session->rtp.socket,m,flags,from,fromlen);
if (err>0){ if (err>0){
err_status_t srtp_err; err_status_t srtp_err;
/* keep NON-RTP data unencrypted */ /* keep NON-RTP data unencrypted */
rtp_header_t *rtp; rtp_header_t *rtp=(rtp_header_t*)m->b_wptr;
if (err>=RTP_FIXED_HEADER_SIZE) if (err<RTP_FIXED_HEADER_SIZE || rtp->version!=2 )
{ return err;
rtp = (rtp_header_t*)m->b_wptr;
if (rtp->version!=2)
{
return err;
}
}
slen=err; slen=err;
srtp_err = srtp_unprotect(srtp,m->b_wptr,&slen); srtp_err = srtp_unprotect(srtp,m->b_wptr,&slen);
if (srtp_err==err_status_no_ctx){
update_recv_stream(t->session,srtp,rtp->ssrc);
slen=err;
srtp_err = srtp_unprotect(srtp,m->b_wptr,&slen);
}
if (srtp_err==err_status_ok) if (srtp_err==err_status_ok)
return slen; return slen;
else { else {
...@@ -82,7 +120,7 @@ static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr ...@@ -82,7 +120,7 @@ static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr
return err; return err;
} }
static int srtcp_sendto(RtpTransport *t, mblk_t *m, int flags, const struct sockaddr *to, socklen_t tolen){ static int srtcp_sendto(RtpTransport *t, mblk_t *m, int flags, const struct sockaddr *to, socklen_t tolen){
srtp_t srtp=(srtp_t)t->data; srtp_t srtp=(srtp_t)t->data;
int slen; int slen;
err_status_t srtp_err; err_status_t srtp_err;
...@@ -104,19 +142,21 @@ static int srtcp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr ...@@ -104,19 +142,21 @@ static int srtcp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr
err=rtp_session_rtp_recv_abstract(t->session->rtcp.socket,m,flags,from,fromlen); err=rtp_session_rtp_recv_abstract(t->session->rtcp.socket,m,flags,from,fromlen);
if (err>0){ if (err>0){
err_status_t srtp_err; err_status_t srtp_err;
uint32_t new_ssrc;
/* keep NON-RTP data unencrypted */ /* keep NON-RTP data unencrypted */
rtcp_common_header_t *rtcp; rtcp_common_header_t *rtcp=(rtcp_common_header_t*)m->b_wptr;
if (err>=RTCP_COMMON_HEADER_SIZE) if (err<(sizeof(rtcp_common_header_t)+4) || rtcp->version!=2 )
{ return err;
rtcp = (rtcp_common_header_t*)m->b_wptr;
if (rtcp->version!=2)
{
return err;
}
}
slen=err; slen=err;
srtp_err=srtp_unprotect_rtcp(srtp,m->b_wptr,&slen); srtp_err=srtp_unprotect_rtcp(srtp,m->b_wptr,&slen);
if (srtp_err==err_status_no_ctx){
new_ssrc=*(uint32_t*)(m->b_wptr+sizeof(rtcp_common_header_t));
update_recv_stream(t->session,srtp,new_ssrc);
slen=err;
srtp_err=srtp_unprotect_rtcp(srtp,m->b_wptr,&slen);
}
if (srtp_err==err_status_ok) if (srtp_err==err_status_ok)
return slen; return slen;
else { else {
...@@ -165,6 +205,10 @@ int srtp_transport_new(srtp_t srtp, RtpTransport **rtpt, RtpTransport **rtcpt ){ ...@@ -165,6 +205,10 @@ int srtp_transport_new(srtp_t srtp, RtpTransport **rtpt, RtpTransport **rtcpt ){
return 0; return 0;
} }
void srtp_transport_destroy(RtpTransport *tp){
ortp_free(tp);
}
static int srtp_init_done=0; static int srtp_init_done=0;
err_status_t ortp_srtp_init(void) err_status_t ortp_srtp_init(void)
...@@ -210,11 +254,15 @@ err_status_t ortp_srtp_add_stream(srtp_t session, const srtp_policy_t *policy) ...@@ -210,11 +254,15 @@ err_status_t ortp_srtp_add_stream(srtp_t session, const srtp_policy_t *policy)
return srtp_add_stream(session, policy); return srtp_add_stream(session, policy);
} }
err_status_t ortp_srtp_remove_stream(srtp_t session, uint32_t ssrc){
return srtp_remove_stream(session,ssrc);
}
bool_t ortp_srtp_supported(void){ bool_t ortp_srtp_supported(void){
return TRUE; return TRUE;
} }
static bool_t ortp_init_srtp_policy(srtp_t srtp, srtp_policy_t* policy, enum ortp_srtp_crypto_suite_t suite, ssrc_t ssrc, const char* b64_key) bool_t ortp_init_srtp_policy(srtp_t srtp, srtp_policy_t* policy, enum ortp_srtp_crypto_suite_t suite, ssrc_t ssrc, const char* b64_key)
{ {
uint8_t* key; uint8_t* key;
int key_size; int key_size;
...@@ -237,9 +285,17 @@ static bool_t ortp_init_srtp_policy(srtp_t srtp, srtp_policy_t* policy, enum ort ...@@ -237,9 +285,17 @@ static bool_t ortp_init_srtp_policy(srtp_t srtp, srtp_policy_t* policy, enum ort
crypto_policy_set_null_cipher_hmac_sha1_80(&policy->rtcp); crypto_policy_set_null_cipher_hmac_sha1_80(&policy->rtcp);
break; break;
case AES_128_SHA1_80: /*default mode*/ case AES_128_SHA1_80: /*default mode*/
default: crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy->rtp);
crypto_policy_set_rtp_default(&policy->rtp); crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy->rtcp);
crypto_policy_set_rtcp_default(&policy->rtcp); break;
case AES_256_SHA1_80:
crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy->rtp);
crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy->rtcp);
break;
case AES_256_SHA1_32:
crypto_policy_set_aes_cm_256_hmac_sha1_32(&policy->rtp);
crypto_policy_set_aes_cm_256_hmac_sha1_32(&policy->rtcp);
break;
} }
key_size = b64_decode(b64_key, b64_key_length, 0, 0); key_size = b64_decode(b64_key, b64_key_length, 0, 0);
if (key_size != policy->rtp.cipher_key_len) { if (key_size != policy->rtp.cipher_key_len) {
...@@ -319,6 +375,7 @@ srtp_t ortp_srtp_create_configure_session(enum ortp_srtp_crypto_suite_t suite, u ...@@ -319,6 +375,7 @@ srtp_t ortp_srtp_create_configure_session(enum ortp_srtp_crypto_suite_t suite, u
return session; return session;
} }
#else #else
err_status_t ortp_srtp_init(void) { err_status_t ortp_srtp_init(void) {
...@@ -349,8 +406,11 @@ err_status_t ortp_srtp_dealloc(srtp_t session) ...@@ -349,8 +406,11 @@ err_status_t ortp_srtp_dealloc(srtp_t session)
return -1; return -1;
} }
err_status_t ortp_srtp_add_stream(srtp_t session, const srtp_policy_t *policy) err_status_t ortp_srtp_add_stream(srtp_t session, const srtp_policy_t *policy){
{ return -1;
}
err_status_t ortp_srtp_remove_stream(srtp_t session, uint32_t ssrc){
return -1; return -1;
} }
...@@ -362,5 +422,8 @@ srtp_t ortp_srtp_create_configure_session(enum ortp_srtp_crypto_suite_t suite, u ...@@ -362,5 +422,8 @@ srtp_t ortp_srtp_create_configure_session(enum ortp_srtp_crypto_suite_t suite, u
void ortp_srtp_shutdown(void){ void ortp_srtp_shutdown(void){
} }
void srtp_transport_destroy(RtpTransport *tp){
}
#endif #endif
...@@ -224,13 +224,11 @@ void rtp_session_rtp_parse(RtpSession *session, mblk_t *mp, uint32_t local_str_t ...@@ -224,13 +224,11 @@ void rtp_session_rtp_parse(RtpSession *session, mblk_t *mp, uint32_t local_str_t
freemsg(mp); freemsg(mp);
return; return;
} }
} } else{
else{
/* The SSRC change must not happen if we still receive /* The SSRC change must not happen if we still receive
ssrc from the initial source. */ ssrc from the initial source. */
session->inc_same_ssrc_count=0; session->inc_same_ssrc_count=0;
} }
}else{ }else{
session->ssrc_set=TRUE; session->ssrc_set=TRUE;
session->rcv.ssrc=rtp->ssrc; session->rcv.ssrc=rtp->ssrc;
......
...@@ -838,6 +838,10 @@ void rtp_session_set_transports(RtpSession *session, struct _RtpTransport *rtptr ...@@ -838,6 +838,10 @@ void rtp_session_set_transports(RtpSession *session, struct _RtpTransport *rtptr
else session->flags&=~(RTP_SESSION_USING_TRANSPORT); else session->flags&=~(RTP_SESSION_USING_TRANSPORT);
} }
void rtp_session_get_transports(RtpSession *session, RtpTransport **rtptr, RtpTransport **rtcptr){
if (rtptr) *rtptr=session->rtp.tr;
if (rtcptr) *rtcptr=session->rtcp.tr;
}
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment