summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/README3
-rw-r--r--mk/modules.mk10
-rw-r--r--modules/libsrtp/module.mk11
-rw-r--r--modules/libsrtp/sdes.c45
-rw-r--r--modules/libsrtp/sdes.h22
-rw-r--r--modules/libsrtp/srtp.c467
-rw-r--r--modules/srtp/module.mk2
-rw-r--r--modules/srtp/srtp.c191
8 files changed, 613 insertions, 138 deletions
diff --git a/docs/README b/docs/README
index 30efedc..c6b3fef 100644
--- a/docs/README
+++ b/docs/README
@@ -165,6 +165,7 @@ ice ICE protocol for NAT Traversal
ilbc iLBC audio codec
isac iSAC audio codec
l16 L16 audio codec
+libsrtp Secure RTP encryption using libsrtp
menu Interactive menu
mwi Message Waiting Indication
natbd NAT Behavior Discovery Module
@@ -190,7 +191,7 @@ sndio Audio driver for OpenBSD
speex Speex audio codec
speex_aec Acoustic Echo Cancellation (AEC) using libspeexdsp
speex_pp Audio pre-processor using libspeexdsp
-srtp Secure RTP encryption
+srtp Secure RTP encryption (SDES) using libre SRTP-stack
stdio Standard input/output UI driver
stun Session Traversal Utilities for NAT (STUN) module
syslog Syslog module
diff --git a/mk/modules.mk b/mk/modules.mk
index 339391b..1f74f6a 100644
--- a/mk/modules.mk
+++ b/mk/modules.mk
@@ -23,6 +23,7 @@
# USE_ILBC iLBC audio codec
# USE_ISAC iSAC audio codec
# USE_L16 L16 audio codec
+# USE_LIBSRTP Secure RTP module using libsrtp
# USE_MPG123 Use mpg123
# USE_OPUS Opus audio codec
# USE_OSS OSS audio driver
@@ -34,7 +35,7 @@
# USE_SPEEX Speex audio codec
# USE_SPEEX_AEC Speex Acoustic Echo Canceller
# USE_SPEEX_PP Speex preprocessor
-# USE_SRTP Secure RTP module
+# USE_SRTP Secure RTP module using libre
# USE_STDIO stdio input driver
# USE_SYSLOG Syslog module
# USE_UUID UUID module
@@ -147,7 +148,7 @@ USE_SPEEX_PP := $(shell [ -f $(SYSROOT)/include/speex_preprocess.h ] || \
[ -f $(SYSROOT)/local/include/speex/speex_preprocess.h ] || \
[ -f $(SYSROOT_ALT)/include/speex/speex_preprocess.h ] || \
[ -f $(SYSROOT)/include/speex/speex_preprocess.h ] && echo "yes")
-USE_SRTP := $(shell [ -f $(SYSROOT)/include/srtp/srtp.h ] || \
+USE_LIBSRTP := $(shell [ -f $(SYSROOT)/include/srtp/srtp.h ] || \
[ -f $(SYSROOT_ALT)/include/srtp/srtp.h ] || \
[ -f $(SYSROOT)/local/include/srtp/srtp.h ] && echo "yes")
USE_SYSLOG := $(shell [ -f $(SYSROOT)/include/syslog.h ] || \
@@ -219,6 +220,7 @@ MODULES += $(EXTRA_MODULES)
MODULES += stun turn ice natbd auloop presence
MODULES += menu contact vumeter mwi account natpmp httpd
MODULES += selftest
+MODULES += srtp
ifneq ($(HAVE_PTHREAD),)
MODULES += aubridge
endif
@@ -339,8 +341,8 @@ endif
ifneq ($(USE_SPEEX_PP),)
MODULES += speex_pp
endif
-ifneq ($(USE_SRTP),)
-MODULES += srtp
+ifneq ($(USE_LIBSRTP),)
+MODULES += libsrtp
ifneq ($(USE_DTLS_SRTP),)
MODULES += dtls_srtp
endif
diff --git a/modules/libsrtp/module.mk b/modules/libsrtp/module.mk
new file mode 100644
index 0000000..d24ad60
--- /dev/null
+++ b/modules/libsrtp/module.mk
@@ -0,0 +1,11 @@
+#
+# module.mk
+#
+# Copyright (C) 2010 Creytiv.com
+#
+
+MOD := libsrtp
+$(MOD)_SRCS += srtp.c sdes.c
+$(MOD)_LFLAGS += -lsrtp
+
+include mk/mod.mk
diff --git a/modules/libsrtp/sdes.c b/modules/libsrtp/sdes.c
new file mode 100644
index 0000000..a750432
--- /dev/null
+++ b/modules/libsrtp/sdes.c
@@ -0,0 +1,45 @@
+/**
+ * @file sdes.c SDP Security Descriptions for Media Streams (RFC 4568)
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re.h>
+#include <baresip.h>
+#include "sdes.h"
+
+
+const char sdp_attr_crypto[] = "crypto";
+
+
+int sdes_encode_crypto(struct sdp_media *m, uint32_t tag, const char *suite,
+ const char *key, size_t key_len)
+{
+ return sdp_media_set_lattr(m, true, sdp_attr_crypto, "%u %s inline:%b",
+ tag, suite, key, key_len);
+}
+
+
+/* http://tools.ietf.org/html/rfc4568
+ * a=crypto:<tag> <crypto-suite> <key-params> [<session-params>]
+ */
+int sdes_decode_crypto(struct crypto *c, const char *val)
+{
+ struct pl tag, key_prms;
+ int err;
+
+ err = re_regex(val, str_len(val), "[0-9]+ [^ ]+ [^ ]+[]*[^]*",
+ &tag, &c->suite, &key_prms, NULL, &c->sess_prms);
+ if (err)
+ return err;
+
+ c->tag = pl_u32(&tag);
+
+ c->lifetime = c->mki = pl_null;
+ err = re_regex(key_prms.p, key_prms.l, "[^:]+:[^|]+[|]*[^|]*[|]*[^|]*",
+ &c->key_method, &c->key_info,
+ NULL, &c->lifetime, NULL, &c->mki);
+ if (err)
+ return err;
+
+ return 0;
+}
diff --git a/modules/libsrtp/sdes.h b/modules/libsrtp/sdes.h
new file mode 100644
index 0000000..66cc2f1
--- /dev/null
+++ b/modules/libsrtp/sdes.h
@@ -0,0 +1,22 @@
+/**
+ * @file sdes.h SDP Security Descriptions for Media Streams (RFC 4568) API
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+
+
+struct crypto {
+ uint32_t tag;
+ struct pl suite;
+ struct pl key_method;
+ struct pl key_info;
+ struct pl lifetime; /* optional */
+ struct pl mki; /* optional */
+ struct pl sess_prms; /* optional */
+};
+
+extern const char sdp_attr_crypto[];
+
+int sdes_encode_crypto(struct sdp_media *m, uint32_t tag, const char *suite,
+ const char *key, size_t key_len);
+int sdes_decode_crypto(struct crypto *c, const char *val);
diff --git a/modules/libsrtp/srtp.c b/modules/libsrtp/srtp.c
new file mode 100644
index 0000000..244d7cc
--- /dev/null
+++ b/modules/libsrtp/srtp.c
@@ -0,0 +1,467 @@
+/**
+ * @file modules/srtp/srtp.c Secure Real-time Transport Protocol (RFC 3711)
+ *
+ * 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"
+
+
+struct menc_st {
+ /* one SRTP session per media line */
+ uint8_t key_tx[32]; /* 32 for alignment, only 30 used */
+ uint8_t key_rx[32];
+ srtp_t srtp_tx, srtp_rx;
+ srtp_policy_t policy_tx, policy_rx;
+ bool use_srtp;
+ char *crypto_suite;
+
+ void *rtpsock;
+ void *rtcpsock;
+ struct udp_helper *uh_rtp; /**< UDP helper for RTP encryption */
+ struct udp_helper *uh_rtcp; /**< UDP helper for RTCP encryption */
+ struct sdp_media *sdpm;
+};
+
+
+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 void destructor(void *arg)
+{
+ struct menc_st *st = arg;
+
+ mem_deref(st->sdpm);
+ mem_deref(st->crypto_suite);
+
+ /* note: must be done before freeing socket */
+ mem_deref(st->uh_rtp);
+ mem_deref(st->uh_rtcp);
+ 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);
+}
+
+
+static bool cryptosuite_issupported(const struct pl *suite)
+{
+ if (0 == pl_strcasecmp(suite, aes_cm_128_hmac_sha1_32)) return true;
+ if (0 == pl_strcasecmp(suite, aes_cm_128_hmac_sha1_80)) return true;
+
+ return false;
+}
+
+
+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:
+ *
+ * +----------------+
+ * | 127 < B < 192 -+--> forward to RTP
+ * | |
+ * packet --> | 19 < B < 64 -+--> forward to DTLS
+ * | |
+ * | B < 2 -+--> forward to STUN
+ * +----------------+
+ *
+ */
+static bool is_rtp_or_rtcp(const struct mbuf *mb)
+{
+ uint8_t b;
+
+ if (mbuf_get_left(mb) < 1)
+ return false;
+
+ b = mbuf_buf(mb)[0];
+
+ return 127 < b && b < 192;
+}
+
+
+static bool is_rtcp_packet(const struct mbuf *mb)
+{
+ uint8_t pt;
+
+ if (mbuf_get_left(mb) < 2)
+ return false;
+
+ pt = mbuf_buf(mb)[1] & 0x7f;
+
+ return 64 <= pt && pt <= 95;
+}
+
+
+static int start_srtp(struct menc_st *st, const char *suite)
+{
+ crypto_policy_t policy;
+ err_status_t e;
+
+ 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;
+
+ /* 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;
+
+ /* 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;
+ }
+
+ 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;
+ }
+
+ /* use SRTP for this stream/session */
+ st->use_srtp = true;
+
+ return 0;
+}
+
+
+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;
+ (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);
+ }
+ else {
+ e = srtp_protect(st->srtp_tx, mbuf_buf(mb), &len);
+ }
+
+ 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;
+ return false;
+ }
+
+ mbuf_set_end(mb, mb->pos + len);
+
+ return false; /* continue processing */
+}
+
+
+static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg)
+{
+ struct menc_st *st = arg;
+ err_status_t e;
+ int len;
+ (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);
+ }
+ 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 */
+ }
+
+ mbuf_set_end(mb, mb->pos + len);
+
+ return false; /* continue processing */
+}
+
+
+/* a=crypto:<tag> <crypto-suite> <key-params> [<session-params>] */
+static int sdp_enc(struct menc_st *st, struct sdp_media *m,
+ uint32_t tag, const char *suite)
+{
+ char key[128] = "";
+ size_t olen;
+ int err;
+
+ olen = sizeof(key);
+ err = base64_encode(st->key_tx, SRTP_MASTER_KEY_LEN, key, &olen);
+ if (err)
+ return err;
+
+ return sdes_encode_crypto(m, tag, suite, key, olen);
+}
+
+
+static int start_crypto(struct menc_st *st, const struct pl *key_info)
+{
+ size_t olen;
+ int err;
+
+ /* key-info is BASE64 encoded */
+
+ olen = sizeof(st->key_rx);
+ err = base64_decode(key_info->p, key_info->l, st->key_rx, &olen);
+ if (err)
+ return err;
+
+ if (SRTP_MASTER_KEY_LEN != olen) {
+ warning("srtp: srtp keylen is %u (should be 30)\n", olen);
+ }
+
+ err = start_srtp(st, st->crypto_suite);
+ if (err)
+ return err;
+
+ info("srtp: %s: SRTP is Enabled (cryptosuite=%s)\n",
+ sdp_media_name(st->sdpm), st->crypto_suite);
+
+ return 0;
+}
+
+
+static bool sdp_attr_handler(const char *name, const char *value, void *arg)
+{
+ struct menc_st *st = arg;
+ struct crypto c;
+ (void)name;
+
+ if (sdes_decode_crypto(&c, value))
+ return false;
+
+ if (0 != pl_strcmp(&c.key_method, "inline"))
+ return false;
+
+ if (!cryptosuite_issupported(&c.suite))
+ return false;
+
+ st->crypto_suite = mem_deref(st->crypto_suite);
+ pl_strdup(&st->crypto_suite, &c.suite);
+
+ if (start_crypto(st, &c.key_info))
+ return false;
+
+ sdp_enc(st, st->sdpm, c.tag, st->crypto_suite);
+
+ return true;
+}
+
+
+static int alloc(struct menc_media **stp, struct menc_sess *sess,
+ struct rtp_sock *rtp,
+ int proto, void *rtpsock, void *rtcpsock,
+ struct sdp_media *sdpm)
+{
+ struct menc_st *st;
+ const char *rattr = NULL;
+ int layer = 10; /* above zero */
+ int err = 0;
+ bool mux = (rtpsock == rtcpsock);
+ (void)sess;
+ (void)rtp;
+
+ if (!stp || !sdpm)
+ return EINVAL;
+ if (proto != IPPROTO_UDP)
+ return EPROTONOSUPPORT;
+
+ st = (struct menc_st *)*stp;
+ if (!st) {
+
+ st = mem_zalloc(sizeof(*st), destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->sdpm = mem_ref(sdpm);
+
+ err = sdp_media_set_alt_protos(st->sdpm, 4,
+ "RTP/AVP",
+ "RTP/AVPF",
+ "RTP/SAVP",
+ "RTP/SAVPF");
+ if (err)
+ goto out;
+
+ if (rtpsock) {
+ st->rtpsock = mem_ref(rtpsock);
+ err |= udp_register_helper(&st->uh_rtp, rtpsock,
+ layer, send_handler,
+ recv_handler, st);
+ }
+ if (rtcpsock && !mux) {
+ st->rtcpsock = mem_ref(rtcpsock);
+ err |= udp_register_helper(&st->uh_rtcp, rtcpsock,
+ layer, send_handler,
+ recv_handler, st);
+ }
+ if (err)
+ goto out;
+
+ /* set our preferred crypto-suite */
+ err |= str_dup(&st->crypto_suite, aes_cm_128_hmac_sha1_80);
+ if (err)
+ goto out;
+
+ err = setup_srtp(st);
+ if (err)
+ goto out;
+ }
+
+ /* SDP handling */
+
+ if (sdp_media_rattr(st->sdpm, "crypto")) {
+
+ rattr = sdp_media_rattr_apply(st->sdpm, "crypto",
+ sdp_attr_handler, st);
+ if (!rattr) {
+ warning("srtp: no valid a=crypto attribute from"
+ " remote peer\n");
+ }
+ }
+
+ if (!rattr)
+ err = sdp_enc(st, sdpm, 0, st->crypto_suite);
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *stp = (struct menc_media *)st;
+
+ return err;
+}
+
+
+static struct menc menc_srtp_opt = {
+ LE_INIT, "srtp", "RTP/AVP", NULL, alloc
+};
+
+static struct menc menc_srtp_mand = {
+ LE_INIT, "srtp-mand", "RTP/SAVP", NULL, alloc
+};
+
+static struct menc menc_srtp_mandf = {
+ LE_INIT, "srtp-mandf", "RTP/SAVPF", NULL, alloc
+};
+
+
+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);
+
+ return 0;
+}
+
+
+static int mod_srtp_close(void)
+{
+ menc_unregister(&menc_srtp_mandf);
+ menc_unregister(&menc_srtp_mand);
+ menc_unregister(&menc_srtp_opt);
+
+ crypto_kernel_shutdown();
+
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(libsrtp) = {
+ "libsrtp",
+ "menc",
+ mod_srtp_init,
+ mod_srtp_close
+};
diff --git a/modules/srtp/module.mk b/modules/srtp/module.mk
index ac4a1c7..285f4ed 100644
--- a/modules/srtp/module.mk
+++ b/modules/srtp/module.mk
@@ -6,6 +6,6 @@
MOD := srtp
$(MOD)_SRCS += srtp.c sdes.c
-$(MOD)_LFLAGS += -lsrtp
+$(MOD)_LFLAGS +=
include mk/mod.mk
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;
}