Improved SRTP support

parent a5f8151f
......@@ -27,6 +27,12 @@
extern "C"{
#endif
enum ortp_srtp_crypto_suite_t {
AES_128_SHA1_80 = 1,
AES_128_SHA1_32,
AES_128_NO_AUTH,
NO_CIPHER_SHA1_80
};
err_status_t ortp_srtp_init(void);
err_status_t ortp_srtp_create(srtp_t *session, const srtp_policy_t *policy);
......@@ -37,6 +43,7 @@ bool_t ortp_srtp_supported(void);
int srtp_transport_new(srtp_t srtp, RtpTransport **rtpt, RtpTransport **rtcpt );
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);
#ifdef __cplusplus
}
#endif
......
......@@ -26,12 +26,14 @@
#ifdef HAVE_SRTP
#include <srtp/srtp.h>
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#include "ortp/srtp.h"
#include "ortp/b64.h"
#define SRTP_PAD_BYTES 64 /*?? */
......@@ -46,7 +48,7 @@ static int srtp_sendto(RtpTransport *t, mblk_t *m, int flags, const struct sock
if (err==err_status_ok){
return sendto(t->session->rtp.socket,m->b_rptr,slen,flags,to,tolen);
}
ortp_error("srtp_protect() failed");
ortp_error("srtp_protect() failed (%d)", err);
return -1;
}
......@@ -56,7 +58,7 @@ static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr
int slen;
err=recvfrom(t->session->rtp.socket,m->b_wptr,m->b_datap->db_lim-m->b_datap->db_base,flags,from,fromlen);
if (err>0){
err_status_t srtp_err;
/* keep NON-RTP data unencrypted */
rtp_header_t *rtp;
if (err>=RTP_FIXED_HEADER_SIZE)
......@@ -69,10 +71,11 @@ static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr
}
slen=err;
if (srtp_unprotect(srtp,m->b_wptr,&slen)==err_status_ok)
srtp_err = srtp_unprotect(srtp,m->b_wptr,&slen);
if (srtp_err==err_status_ok)
return slen;
else {
ortp_error("srtp_unprotect() failed");
ortp_error("srtp_unprotect() failed (%d)", srtp_err);
return -1;
}
}
......@@ -82,13 +85,15 @@ static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr
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;
int slen;
err_status_t srtp_err;
/* enlarge the buffer for srtp to write its data */
msgpullup(m,msgdsize(m)+SRTP_PAD_BYTES);
slen=m->b_wptr-m->b_rptr;
if (srtp_protect_rtcp(srtp,m->b_rptr,&slen)==err_status_ok){
srtp_err=srtp_protect_rtcp(srtp,m->b_rptr,&slen);
if (srtp_err==err_status_ok){
return sendto(t->session->rtcp.socket,m->b_rptr,slen,flags,to,tolen);
}
ortp_error("srtp_protect_rtcp() failed");
ortp_error("srtp_protect_rtcp() failed (%d)", srtp_err);
return -1;
}
......@@ -98,11 +103,13 @@ static int srtcp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr
int slen;
err=recvfrom(t->session->rtcp.socket,m->b_wptr,m->b_datap->db_lim-m->b_datap->db_base,flags,from,fromlen);
if (err>0){
err_status_t srtp_err;
slen=err;
if (srtp_unprotect_rtcp(srtp,m->b_wptr,&slen)==err_status_ok)
srtp_err=srtp_unprotect_rtcp(srtp,m->b_wptr,&slen);
if (srtp_err==err_status_ok)
return slen;
else {
ortp_error("srtp_unprotect_rtcp() failed");
ortp_error("srtp_unprotect_rtcp() failed (%d)", srtp_err);
return -1;
}
}
......@@ -149,6 +156,7 @@ int srtp_transport_new(srtp_t srtp, RtpTransport **rtpt, RtpTransport **rtcpt ){
err_status_t ortp_srtp_init(void)
{
ortp_message("srtp init");
return srtp_init();
}
......@@ -173,6 +181,102 @@ bool_t ortp_srtp_supported(void){
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)
{
uint8_t* key;
int key_size;
err_status_t err;
unsigned b64_key_length = strlen(b64_key);
switch (suite) {
case AES_128_SHA1_32:
crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy->rtp);
// srtp doc says: not adapted to rtcp...
crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy->rtcp);
case AES_128_NO_AUTH:
crypto_policy_set_aes_cm_128_null_auth(&policy->rtp);
// srtp doc says: not adapted to rtcp...
crypto_policy_set_aes_cm_128_null_auth(&policy->rtcp);
case NO_CIPHER_SHA1_80:
crypto_policy_set_null_cipher_hmac_sha1_80(&policy->rtp);
crypto_policy_set_null_cipher_hmac_sha1_80(&policy->rtcp);
case AES_128_SHA1_80:
default:
crypto_policy_set_rtp_default(&policy->rtp);
crypto_policy_set_rtcp_default(&policy->rtcp);
}
key_size = b64_decode(b64_key, b64_key_length, 0, 0);
if (key_size != policy->rtp.cipher_key_len) {
ortp_error("Key size (%d) doesn't match the selected srtp profile (required %d)",
key_size,
policy->rtp.cipher_key_len);
return FALSE;
}
key = (uint8_t*) malloc(key_size);
if (b64_decode((const char*)b64_key, b64_key_length, key, key_size) != key_size) {
ortp_error("Error decoding key");
free(key);
return FALSE;
}
policy->ssrc = ssrc;
policy->key = key;
policy->next = NULL;
err = ortp_srtp_add_stream(srtp, policy);
if (err != err_status_ok) {
ortp_error("Failed to add incoming stream to srtp session (%d)", err);
free(key);
return FALSE;
}
free(key);
return TRUE;
}
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)
{
err_status_t err;
srtp_t session;
err = ortp_srtp_create(&session, NULL);
if (err != err_status_ok) {
ortp_error("Failed to create srtp session (%d)", err);
return NULL;
}
// incoming stream
{
ssrc_t incoming_ssrc;
srtp_policy_t policy;
memset(&policy, 0, sizeof(srtp_policy_t));
incoming_ssrc.type = ssrc_any_inbound;
if (!ortp_init_srtp_policy(session, &policy, suite, incoming_ssrc, rcv_key)) {
ortp_srtp_dealloc(session);
return NULL;
}
}
// outgoing stream
{
ssrc_t outgoing_ssrc;
srtp_policy_t policy;
memset(&policy, 0, sizeof(srtp_policy_t));
outgoing_ssrc.type = ssrc_specific;
outgoing_ssrc.value = ssrc;
if (!ortp_init_srtp_policy(session, &policy, suite, outgoing_ssrc, snd_key)) {
ortp_srtp_dealloc(session);
return NULL;
}
}
return session;
}
#else
int srtp_transport_new(void *i, RtpTransport **rtpt, RtpTransport **rtcpt ){
......@@ -199,5 +303,10 @@ int ortp_srtp_add_stream(void *session, const void *policy)
return -1;
}
srtp_t ortp_srtp_create_configure_session(enum ortp_srtp_crypto_suite_t suite, const char* snd_key, unsigned snd_key_length, uint32_t ssrc, const char* rcv_key, unsigned rcv_key_length)
{
return NULL;
}
#endif
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