diff --git a/main/sdp_srtp.c b/main/sdp_srtp.c
index 31d633e387ff778df05e7280d9c8720ae9a160a9..fee3fea56ce716daf60ab1a8ee36a2e44b1d6f6a 100644
--- a/main/sdp_srtp.c
+++ b/main/sdp_srtp.c
@@ -34,6 +34,7 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include <math.h>
 #include "asterisk/options.h"
 #include "asterisk/utils.h"
 #include "asterisk/sdp_srtp.h"
@@ -68,7 +69,7 @@ void ast_sdp_srtp_destroy(struct ast_sdp_srtp *srtp)
 struct ast_sdp_crypto {
 	char *a_crypto;
 	unsigned char local_key[SRTP_MASTER_LEN];
-	char *tag;
+	int tag;
 	char local_key64[SRTP_MASTER_LEN64];
 	unsigned char remote_key[SRTP_MASTER_LEN];
 };
@@ -79,8 +80,6 @@ void ast_sdp_crypto_destroy(struct ast_sdp_crypto *crypto)
 {
 	ast_free(crypto->a_crypto);
 	crypto->a_crypto = NULL;
-	ast_free(crypto->tag);
-	crypto->tag = NULL;
 	ast_free(crypto);
 }
 
@@ -97,6 +96,7 @@ struct ast_sdp_crypto *ast_sdp_crypto_alloc(void)
 	if (!(p = ast_calloc(1, sizeof(*p)))) {
 		return NULL;
 	}
+	p->tag = 1;
 
 	if (res_srtp->get_random(p->local_key, sizeof(p->local_key)) < 0) {
 		ast_sdp_crypto_destroy(p);
@@ -109,13 +109,13 @@ struct ast_sdp_crypto *ast_sdp_crypto_alloc(void)
 
 	if (key_len != SRTP_MASTER_LEN) {
 		ast_log(LOG_ERROR, "base64 encode/decode bad len %d != %d\n", key_len, SRTP_MASTER_LEN);
-		ast_free(p);
+		ast_sdp_crypto_destroy(p);
 		return NULL;
 	}
 
 	if (memcmp(remote_key, p->local_key, SRTP_MASTER_LEN)) {
 		ast_log(LOG_ERROR, "base64 encode/decode bad key\n");
-		ast_free(p);
+		ast_sdp_crypto_destroy(p);
 		return NULL;
 	}
 
@@ -211,13 +211,15 @@ int ast_sdp_crypto_process(struct ast_rtp_instance *rtp, struct ast_sdp_srtp *sr
 	char *key_params = NULL;
 	char *key_param = NULL;
 	char *session_params = NULL;
-	char *key_salt = NULL;
-	char *lifetime = NULL;
+	char *key_salt = NULL;       /* The actual master key and key salt */
+	char *lifetime = NULL;       /* Key lifetime (# of RTP packets) */
+	char *mki = NULL;            /* Master Key Index */
 	int found = 0;
 	int key_len = 0;
 	int suite_val = 0;
 	unsigned char remote_key[SRTP_MASTER_LEN];
 	int taglen = 0;
+	double sdes_lifetime;
 	struct ast_sdp_crypto *crypto = srtp->crypto;
 
 	if (!ast_rtp_engine_srtp_is_registered()) {
@@ -236,6 +238,11 @@ int ast_sdp_crypto_process(struct ast_rtp_instance *rtp, struct ast_sdp_srtp *sr
 		return -1;
 	}
 
+	if (sscanf(tag, "%30d", &crypto->tag) != 1 || crypto->tag <= 0 || crypto->tag > 9) {
+		ast_log(LOG_WARNING, "Unacceptable a=crypto tag: %s\n", tag);
+		return -1;
+	}
+
 	if (!ast_strlen_zero(session_params)) {
 		ast_log(LOG_WARNING, "Unsupported crypto parameters: %s\n", session_params);
 		return -1;
@@ -255,33 +262,88 @@ int ast_sdp_crypto_process(struct ast_rtp_instance *rtp, struct ast_sdp_srtp *sr
 	}
 
 	while ((key_param = strsep(&key_params, ";"))) {
+		unsigned int n_lifetime;
 		char *method = NULL;
 		char *info = NULL;
 
 		method = strsep(&key_param, ":");
 		info = strsep(&key_param, ";");
+		sdes_lifetime = 0;
 
-		if (!strcmp(method, "inline")) {
-			key_salt = strsep(&info, "|");
-			lifetime = strsep(&info, "|");
+		if (strcmp(method, "inline")) {
+			continue;
+		}
 
-			if (lifetime) {
-				ast_log(LOG_NOTICE, "Crypto life time unsupported: %s\n", attr);
-				continue;
-			}
+		key_salt = strsep(&info, "|");
 
+		/* The next parameter can be either lifetime or MKI */
+		lifetime = strsep(&info, "|");
+		if (!lifetime) {
 			found = 1;
 			break;
 		}
+
+		mki = strchr(lifetime, ':');
+		if (mki) {
+			mki = lifetime;
+			lifetime = NULL;
+		} else {
+			mki = strsep(&info, "|");
+		}
+
+		if (mki && *mki != '1') {
+			ast_log(LOG_NOTICE, "Crypto MKI handling is not supported: ignoring attribute %s\n", attr);
+			continue;
+		}
+
+		if (lifetime) {
+			if (!strncmp(lifetime, "2^", 2)) {
+				char *lifetime_val = lifetime + 2;
+
+				/* Exponential lifetime */
+				if (sscanf(lifetime_val, "%30u", &n_lifetime) != 1) {
+					ast_log(LOG_NOTICE, "Failed to parse lifetime value in crypto attribute: %s\n", attr);
+					continue;
+				}
+
+				if (n_lifetime > 48) {
+					/* Yeah... that's a bit big. */
+					ast_log(LOG_NOTICE, "Crypto lifetime exponent of '%u' is a bit large; using 48\n", n_lifetime);
+					n_lifetime = 48;
+				}
+				sdes_lifetime = pow(2, n_lifetime);
+			} else {
+				/* Decimal lifetime */
+				if (sscanf(lifetime, "%30u", &n_lifetime) != 1) {
+					ast_log(LOG_NOTICE, "Failed to parse lifetime value in crypto attribute: %s\n", attr);
+					continue;
+				}
+				sdes_lifetime = n_lifetime;
+			}
+
+			/* Accept anything above 10 hours. Less than 10; reject. */
+			if (sdes_lifetime < 1800000) {
+				ast_log(LOG_NOTICE, "Rejecting crypto attribute '%s': lifetime '%f' too short\n", attr, sdes_lifetime);
+				continue;
+			}
+		}
+
+		ast_debug(2, "Crypto attribute '%s' accepted with lifetime '%f', MKI '%s'\n",
+			attr, sdes_lifetime, mki ? mki : "-");
+
+		found = 1;
+		break;
 	}
 
 	if (!found) {
-		ast_log(LOG_NOTICE, "SRTP crypto offer not acceptable\n");
+		ast_log(LOG_NOTICE, "SRTP crypto offer not acceptable: '%s'\n", attr);
 		return -1;
 	}
 
-	if ((key_len = ast_base64decode(remote_key, key_salt, sizeof(remote_key))) != SRTP_MASTER_LEN) {
-		ast_log(LOG_WARNING, "SRTP descriptions key %d != %d\n", key_len, SRTP_MASTER_LEN);
+	key_len = ast_base64decode(remote_key, key_salt, sizeof(remote_key));
+	if (key_len != SRTP_MASTER_LEN) {
+		ast_log(LOG_WARNING, "SRTP descriptions key length '%d' != master length '%d'\n",
+			key_len, SRTP_MASTER_LEN);
 		return -1;
 	}
 
@@ -296,15 +358,6 @@ int ast_sdp_crypto_process(struct ast_rtp_instance *rtp, struct ast_sdp_srtp *sr
 		return -1;
 	}
 
-	if (!crypto->tag) {
-		ast_debug(1, "Accepting crypto tag %s\n", tag);
-		crypto->tag = ast_strdup(tag);
-		if (!crypto->tag) {
-			ast_log(LOG_ERROR, "Could not allocate memory for tag\n");
-			return -1;
-		}
-	}
-
 	/* Finally, rebuild the crypto line */
 	if (ast_sdp_crypto_build_offer(crypto, taglen)) {
 		return -1;
@@ -321,8 +374,8 @@ int ast_sdp_crypto_build_offer(struct ast_sdp_crypto *p, int taglen)
 		ast_free(p->a_crypto);
 	}
 
-	if (ast_asprintf(&p->a_crypto, "%s AES_CM_128_HMAC_SHA1_%i inline:%s",
-			 p->tag ? p->tag : "1", taglen, p->local_key64) == -1) {
+	if (ast_asprintf(&p->a_crypto, "%d AES_CM_128_HMAC_SHA1_%i inline:%s",
+			 p->tag, taglen, p->local_key64) == -1) {
 			ast_log(LOG_ERROR, "Could not allocate memory for crypto line\n");
 		return -1;
 	}