[svn-commits] branch oej/securertp - r7892 in /team/oej/securertp: ./ channels/ include/ast...

svn-commits at lists.digium.com svn-commits at lists.digium.com
Mon Jan 9 10:25:25 CST 2006


Author: oej
Date: Mon Jan  9 10:25:20 2006
New Revision: 7892

URL: http://svn.digium.com/view/asterisk?rev=7892&view=rev
Log:
Integrating Mikael Magnusson's secure RTP patch with a few tiny changes

Modified:
    team/oej/securertp/channels/chan_sip.c
    team/oej/securertp/include/asterisk/aes.h
    team/oej/securertp/include/asterisk/rtp.h
    team/oej/securertp/res/Makefile
    team/oej/securertp/rtp.c

Modified: team/oej/securertp/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/securertp/channels/chan_sip.c?rev=7892&r1=7891&r2=7892&view=diff
==============================================================================
--- team/oej/securertp/channels/chan_sip.c (original)
+++ team/oej/securertp/channels/chan_sip.c Mon Jan  9 10:25:20 2006
@@ -109,6 +109,18 @@
 #define DEFAULT_MAX_EXPIRY	3600
 #define DEFAULT_REGISTRATION_TIMEOUT	20
 #define DEFAULT_MAX_FORWARDS	"70"
+
+#define SRTP_MASTER_LEN 30
+#define SRTP_MASTERKEY_LEN 16
+#define SRTP_MASTERSALT_LEN (SRTP_MASTER_LEN - SRTP_MASTERKEY_LEN)
+#define SRTP_MASTER_LEN64 ((SRTP_MASTER_LEN * 8 + 5) / 6 + 1)
+
+/*! \brief structure for secure RTP audio */
+struct sip_srtp {
+	char *a_crypto;
+	unsigned char local_key[SRTP_MASTER_LEN];
+	char local_key64[SRTP_MASTER_LEN64];
+};
 
 /* guard limit must be larger than guard secs */
 /* guard min must be < 1000, and should be >= 250 */
@@ -704,6 +716,7 @@
 	struct ast_variable *chanvars;		/*!< Channel variables to set for call */
 	struct sip_pvt *next;			/*!< Next call in chain */
 	struct sip_invite_param *options;	/*!< Options for INVITE */
+	struct sip_srtp *srtp;			/*!< Structure for Secure RTP session data */
 } *iflist = NULL;
 
 #define FLAG_RESPONSE (1 << 0)
@@ -1993,6 +2006,235 @@
 }
 
 
+/*
+ * SRTP sdescriptions
+ * Specified in: draft-ietf-mmusic-sdescriptions-12.txt
+ */
+
+static struct sip_srtp *sip_srtp_alloc(void)
+{
+	struct sip_srtp *srtp = malloc(sizeof(*srtp));
+
+	if (srtp)
+		memset(srtp, 0, sizeof(*srtp));
+	else
+		ast_log(LOG_ERROR, "Out of memory, can't allocate srtp structure\n");
+
+	return srtp;
+}
+
+static void sip_srtp_destroy(struct sip_srtp *srtp)
+{
+	free(srtp->a_crypto);
+	srtp->a_crypto = NULL;
+}
+
+
+static int setup_crypto(struct sip_pvt *p)
+{
+	if (!ast_srtp_is_registered()) {
+		ast_log(LOG_ERROR, "No SRTP module loaded, can't setup SRTP session.\n");
+		return -1;
+	}
+
+	p->srtp = sip_srtp_alloc();	/* Allocate SRTP data structure */
+	if (!p->srtp)
+		return -1;
+
+	if (ast_srtp_get_random(p->srtp->local_key, sizeof(p->srtp->local_key)) < 0) {
+		sip_srtp_destroy(p->srtp);
+		p->srtp = NULL;
+		return -1;
+	}
+
+	ast_base64encode(p->srtp->local_key64, p->srtp->local_key,
+			 SRTP_MASTER_LEN, sizeof(p->srtp->local_key64));
+	return 0;
+}
+
+static int set_crypto_policy(struct ast_srtp_policy *policy,
+			     int suite_val, const unsigned char *master_key,
+			     unsigned long ssrc, int inbound)
+{
+	const unsigned char *master_salt = NULL;
+
+	master_salt = master_key + SRTP_MASTERKEY_LEN;
+	if (ast_srtp_policy_set_master_key(policy,
+					   master_key, SRTP_MASTERKEY_LEN,
+					   master_salt, SRTP_MASTERSALT_LEN) < 0)
+		return -1;
+
+
+	if (ast_srtp_policy_set_suite(policy, suite_val)) {
+		ast_log(LOG_WARNING, "Could not set remote SRTP suite\n");
+		return -1;
+	}
+
+	ast_srtp_policy_set_ssrc(policy, ssrc, inbound);
+
+	return 0;
+}
+
+static int activate_crypto(struct sip_pvt *p, int suite_val,
+			   unsigned char *remote_key)
+{
+	struct ast_srtp_policy *local_policy = NULL;
+	struct ast_srtp_policy *remote_policy = NULL;
+	int res = -1;
+	struct sip_srtp *srtp = p->srtp;
+
+	if (!srtp)
+		return -1;
+
+	local_policy = ast_srtp_policy_alloc();
+	if (!local_policy)
+		goto err;
+
+	remote_policy = ast_srtp_policy_alloc();
+	if (!remote_policy) {
+		goto err;
+	}
+
+	if (set_crypto_policy(local_policy, suite_val, srtp->local_key,
+			      ast_rtp_get_ssrc(p->rtp), 0) < 0)
+		goto err;
+	
+	if (set_crypto_policy(remote_policy, suite_val, remote_key, 0, 1) < 0)
+		goto err;
+
+	if (ast_rtp_add_srtp_policy(p->rtp, local_policy)) {
+		ast_log(LOG_WARNING, "Could not set local SRTP policy\n");
+		goto err;
+	}
+
+	if (ast_rtp_add_srtp_policy(p->rtp, remote_policy)) {
+		ast_log(LOG_WARNING, "Could not set remote SRTP policy\n");
+		goto err;
+	}
+
+
+	if (option_debug > 1)
+		ast_log(LOG_DEBUG, "SRTP policy activated\n");
+	res = 0;
+
+err:
+	if (local_policy)
+		ast_srtp_policy_destroy(local_policy);
+
+	if (remote_policy)
+		ast_srtp_policy_destroy(remote_policy);
+	return res;
+}
+
+static int process_crypto(struct sip_pvt *p, const char *attr)
+{
+	char *str = NULL;
+	char *name = NULL;
+	char *tag = NULL;
+	char *suite = NULL;
+	char *key_params = NULL;
+	char *key_param = NULL;
+	char *session_params = NULL;
+	char *key_salt = NULL;
+	char *lifetime = NULL;
+	int found = 0;
+	int attr_len = strlen(attr);
+	int key_len = 0;
+	unsigned char remote_key[SRTP_MASTER_LEN];
+	int suite_val = 0;
+	struct sip_srtp *srtp = p->srtp;
+
+	if (!ast_srtp_is_registered())
+		return -1;
+
+	/* Crypto already accepted */
+	if (srtp && srtp->a_crypto)
+		return -1;
+
+	str = ast_strdupa(attr);
+
+	name = strsep(&str, ":");
+	tag = strsep(&str, " ");
+	suite = strsep(&str, " ");
+	key_params = strsep(&str, " ");
+	session_params = strsep(&str, " ");
+
+	if (!tag || !suite) {
+		ast_log(LOG_WARNING, "Unrecognized a=%s", attr);
+		return -1;
+	}
+
+	if (session_params) {
+		ast_log(LOG_WARNING, "Unsupported crypto parameters: %s",
+			session_params);
+		return -1;
+	}
+
+	if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80")) {
+		suite_val = AST_AES_CM_128_HMAC_SHA1_80;
+	} else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) {
+		suite_val = AST_AES_CM_128_HMAC_SHA1_32;
+	} else {
+		ast_log(LOG_WARNING, "Unsupported crypto suite: %s",
+			suite);
+		return -1;
+	}
+
+	while ((key_param = strsep(&key_params, ";"))) {
+		char *method = NULL;
+		char *info = NULL;
+
+		method = strsep(&key_param, ":");
+		info = strsep(&key_param, ";");
+
+		if (!strcmp(method, "inline")) {
+			key_salt = strsep(&info, "|");
+			lifetime = strsep(&info, "|");
+
+			if (lifetime) {
+				ast_log(LOG_NOTICE, "Crypto life time unsupported: %s\n",
+					attr);
+				continue;
+			}
+
+/* 			if (info || strncmp(lifetime, "2^", 2)) { */
+/* 				ast_log(LOG_NOTICE, "MKI unsupported: %s\n", */
+/* 					attr); */
+/* 				continue; */
+/* 			} */
+
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		ast_log(LOG_NOTICE, "SRTP crypto offer not acceptable\n");
+		return -1;
+	}
+
+	if (!srtp) {
+		setup_crypto(p);
+		srtp = p->srtp;
+	}
+
+	key_len = ast_base64decode(remote_key, key_salt, sizeof(remote_key));
+	if (key_len != SRTP_MASTER_LEN) {
+		ast_log(LOG_WARNING, "SRTP sdescriptions key %d != %d\n",
+			key_len, SRTP_MASTER_LEN);
+		return -1;
+	}
+
+	if (activate_crypto(p, suite_val, remote_key) < 0)
+		return -1;
+
+	srtp->a_crypto = malloc(attr_len+11);
+	snprintf(srtp->a_crypto, attr_len+10,
+		 "a=crypto:%s %s inline:%s\r\n",
+		 tag, suite, srtp->local_key64);
+
+	return 0;
+}
 
 
 /*! \brief  sip_call: Initiate SIP call from PBX 
@@ -2031,6 +2273,18 @@
 		} else if (!p->options->addsipheaders && !strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) {
 			/* Check whether there is a variable with a name starting with SIPADDHEADER */
 			p->options->addsipheaders = 1;
+		} else if (!strncasecmp(ast_var_name(current), "SIP_SRTP_SDES", strlen("SIP_SRTP_SDES"))) {
+			if (!ast_srtp_is_registered()) {
+				ast_log(LOG_WARNING, "SIP_SRTP_SDES set but SRTP is not available\n");
+				return -1;
+			}
+
+			if (!p->srtp) {
+				if (setup_crypto(p) < 0) {
+					ast_log(LOG_WARNING, "SIP SRTP sdes setup failed\n");
+					return -1;
+				}
+			}
 		}
 
 		
@@ -2176,6 +2430,10 @@
 	if (p->chanvars) {
 		ast_variables_destroy(p->chanvars);
 		p->chanvars = NULL;
+	}
+	if (p->srtp) {
+		sip_srtp_destroy(p->srtp);
+		p->srtp = NULL;
 	}
 	ast_mutex_destroy(&p->lock);
 
@@ -3091,6 +3349,7 @@
 	snprintf(tagbuf, len, "as%08x", thread_safe_rand());
 }
 
+
 /*! \brief  sip_alloc: Allocate SIP_PVT structure and set defaults ---*/
 static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
 				 int useglobal_nat, const int intended_method)
@@ -3484,6 +3743,7 @@
 	int x,y;
 	int debug=sip_debug_test_pvt(p);
 	struct ast_channel *bridgepeer = NULL;
+	int secure_audio = 0;
 
 	if (!p->rtp) {
 		ast_log(LOG_ERROR, "Got SDP but have no RTP session allocated.\n");
@@ -3519,9 +3779,24 @@
 	sdpLineNum_iterator_init(&iterator);
 	ast_set_flag(p, SIP_NOVIDEO);	
 	while ((m = get_sdp_iterate(&iterator, req, "m"))[0] != '\0') {
+		char protocol[5] = "";
 		int found = 0;
-		if ((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &y, &len) == 2) ||
-		    (sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1)) {
+
+		len = -1;
+		if ((sscanf(m, "audio %d/%d RTP/%4s %n", &x, &y, protocol, &len) == 3) ||
+		    (sscanf(m, "audio %d RTP/%4s %n", &x, protocol, &len) == 2)) {
+			if (!strcmp(protocol, "SAVP"))
+				secure_audio = 1;
+			else if (strcmp(protocol, "AVP")) {
+				ast_log(LOG_WARNING, "Unknown SDP media protocol in offer: %s\n", protocol);
+				continue;
+			}
+
+			if (len < 0) {
+				ast_log(LOG_WARNING, "Unknown SDP media type in offer: %s\n", m);
+				continue;
+			}
+
 			found = 1;
 			portno = x;
 			/* Scan through the RTP payload types specified in a "m=" line: */
@@ -3541,7 +3816,13 @@
 		if (p->vrtp)
 			ast_rtp_pt_clear(p->vrtp);  /* Must be cleared in case no m=video line exists */
 
+		len= -1;
 		if (p->vrtp && (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1)) {
+			if (len < 0) {
+				ast_log(LOG_WARNING, "Unknown SDP media type in offer: %s\n", m);
+				continue;
+			}
+
 			found = 1;
 			ast_clear_flag(p, SIP_NOVIDEO);	
 			vportno = x;
@@ -3628,9 +3909,14 @@
 			sendonly=1;
 			continue;
 		}
+		if (!strncasecmp(a, "crypto:", 7)) {
+			process_crypto(p, a);
+			continue;
+		}
 		if (!strcasecmp(a, "sendrecv")) {
 		  	sendonly=0;
 		}
+
 		if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
 		if (debug)
 			ast_verbose("Found description format %s\n", mimeSubtype);
@@ -3638,6 +3924,11 @@
 		ast_rtp_set_rtpmap_type(p->rtp, codec, "audio", mimeSubtype);
 		if (p->vrtp)
 			ast_rtp_set_rtpmap_type(p->vrtp, codec, "video", mimeSubtype);
+	}
+
+	if (secure_audio && !(p->srtp && p->srtp->a_crypto)) {
+		ast_log(LOG_WARNING, "Can't provide secure audio requested in SDP offer\n");
+		return -2;
 	}
 
 	/* Now gather all of the codecs that were asked for: */
@@ -4399,6 +4690,8 @@
 	char m_video[256];
 	char a_audio[1024];
 	char a_video[1024];
+	char crypto_buf[128];
+	const char *a_crypto = NULL;
 	char *m_audio_next = m_audio;
 	char *m_video_next = m_video;
 	size_t m_audio_left = sizeof(m_audio);
@@ -4413,6 +4706,8 @@
 	struct sockaddr_in dest;
 	struct sockaddr_in vdest = { 0, };
 	int debug;
+	const char *protocol = NULL;
+	struct sip_srtp *srtp = p->srtp;
 	
 	debug = sip_debug_test_pvt(p);
 
@@ -4458,6 +4753,24 @@
 			ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ntohs(vsin.sin_port));	
 	}
 
+	if (srtp) {
+		if (srtp->a_crypto) {
+			a_crypto = srtp->a_crypto;
+		} else {
+			const char *crypto_suite = "AES_CM_128_HMAC_SHA1_80";
+			snprintf(crypto_buf, sizeof(crypto_buf),
+				 "a=crypto:1 %s inline:%s\r\n",
+				 crypto_suite, srtp->local_key64);
+			a_crypto = crypto_buf;
+		}
+	}
+
+	if (a_crypto) {
+		protocol = "SAVP";
+	} else {
+		protocol = "AVP";
+	}
+
 	/* We break with the "recommendation" and send our IP, in order that our
 	   peer doesn't have to ast_gethostbyname() us */
 
@@ -4467,7 +4780,7 @@
 	snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
 	snprintf(t, sizeof(t), "t=0 0\r\n");
 
-	ast_build_string(&m_audio_next, &m_audio_left, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
+	ast_build_string(&m_audio_next, &m_audio_left, "m=audio %d RTP/%s", ntohs(dest.sin_port), protocol);
 	ast_build_string(&m_video_next, &m_video_left, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
 
 	/* Prefer the codec we were requested to use, first, no matter what */
@@ -4551,6 +4864,9 @@
 	if ((p->vrtp) && (!ast_test_flag(p, SIP_NOVIDEO)) && (capability & VIDEO_CODEC_MASK)) /* only if video response is appropriate */
 		len += strlen(m_video) + strlen(a_video);
 
+	if (a_crypto)
+		len += strlen(a_crypto);
+
 	add_header(resp, "Content-Type", "application/sdp");
 	add_header_contentLength(resp, len);
 	add_line(resp, v);
@@ -4560,6 +4876,8 @@
 	add_line(resp, t);
 	add_line(resp, m_audio);
 	add_line(resp, a_audio);
+	if (a_crypto)
+	    add_line(resp, a_crypto);
 	if ((p->vrtp) && (!ast_test_flag(p, SIP_NOVIDEO)) && (capability & VIDEO_CODEC_MASK)) { /* only if video response is appropriate */
 		add_line(resp, m_video);
 		add_line(resp, a_video);

Modified: team/oej/securertp/include/asterisk/aes.h
URL: http://svn.digium.com/view/asterisk/team/oej/securertp/include/asterisk/aes.h?rev=7892&r1=7891&r2=7892&view=diff
==============================================================================
--- team/oej/securertp/include/asterisk/aes.h (original)
+++ team/oej/securertp/include/asterisk/aes.h Mon Jan  9 10:25:20 2006
@@ -115,6 +115,8 @@
 
 #ifdef  AES_ENCRYPT
 
+#define aes_encrypt ast_aes_encrypt
+
 typedef struct  
 {   aes_32t ks[KS_LENGTH];
 } aes_encrypt_ctx;
@@ -139,6 +141,8 @@
 #endif
 
 #ifdef AES_DECRYPT
+
+#define aes_decrypt ast_aes_decrypt
 
 typedef struct  
 {   aes_32t ks[KS_LENGTH];

Modified: team/oej/securertp/include/asterisk/rtp.h
URL: http://svn.digium.com/view/asterisk/team/oej/securertp/include/asterisk/rtp.h?rev=7892&r1=7891&r2=7892&view=diff
==============================================================================
--- team/oej/securertp/include/asterisk/rtp.h (original)
+++ team/oej/securertp/include/asterisk/rtp.h Mon Jan  9 10:25:20 2006
@@ -68,6 +68,66 @@
  */
 struct ast_rtp;
 
+struct ast_srtp;
+
+struct ast_srtp_policy;
+
+struct ast_srtp_cb {
+	int (*no_ctx)(struct ast_rtp *rtp, unsigned long ssrc, void *data);
+};
+
+struct ast_srtp_res {
+	int (*create)(struct ast_srtp **srtp, struct ast_rtp *rtp,
+		      struct ast_srtp_policy *policy);
+	void (*destroy)(struct ast_srtp *srtp);
+	int (*add_stream)(struct ast_srtp *srtp, struct ast_srtp_policy *policy);
+	void (*set_cb)(struct ast_srtp *srtp,
+		       const struct ast_srtp_cb *cb, void *data);
+	int (*unprotect)(struct ast_srtp *srtp, void *buf, int *size);
+	int (*protect)(struct ast_srtp *srtp, void **buf, int *size);
+	int (*get_random)(unsigned char *key, size_t len);
+};
+
+/* Crypto suites */
+enum ast_srtp_suite {
+	AST_AES_CM_128_HMAC_SHA1_80 = 1,
+	AST_AES_CM_128_HMAC_SHA1_32 = 2,
+	AST_F8_128_HMAC_SHA1_80     = 3
+};
+
+enum ast_srtp_ealg {
+	AST_MIKEY_SRTP_EALG_NULL    = 0,
+	AST_MIKEY_SRTP_EALG_AESCM   = 1
+};
+
+enum ast_srtp_aalg {
+	AST_MIKEY_SRTP_AALG_NULL     = 0,
+	AST_MIKEY_SRTP_AALG_SHA1HMAC = 1
+};
+
+struct ast_srtp_policy_res {
+	struct ast_srtp_policy *(*alloc)(void);
+	void (*destroy)(struct ast_srtp_policy *policy);
+	int (*set_suite)(struct ast_srtp_policy *policy,
+			 enum ast_srtp_suite suite);
+	int (*set_master_key)(struct ast_srtp_policy *policy,
+			      const unsigned char *key, size_t key_len,
+			      const unsigned char *salt, size_t salt_len);
+	int (*set_encr_alg)(struct ast_srtp_policy *policy,
+			    enum ast_srtp_ealg  ealg);
+	int (*set_auth_alg)(struct ast_srtp_policy *policy,
+			    enum ast_srtp_aalg aalg);
+	void (*set_encr_keylen)(struct ast_srtp_policy *policy, int ekeyl);
+	void (*set_auth_keylen)(struct ast_srtp_policy *policy, int akeyl);
+	void (*set_srtp_auth_taglen)(struct ast_srtp_policy *policy, int autht);
+	void (*set_srtp_encr_enable)(struct ast_srtp_policy *policy, int enable);
+	void (*set_srtcp_encr_enable)(struct ast_srtp_policy *policy, int enable);
+	void (*set_srtp_auth_enable)(struct ast_srtp_policy *policy, int enable);
+	void (*set_ssrc)(struct ast_srtp_policy *policy, unsigned long ssrc,
+			 int inbound);
+};
+
+
 typedef int (*ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data);
 
 /*!
@@ -162,6 +222,32 @@
 
 void ast_rtp_reload(void);
 
+int ast_rtp_register_srtp(struct ast_srtp_res *srtp_res, struct ast_srtp_policy_res *policy_res);
+
+int ast_rtp_unregister_srtp(struct ast_srtp_res *srtp_res, struct ast_srtp_policy_res *policy_res);
+
+int ast_srtp_is_registered(void);
+
+unsigned int ast_rtp_get_ssrc(struct ast_rtp *rtp);
+void ast_rtp_set_srtp_cb(struct ast_rtp *rtp, const struct ast_srtp_cb *cb,
+	void *data);
+int ast_rtp_add_srtp_policy(struct ast_rtp *rtp, struct ast_srtp_policy *policy);
+struct ast_srtp_policy *ast_srtp_policy_alloc(void);
+int ast_srtp_policy_set_suite(struct ast_srtp_policy *policy, enum ast_srtp_suite suite);
+int ast_srtp_policy_set_master_key(struct ast_srtp_policy *policy, const unsigned char *key, size_t key_len, const unsigned char *salt, size_t salt_len);
+int ast_srtp_policy_set_encr_alg(struct ast_srtp_policy *policy, enum ast_srtp_ealg ealg);
+int ast_srtp_policy_set_auth_alg(struct ast_srtp_policy *policy, enum ast_srtp_aalg aalg);
+void ast_srtp_policy_set_encr_keylen(struct ast_srtp_policy *policy, int ekeyl);
+void ast_srtp_policy_set_auth_keylen(struct ast_srtp_policy *policy, int akeyl);
+void ast_srtp_policy_set_srtp_auth_taglen(struct ast_srtp_policy *policy, int autht);
+void ast_srtp_policy_set_srtp_encr_enable(struct ast_srtp_policy *policy, int enable);
+void ast_srtp_policy_set_srtcp_encr_enable(struct ast_srtp_policy *policy, int enable);
+void ast_srtp_policy_set_srtp_auth_enable(struct ast_srtp_policy *policy, int enable);
+void ast_srtp_policy_set_ssrc(struct ast_srtp_policy *policy, unsigned long ssrc, int inbound);
+
+void ast_srtp_policy_destroy(struct ast_srtp_policy *policy);
+int ast_srtp_get_random(unsigned char *key, size_t len);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/oej/securertp/res/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/securertp/res/Makefile?rev=7892&r1=7891&r2=7892&view=diff
==============================================================================
--- team/oej/securertp/res/Makefile (original)
+++ team/oej/securertp/res/Makefile Mon Jan  9 10:25:20 2006
@@ -60,6 +60,12 @@
 endif
 endif # WITHOUT_ZAPTEL
 
+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/srtp)$(wildcard $(CROSS_COMPILE_TARGET)/usr/include/srtp),)
+  MODS+=res_srtp.so
+  SRTP_LIBS=-lsrtp
+endif
+
+
 #
 # Work around buggy RedHat 9.0
 #
@@ -109,6 +115,9 @@
 res_config_odbc.so: res_config_odbc.o
 	$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} ${CYG_RES_CONFIG_ODBC_LIB}
 
+res_srtp.so: res_srtp.o
+	$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} ${SRTP_LIBS}
+
 ifneq ($(wildcard .depend),)
   include .depend
 endif

Modified: team/oej/securertp/rtp.c
URL: http://svn.digium.com/view/asterisk/team/oej/securertp/rtp.c?rev=7892&r1=7891&r2=7892&view=diff
==============================================================================
--- team/oej/securertp/rtp.c (original)
+++ team/oej/securertp/rtp.c Mon Jan  9 10:25:20 2006
@@ -72,6 +72,9 @@
 #ifdef SO_NO_CHECK
 static int nochecksums = 0;
 #endif
+
+struct ast_srtp_res *g_srtp_res;
+struct ast_srtp_policy_res *g_policy_res;
 
 /*! \brief The value of each payload format mapping: */
 struct rtpPayloadType {
@@ -124,6 +127,7 @@
 	int rtp_lookup_code_cache_code;
 	int rtp_lookup_code_cache_result;
 	struct ast_rtcp *rtcp;
+	struct ast_srtp *srtp;
 };
 
 /*!
@@ -348,6 +352,235 @@
 	rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
 	f = &rtp->f;
 	return f;
+}
+
+int ast_rtp_register_srtp(struct ast_srtp_res *srtp_res,
+			   struct ast_srtp_policy_res *policy_res)
+{
+	if (g_srtp_res || g_policy_res)
+		return -1;
+
+	if (!srtp_res || !policy_res)
+		return -1;
+
+	g_srtp_res = srtp_res;
+	g_policy_res = policy_res;
+	return 0;
+}
+
+int ast_rtp_unregister_srtp(struct ast_srtp_res *srtp_res,
+			     struct ast_srtp_policy_res *policy_res)
+{
+	g_srtp_res = NULL;
+	g_policy_res = NULL;
+	return 0;
+}
+
+int ast_srtp_is_registered(void)
+{
+	return g_srtp_res && g_policy_res;
+}
+
+unsigned int ast_rtp_get_ssrc(struct ast_rtp *rtp)
+{
+	return rtp->ssrc;
+}
+
+void ast_rtp_set_srtp_cb(struct ast_rtp *rtp, const struct ast_srtp_cb *cb,
+			 void *data)
+{
+	if (!g_srtp_res || !rtp->srtp)
+		return;
+
+	g_srtp_res->set_cb(rtp->srtp, cb, data);
+}
+
+void
+ast_srtp_policy_set_ssrc(struct ast_srtp_policy *policy,
+			  unsigned long ssrc, int inbound)
+{
+	if (!g_policy_res)
+		return;
+
+	g_policy_res->set_ssrc(policy, ssrc, inbound);
+}
+
+int ast_rtp_add_srtp_policy(struct ast_rtp *rtp, struct ast_srtp_policy *policy)
+{
+	int res;
+	
+	if (!g_srtp_res)
+		return -1;
+
+	if (!rtp->srtp) {
+		res = g_srtp_res->create(&rtp->srtp, rtp, policy);
+	} else {
+		res = g_srtp_res->add_stream(rtp->srtp, policy);
+	}
+
+	return res;
+}
+
+struct ast_srtp_policy *ast_srtp_policy_alloc()
+{
+	if (!g_policy_res)
+		return NULL;
+
+	return g_policy_res->alloc();
+}
+
+void
+ast_srtp_policy_destroy(struct ast_srtp_policy *policy)
+{
+	if (!g_policy_res)
+		return;
+
+	g_policy_res->destroy(policy);
+}
+
+int
+ast_srtp_policy_set_suite(struct ast_srtp_policy *policy,
+			   enum ast_srtp_suite suite)
+{
+	if (!g_policy_res)
+		return -1;
+
+	return g_policy_res->set_suite(policy, suite);
+}
+
+int
+ast_srtp_policy_set_master_key(struct ast_srtp_policy *policy,
+				const unsigned char *key, size_t key_len,
+				const unsigned char *salt, size_t salt_len)
+{
+	if (!g_policy_res)
+		return -1;
+
+	return g_policy_res->set_master_key(policy, key, key_len,
+					    salt, salt_len);
+}
+
+int
+ast_srtp_policy_set_encr_alg(struct ast_srtp_policy *policy,
+			      enum ast_srtp_ealg ealg)
+{
+	if (!g_policy_res)
+		return -1;
+
+	return g_policy_res->set_encr_alg(policy, ealg);
+}
+
+int
+ast_srtp_policy_set_auth_alg(struct ast_srtp_policy *policy,
+			      enum ast_srtp_aalg aalg)
+{
+	if (!g_policy_res)
+		return -1;
+
+	return g_policy_res->set_auth_alg(policy, aalg);
+}
+
+void ast_srtp_policy_set_encr_keylen(struct ast_srtp_policy *policy, int ekeyl)
+{
+	if (!g_policy_res)
+		return;
+
+	return g_policy_res->set_encr_keylen(policy, ekeyl);
+}
+
+void
+ast_srtp_policy_set_auth_keylen(struct ast_srtp_policy *policy,
+				 int akeyl)
+{
+	if (!g_policy_res)
+		return;
+
+	return g_policy_res->set_auth_keylen(policy, akeyl);
+}
+
+void
+ast_srtp_policy_set_srtp_auth_taglen(struct ast_srtp_policy *policy,
+				      int autht)
+{
+	if (!g_policy_res)
+		return;
+
+	return g_policy_res->set_srtp_auth_taglen(policy, autht);
+}
+
+void
+ast_srtp_policy_set_srtp_encr_enable(struct ast_srtp_policy *policy,
+				      int enable)
+{
+	if (!g_policy_res)
+		return;
+
+	return g_policy_res->set_srtp_encr_enable(policy, enable);
+}
+
+void
+ast_srtp_policy_set_srtcp_encr_enable(struct ast_srtp_policy *policy,
+				       int enable)
+{
+	if (!g_policy_res)
+		return;
+
+	return g_policy_res->set_srtcp_encr_enable(policy, enable);
+}
+
+void
+ast_srtp_policy_set_srtp_auth_enable(struct ast_srtp_policy *policy,
+				      int enable)
+{
+	if (!g_policy_res)
+		return;
+
+	return g_policy_res->set_srtp_auth_enable(policy, enable);
+}
+
+int ast_srtp_get_random(unsigned char *key, size_t len)
+{
+	if (!g_srtp_res)
+		return -1;
+
+	return g_srtp_res->get_random(key, len);
+}
+
+static int rtp_recvfrom(struct ast_rtp *rtp, void *buf, size_t size,
+			int flags, struct sockaddr *sa, socklen_t *salen)
+{
+	int len;
+
+	len = recvfrom(rtp->s, buf, size, flags, sa, salen);
+
+	if (len < 0)
+		return len;
+
+	if (g_srtp_res && rtp->srtp) {
+		int res;
+		
+		res = g_srtp_res->unprotect(rtp->srtp, buf, &len);
+		if (res < 0)
+			return -1;
+	}
+
+	return len;
+}
+
+static int rtp_sendto(struct ast_rtp *rtp, void *buf, size_t size,
+		      int flags, struct sockaddr *sa, socklen_t salen)
+{
+	int len = size;
+	void *temp = buf;
+
+	if (g_srtp_res && rtp->srtp) {
+		int res = g_srtp_res->protect(rtp->srtp, &temp, &len);
+
+		if (res < 0)
+			return -1;
+	}
+
+	return sendto(rtp->s, temp, len, flags, sa, salen);
 }
 
 static int rtpread(int *id, int fd, short events, void *cbdata)
@@ -440,7 +673,7 @@
 	len = sizeof(sin);
 	
 	/* Cache where the header will go */
-	res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
+	res = rtp_recvfrom(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
 					0, (struct sockaddr *)&sin, &len);
 
 
@@ -1167,6 +1400,10 @@
 		close(rtp->rtcp->s);
 		free(rtp->rtcp);
 	}
+	if (g_srtp_res && rtp->srtp) {
+		g_srtp_res->destroy(rtp->srtp);
+		rtp->srtp = NULL;
+	}
 	free(rtp);
 }
 
@@ -1229,7 +1466,7 @@
 	rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
 	for (x = 0; x < 6; x++) {
 		if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
-			res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+			res = rtp_sendto(rtp, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
 			if (res < 0) 
 				ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
 					ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
@@ -1295,7 +1532,7 @@
 	rtpheader[2] = htonl(rtp->ssrc); 
 	data[12] = level;
 	if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
-		res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
+		res = rtp_sendto(rtp, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
 		if (res <0) 
 			ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
 		if(rtp_debug_test_addr(&rtp->them))
@@ -1365,7 +1602,7 @@
 	put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 
 
 	if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
-		res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
+		res = rtp_sendto(rtp, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
 		if (res <0) {
 			if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
 				ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
@@ -1635,6 +1872,14 @@
 		ast_mutex_unlock(&c1->lock);
 		return AST_BRIDGE_FAILED_NOWARN;
 	}
+
+	if (p0->srtp || p1->srtp) {
+		ast_log(LOG_NOTICE, "Cannot native bridge in SRTP.\n");
+		ast_mutex_unlock(&c0->lock);
+		ast_mutex_unlock(&c1->lock);
+		return AST_BRIDGE_FAILED_NOWARN;
+	}
+
 	/* Get codecs from both sides */
 	if (pr0->get_codec)
 		codec0 = pr0->get_codec(c0);



More information about the svn-commits mailing list