]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-11052: Allow alias for crypto suites
authorPiotr Gregor <piotr@dataandsignal.com>
Wed, 21 Mar 2018 16:58:01 +0000 (16:58 +0000)
committerMike Jerris <mike@jerris.com>
Mon, 13 Aug 2018 20:57:50 +0000 (20:57 +0000)
For outgoing calls send AES crypto in offer using corrected names
for keys of length 192 and 256, i.e. names containing _192_CM_
and _256_CM_ instead of _CM_192_ and CM_256_. For incoming calls
accept both naming conventions, decaying to same entry in SUITES.

+ fix after SRTP failed for 256 keys:

Tests showed loop removing '=' from keys in switch_core_media_build_crypto

 1190     if (!switch_channel_var_true(channel, "rtp_pad_srtp_keys")) {
 1191         p = strrchr((char *) b64_key, '=');
 1192
 1193         while (p && *p && *p == '=') {
 1194             *p-- = '\0';
 1195         }
 1196     }

shouldn't be executed for AES_CM_256_HMAC_SHA1_32 and AES_CM_256_HMAC_SHA1_80
keys and it is meaningless for AES_CM_128_HMAC_SHA1_32 AES_CM_128_HMAC_SHA1_80
keys. Tested calling from Bria.

Introduced switch_channel_var_false and changed this to:
if (switch_channel_var_false(channel, "rtp_pad_srtp_keys"))
to enter the loop if var is set to false (and not if it is _not_ set).

src/include/switch_channel.h
src/include/switch_rtp.h
src/switch_core_media.c
src/switch_rtp.c

index 86d6769bc6ecc942b69eb314a179e899228f009c..8e24893fdcacb9c0235f181fa7aef78302a187d2 100644 (file)
@@ -320,6 +320,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_get_variables(switch_channel_t *c
 
 SWITCH_DECLARE(switch_status_t) switch_channel_pass_callee_id(switch_channel_t *channel, switch_channel_t *other_channel);
 
+static inline int switch_channel_var_false(switch_channel_t *channel, const char *variable) {
+       return switch_false(switch_channel_get_variable_dup(channel, variable, SWITCH_FALSE, -1));
+}
 
 static inline int switch_channel_var_true(switch_channel_t *channel, const char *variable) {
        return switch_true(switch_channel_get_variable_dup(channel, variable, SWITCH_FALSE, -1));
index 5566d36ff6976834ceed6f120115a7cb584bfb6e..41e863768397be8d952fd7f6a4590b5711d1a2db 100644 (file)
@@ -65,6 +65,7 @@ typedef enum {
 
 typedef struct switch_srtp_crypto_suite_s {
        char *name;
+       const char *alias;
        switch_rtp_crypto_key_type_t type;
        int keysalt_len;
        int salt_len;
index 4100a6ed7c97515e56127891423128ffa664f166..1e8ab68efb6245947ae359cea883cad6a5035f5e 100644 (file)
@@ -273,15 +273,15 @@ struct switch_media_handle_s {
 };
 
 switch_srtp_crypto_suite_t SUITES[CRYPTO_INVALID] = {
-       { "AEAD_AES_256_GCM_8", AEAD_AES_256_GCM_8, 44, 12},
-       { "AEAD_AES_128_GCM_8", AEAD_AES_128_GCM_8, 28, 12},
-       { "AES_CM_256_HMAC_SHA1_80", AES_CM_256_HMAC_SHA1_80, 46, 14},
-       { "AES_CM_192_HMAC_SHA1_80", AES_CM_192_HMAC_SHA1_80, 38, 14},
-       { "AES_CM_128_HMAC_SHA1_80", AES_CM_128_HMAC_SHA1_80, 30, 14},
-       { "AES_CM_256_HMAC_SHA1_32", AES_CM_256_HMAC_SHA1_32, 46, 14},
-       { "AES_CM_192_HMAC_SHA1_32", AES_CM_192_HMAC_SHA1_32, 38, 14},
-       { "AES_CM_128_HMAC_SHA1_32", AES_CM_128_HMAC_SHA1_32, 30, 14},
-       { "AES_CM_128_NULL_AUTH", AES_CM_128_NULL_AUTH, 30, 14}
+       { "AEAD_AES_256_GCM_8", "", AEAD_AES_256_GCM_8, 44, 12},
+       { "AEAD_AES_128_GCM_8", "", AEAD_AES_128_GCM_8, 28, 12},
+       { "AES_256_CM_HMAC_SHA1_80", "AES_CM_256_HMAC_SHA1_80", AES_CM_256_HMAC_SHA1_80, 46, 14},
+       { "AES_192_CM_HMAC_SHA1_80", "AES_CM_192_HMAC_SHA1_80", AES_CM_192_HMAC_SHA1_80, 38, 14},
+       { "AES_CM_128_HMAC_SHA1_80", "", AES_CM_128_HMAC_SHA1_80, 30, 14},
+       { "AES_256_CM_HMAC_SHA1_32", "AES_CM_256_HMAC_SHA1_32", AES_CM_256_HMAC_SHA1_32, 46, 14},
+       { "AES_192_CM_HMAC_SHA1_32", "AES_CM_192_HMAC_SHA1_32", AES_CM_192_HMAC_SHA1_32, 38, 14},
+       { "AES_CM_128_HMAC_SHA1_32", "", AES_CM_128_HMAC_SHA1_32, 30, 14},
+       { "AES_CM_128_NULL_AUTH", "", AES_CM_128_NULL_AUTH, 30, 14}
 };
 
 SWITCH_DECLARE(switch_rtp_crypto_key_type_t) switch_core_media_crypto_str2type(const char *str)
@@ -289,7 +289,7 @@ SWITCH_DECLARE(switch_rtp_crypto_key_type_t) switch_core_media_crypto_str2type(c
        int i;
 
        for (i = 0; i < CRYPTO_INVALID; i++) {
-               if (!strncasecmp(str, SUITES[i].name, strlen(SUITES[i].name))) {
+               if (!strncasecmp(str, SUITES[i].name, strlen(SUITES[i].name)) || (SUITES[i].alias && strlen(SUITES[i].alias) && !strncasecmp(str, SUITES[i].alias, strlen(SUITES[i].alias)))) {
                        return SUITES[i].type;
                }
        }
@@ -1140,10 +1140,12 @@ SWITCH_DECLARE(void) switch_core_media_parse_rtp_bugs(switch_rtp_bug_flag_t *fla
        }
 }
 
-
+/**
+ * If @use_alias != 0 then send crypto with alias name instead of name.
+ */ 
 static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh,
                                                                                                          switch_media_type_t type,
-                                                                                                         int index, switch_rtp_crypto_key_type_t ctype, switch_rtp_crypto_direction_t direction, int force)
+                                                                                                         int index, switch_rtp_crypto_key_type_t ctype, switch_rtp_crypto_direction_t direction, int force, int use_alias)
 {
        unsigned char b64_key[512] = "";
        unsigned char *key;
@@ -1185,7 +1187,7 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh
 #endif
 
        switch_b64_encode(key, SUITES[ctype].keysalt_len, b64_key, sizeof(b64_key));
-       if (!switch_channel_var_true(channel, "rtp_pad_srtp_keys")) {
+       if (switch_channel_var_false(channel, "rtp_pad_srtp_keys")) {
                p = strrchr((char *) b64_key, '=');
 
                while (p && *p && *p == '=') {
@@ -1196,9 +1198,9 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh
        if (index == SWITCH_NO_CRYPTO_TAG) index = ctype + 1;
 
        if (switch_channel_var_true(channel, "rtp_secure_media_mki")) { 
-               engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s|2^31|1:1", index, SUITES[ctype].name, b64_key);
+               engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s|2^31|1:1", index, (use_alias ? SUITES[ctype].alias : SUITES[ctype].name), b64_key);
        } else {
-               engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, SUITES[ctype].name, b64_key);
+               engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, (use_alias ? SUITES[ctype].alias : SUITES[ctype].name), b64_key);
        }
 
        switch_channel_set_variable_name_printf(smh->session->channel, engine->ssec[ctype].local_crypto_key, "rtp_last_%s_local_crypto_key", type2str(type));
@@ -1218,7 +1220,6 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh
        return SWITCH_STATUS_SUCCESS;
 }
 
-
 #define CRYPTO_KEY_MATERIAL_LIFETIME_MKI_ERR   0x0u
 #define CRYPTO_KEY_MATERIAL_MKI                                        0x1u
 #define CRYPTO_KEY_MATERIAL_LIFETIME                   0x2u
@@ -1771,8 +1772,6 @@ static void switch_core_session_parse_crypto_prefs(switch_core_session_t *sessio
        }
 }
 
-
-
 SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_session_t *session,
                                                                                                                           const char *varname,
                                                                                                                          switch_media_type_t type, const char *crypto, int crypto_tag, switch_sdp_type_t sdp_type)
@@ -1781,6 +1780,7 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio
        int i = 0;
        int ctype = 0;
        const char *vval = NULL;
+       int use_alias = 0;
        switch_rtp_engine_t *engine;
        switch_media_handle_t *smh;
 
@@ -1801,15 +1801,21 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio
        for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
                switch_rtp_crypto_key_type_t j = SUITES[smh->crypto_suite_order[i]].type;
 
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "looking for crypto suite [%s] in [%s]\n", SUITES[j].name, crypto);
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "looking for crypto suite [%s]alias=[%s] in [%s]\n", SUITES[j].name, SUITES[j].alias, crypto);
 
-               if (switch_stristr(SUITES[j].name, crypto)) {
+               if (switch_stristr(SUITES[j].alias, crypto)) {
+                       use_alias = 1;
+               }
+               
+               if (use_alias || switch_stristr(SUITES[j].name, crypto)) {
                        ctype = SUITES[j].type;
-                       vval = SUITES[j].name;
+                       vval = use_alias ? SUITES[j].alias : SUITES[j].name;
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Found suite %s\n", vval);
                        switch_channel_set_variable(session->channel, "rtp_secure_media_negotiated", vval);
                        break;
                }
+
+               use_alias = 0;
        }
 
        if (engine->ssec[engine->crypto_type].remote_crypto_key && switch_rtp_ready(engine->rtp_session)) {
@@ -1828,7 +1834,7 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio
                                }
                                switch_channel_set_variable(session->channel, varname, vval);
 
-                               switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1);
+                               switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1, use_alias);
                                switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), &engine->ssec[engine->crypto_type]);
                        }
 
@@ -1893,7 +1899,7 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio
                switch_channel_set_flag(smh->session->channel, CF_SECURE);
 
                if (zstr(engine->ssec[engine->crypto_type].local_crypto_key)) {
-                       switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1);
+                       switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1, use_alias);
                }
        }
 
@@ -1929,13 +1935,13 @@ SWITCH_DECLARE(void) switch_core_session_check_outgoing_crypto(switch_core_sessi
 
        for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
                switch_core_media_build_crypto(session->media_handle,
-                                                                          SWITCH_MEDIA_TYPE_AUDIO, SWITCH_NO_CRYPTO_TAG, smh->crypto_suite_order[i], SWITCH_RTP_CRYPTO_SEND, 0);
+                                                                          SWITCH_MEDIA_TYPE_AUDIO, SWITCH_NO_CRYPTO_TAG, smh->crypto_suite_order[i], SWITCH_RTP_CRYPTO_SEND, 0, 0);
 
                switch_core_media_build_crypto(session->media_handle,
-                                                                          SWITCH_MEDIA_TYPE_VIDEO, SWITCH_NO_CRYPTO_TAG, smh->crypto_suite_order[i], SWITCH_RTP_CRYPTO_SEND, 0);
+                                                                          SWITCH_MEDIA_TYPE_VIDEO, SWITCH_NO_CRYPTO_TAG, smh->crypto_suite_order[i], SWITCH_RTP_CRYPTO_SEND, 0, 0);
 
                switch_core_media_build_crypto(session->media_handle,
-                                                                          SWITCH_MEDIA_TYPE_TEXT, SWITCH_NO_CRYPTO_TAG, smh->crypto_suite_order[i], SWITCH_RTP_CRYPTO_SEND, 0);
+                                                                          SWITCH_MEDIA_TYPE_TEXT, SWITCH_NO_CRYPTO_TAG, smh->crypto_suite_order[i], SWITCH_RTP_CRYPTO_SEND, 0, 0);
        }
 
 }
index 517292bcc187c3464e034b51f2a52141a216a2a4..2edcb382184e12698b95baf6684d24946e7562da 100644 (file)
@@ -3932,7 +3932,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
                break;
        case AES_CM_128_HMAC_SHA1_32:
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy->rtp);
-               srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy->rtcp);
+               srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy->rtcp);
 
 
                if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
@@ -3965,6 +3965,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
                        switch_channel_set_variable(channel, "rtp_has_crypto", "AES_CM_256_HMAC_SHA1_80");
                }
                break;
+       case AES_CM_256_HMAC_SHA1_32:
+               srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(&policy->rtp);
+               srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(&policy->rtcp);
+               if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+                       switch_channel_set_variable(channel, "rtp_has_crypto", "AES_CM_256_HMAC_SHA1_32");
+               }
+               break;
        case AES_CM_128_NULL_AUTH:
                srtp_crypto_policy_set_aes_cm_128_null_auth(&policy->rtp);
                srtp_crypto_policy_set_aes_cm_128_null_auth(&policy->rtcp);