diff options
Diffstat (limited to 'modules/srtp/srtp.c')
-rw-r--r-- | modules/srtp/srtp.c | 191 |
1 files changed, 59 insertions, 132 deletions
diff --git a/modules/srtp/srtp.c b/modules/srtp/srtp.c index 8bda31a..cd8fbf6 100644 --- a/modules/srtp/srtp.c +++ b/modules/srtp/srtp.c @@ -3,21 +3,19 @@ * * Copyright (C) 2010 Creytiv.com */ -#if defined (__GNUC__) && !defined (asm) -#define asm __asm__ /* workaround */ -#endif -#include <srtp/srtp.h> #include <re.h> #include <baresip.h> #include "sdes.h" +#define SRTP_MASTER_KEY_LEN 30 + + struct menc_st { /* one SRTP session per media line */ - uint8_t key_tx[32]; /* 32 for alignment, only 30 used */ + uint8_t key_tx[32]; uint8_t key_rx[32]; - srtp_t srtp_tx, srtp_rx; - srtp_policy_t policy_tx, policy_rx; + struct srtp *srtp_tx, *srtp_rx; bool use_srtp; char *crypto_suite; @@ -32,6 +30,8 @@ struct menc_st { static const char aes_cm_128_hmac_sha1_32[] = "AES_CM_128_HMAC_SHA1_32"; static const char aes_cm_128_hmac_sha1_80[] = "AES_CM_128_HMAC_SHA1_80"; +static const char *preferred_suite = aes_cm_128_hmac_sha1_80; + static void destructor(void *arg) { @@ -46,10 +46,8 @@ static void destructor(void *arg) mem_deref(st->rtpsock); mem_deref(st->rtcpsock); - if (st->srtp_tx) - srtp_dealloc(st->srtp_tx); - if (st->srtp_rx) - srtp_dealloc(st->srtp_rx); + mem_deref(st->srtp_tx); + mem_deref(st->srtp_rx); } @@ -62,26 +60,6 @@ static bool cryptosuite_issupported(const struct pl *suite) } -static int errstatus_print(struct re_printf *pf, err_status_t e) -{ - const char *s; - - switch (e) { - - case err_status_ok: s = "ok"; break; - case err_status_fail: s = "fail"; break; - case err_status_auth_fail: s = "auth_fail"; break; - case err_status_cipher_fail: s = "cipher_fail"; break; - case err_status_replay_fail: s = "replay_fail"; break; - - default: - return re_hprintf(pf, "err=%d", e); - } - - return re_hprintf(pf, "%s", s); -} - - /* * See RFC 5764 figure 3: * @@ -120,49 +98,39 @@ static bool is_rtcp_packet(const struct mbuf *mb) } -static int start_srtp(struct menc_st *st, const char *suite) +static enum srtp_suite resolve_suite(const char *suite) { - crypto_policy_t policy; - err_status_t e; + if (0 == str_casecmp(suite, aes_cm_128_hmac_sha1_32)) + return SRTP_AES_CM_128_HMAC_SHA1_32; + if (0 == str_casecmp(suite, aes_cm_128_hmac_sha1_80)) + return SRTP_AES_CM_128_HMAC_SHA1_80; + + return -1; +} - if (0 == str_casecmp(suite, aes_cm_128_hmac_sha1_32)) { - crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy); - } - else if (0 == str_casecmp(suite, aes_cm_128_hmac_sha1_80)) { - crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy); - } - else { - warning("srtp: unknown SRTP crypto suite (%s)\n", suite); - return ENOENT; - } - /* transmit policy */ - st->policy_tx.rtp = policy; - st->policy_tx.rtcp = policy; - st->policy_tx.ssrc.type = ssrc_any_outbound; - st->policy_tx.key = st->key_tx; - st->policy_tx.next = NULL; +static int start_srtp(struct menc_st *st, const char *suite_name) +{ + enum srtp_suite suite; + int err; - /* receive policy */ - st->policy_rx.rtp = policy; - st->policy_rx.rtcp = policy; - st->policy_rx.ssrc.type = ssrc_any_inbound; - st->policy_rx.key = st->key_rx; - st->policy_rx.next = NULL; + suite = resolve_suite(suite_name); /* allocate and initialize the SRTP session */ - e = srtp_create(&st->srtp_tx, &st->policy_tx); - if (e != err_status_ok) { - warning("srtp: srtp_create TX failed (%H)\n", - errstatus_print, e); - return EPROTO; + if (!st->srtp_tx) { + err = srtp_alloc(&st->srtp_tx, suite, st->key_tx, 30, 0); + if (err) { + warning("srtp: srtp_alloc TX failed (%m)\n", err); + return err; + } } - e = srtp_create(&st->srtp_rx, &st->policy_rx); - if (err_status_ok != e) { - warning("srtp: srtp_create RX failed (%H)\n", - errstatus_print, e); - return EPROTO; + if (!st->srtp_rx) { + err = srtp_alloc(&st->srtp_rx, suite, st->key_rx, 30, 0); + if (err) { + warning("srtp: srtp_alloc RX failed (%m)\n", err); + return err; + } } /* use SRTP for this stream/session */ @@ -172,56 +140,32 @@ static int start_srtp(struct menc_st *st, const char *suite) } -static int setup_srtp(struct menc_st *st) -{ - err_status_t e; - - /* init SRTP */ - e = crypto_get_random(st->key_tx, SRTP_MASTER_KEY_LEN); - if (err_status_ok != e) { - warning("srtp: crypto_get_random() failed (%H)\n", - errstatus_print, e); - return ENOSYS; - } - - return 0; -} - - static bool send_handler(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct menc_st *st = arg; - err_status_t e; - int len; + size_t len = mbuf_get_left(mb); + int lerr = 0; (void)dst; if (!st->use_srtp || !is_rtp_or_rtcp(mb)) return false; - len = (int)mbuf_get_left(mb); - - if (mbuf_get_space(mb) < ((size_t)len + SRTP_MAX_TRAILER_LEN)) { - mbuf_resize(mb, mb->pos + len + SRTP_MAX_TRAILER_LEN); - } - if (is_rtcp_packet(mb)) { - e = srtp_protect_rtcp(st->srtp_tx, mbuf_buf(mb), &len); + lerr = srtcp_encrypt(st->srtp_tx, mb); } else { - e = srtp_protect(st->srtp_tx, mbuf_buf(mb), &len); + lerr = srtp_encrypt(st->srtp_tx, mb); } - if (err_status_ok != e) { - warning("srtp: send: failed to protect %s-packet" - " with %d bytes (%H)\n", - is_rtcp_packet(mb) ? "RTCP" : "RTP", - len, errstatus_print, e); - *err = EPROTO; + if (lerr) { + warning("srtp: failed to encrypt %s-packet" + " with %zu bytes (%m)\n", + is_rtcp_packet(mb) ? "RTCP" : "RTP", + len, lerr); + *err = lerr; return false; } - mbuf_set_end(mb, mb->pos + len); - return false; /* continue processing */ } @@ -229,33 +173,29 @@ static bool send_handler(int *err, struct sa *dst, struct mbuf *mb, void *arg) static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct menc_st *st = arg; - err_status_t e; - int len; + size_t len = mbuf_get_left(mb); + int err = 0; (void)src; if (!st->use_srtp || !is_rtp_or_rtcp(mb)) return false; - len = (int)mbuf_get_left(mb); - if (is_rtcp_packet(mb)) { - e = srtp_unprotect_rtcp(st->srtp_rx, mbuf_buf(mb), &len); + err = srtcp_decrypt(st->srtp_rx, mb); + if (err) { + warning("srtp: failed to decrypt RTCP packet" + " with %zu bytes (%m)\n", len, err); + } } else { - e = srtp_unprotect(st->srtp_rx, mbuf_buf(mb), &len); - } - - if (e != err_status_ok) { - warning("srtp: recv: failed to unprotect %s-packet" - " with %d bytes (%H)\n", - is_rtcp_packet(mb) ? "RTCP" : "RTP", - len, errstatus_print, e); - return true; /* error - drop packet */ + err = srtp_decrypt(st->srtp_rx, mb); + if (err) { + warning("srtp: failed to decrypt RTP packet" + " with %zu bytes (%m)\n", len, err); + } } - mbuf_set_end(mb, mb->pos + len); - - return false; /* continue processing */ + return err ? true : false; } @@ -381,13 +321,11 @@ static int alloc(struct menc_media **stp, struct menc_sess *sess, goto out; /* set our preferred crypto-suite */ - err |= str_dup(&st->crypto_suite, aes_cm_128_hmac_sha1_80); + err |= str_dup(&st->crypto_suite, preferred_suite); if (err) goto out; - err = setup_srtp(st); - if (err) - goto out; + rand_bytes(st->key_tx, SRTP_MASTER_KEY_LEN); } /* SDP handling */ @@ -430,15 +368,6 @@ static struct menc menc_srtp_mandf = { static int mod_srtp_init(void) { - err_status_t err; - - err = srtp_init(); - if (err_status_ok != err) { - warning("srtp: srtp_init() failed (%H)\n", - errstatus_print, err); - return ENOSYS; - } - menc_register(&menc_srtp_opt); menc_register(&menc_srtp_mand); menc_register(&menc_srtp_mandf); @@ -453,8 +382,6 @@ static int mod_srtp_close(void) menc_unregister(&menc_srtp_mand); menc_unregister(&menc_srtp_opt); - crypto_kernel_shutdown(); - return 0; } |