Merge pull request #1 in FSA/freeswitch-advantage from ~PIOTRGREGOR/freeswitch:feature/FS-10778-srtp-mki-support to v1.8-fsa

* commit '6520827b620951b8e016cbaaa4d321261e3ea3e2':
  FS-10778: Add support for MKI to SRTP
This commit is contained in:
Mike Jerris
2017-11-30 20:20:33 +00:00
6 changed files with 626 additions and 140 deletions
+5 -6
View File
@@ -44,7 +44,6 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_RTP_MAX_BUF_LEN 16384
#define SWITCH_RTCP_MAX_BUF_LEN 16384
#define SWITCH_RTP_MAX_BUF_LEN_WORDS 4094 /* (max / 4) - 2 */
#define SWITCH_RTP_MAX_CRYPTO_LEN 64
//#define SWITCH_RTP_KEY_LEN 30
//#define SWITCH_RTP_CRYPTO_KEY_32 "AES_CM_128_HMAC_SHA1_32"
#define SWITCH_RTP_CRYPTO_KEY_80 "AES_CM_128_HMAC_SHA1_80"
@@ -67,14 +66,16 @@ typedef enum {
typedef struct switch_srtp_crypto_suite_s {
char *name;
switch_rtp_crypto_key_type_t type;
int keylen;
int keysalt_len;
int salt_len;
} switch_srtp_crypto_suite_t;
extern switch_srtp_crypto_suite_t SUITES[CRYPTO_INVALID];
struct switch_rtp_crypto_key {
uint32_t index;
switch_rtp_crypto_key_type_t type;
unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
unsigned char keysalt[SWITCH_RTP_MAX_CRYPTO_LEN];
switch_size_t keylen;
struct switch_rtp_crypto_key *next;
};
@@ -170,9 +171,7 @@ typedef enum { /* FMT Values for PSFB Payload Types http://www.iana.org/assignme
SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session,
switch_rtp_crypto_direction_t direction,
uint32_t index, switch_rtp_crypto_key_type_t type, unsigned char *key, switch_size_t keylen);
SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session, switch_rtp_crypto_direction_t direction, uint32_t index, switch_secure_settings_t *ssec);
///\defgroup rtp RTP (RealTime Transport Protocol)
///\ingroup core1
+58
View File
@@ -779,6 +779,8 @@ typedef enum {
SWITCH_RTP_FLAG_TEXT,
SWITCH_RTP_FLAG_OLD_FIR,
SWITCH_RTP_FLAG_PASSTHRU,
SWITCH_RTP_FLAG_SECURE_SEND_MKI,
SWITCH_RTP_FLAG_SECURE_RECV_MKI,
SWITCH_RTP_FLAG_INVALID
} switch_rtp_flag_t;
@@ -2566,6 +2568,12 @@ typedef enum {
CRYPTO_INVALID
} switch_rtp_crypto_key_type_t;
/* Keep in sync with CRYPTO_KEY_PARAM_METHOD table. */
typedef enum {
CRYPTO_KEY_PARAM_METHOD_INLINE, /* identified by "inline" chars in SRTP key parameter */
CRYPTO_KEY_PARAM_METHOD_INVALID
} switch_rtp_crypto_key_param_method_type_t;
typedef struct payload_map_s {
switch_media_type_t type;
switch_sdp_type_t sdp_type;
@@ -2709,6 +2717,56 @@ typedef struct switch_mm_s {
char *auth_password;
} switch_mm_t;
#define SWITCH_RTP_MAX_CRYPTO_LEN 64
/* If MKI is used, then one or more key-materials are present in the <key-params> section of the crypto attribute.
* This struct describes the single MKI entry (key-material) within <key-params> section of crypto attribute.
* Key-material follows the format:
* "inline:" <key||salt> ["|" lifetime] ["|" MKI ":" length]
* which translates to
* "inline: KEYSALT|MKI_ID:MKI_SZ" or "inline: KEYSALT|LIFETIME|MKI_ID:MKI_SZ" */
typedef struct switch_crypto_key_material_s {
switch_rtp_crypto_key_param_method_type_t method;
unsigned char raw_key[SWITCH_RTP_MAX_CRYPTO_LEN]; /* Key-salt. Master key appended with salt. Sizes determined by crypto suite. */
char *crypto_key; /* Complete key material string ("method:keysalt[|lifetime]|mki"). */
uint64_t lifetime; /* OPTIONAL. The lifetime value MAY be written as a non-zero, positive decimal integer or as a power of 2. Must be less than max lifetime of RTP and RTCP packets in given crypto suite. */
unsigned int mki_id; /* OPTIONAL. */
unsigned int mki_size; /* OPTIONAL. Byte length of the master key field in the RTP packet. */
struct switch_crypto_key_material_s *next; /* NULL if this is the last master key in crypto attribute set. */
} switch_crypto_key_material_t;
typedef struct secure_settings_s {
int crypto_tag;
unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
switch_rtp_crypto_key_type_t crypto_type;
char *local_crypto_key;
char *remote_crypto_key;
/*
* MKI support (as per rfc4568).
* Normally single crypto attribute contains one key-material in a <key-params> section, e.g. "inline: KEYSALT" or "inline: KEYSALT|2^LIFETIME_BITS".
* But if MKI is used, then one or more key-materials are present in the <key-params> section of the crypto attribute. Each key-material follows the format:
*
* "inline:" <key||salt> ["|" lifetime] ["|" MKI ":" length]
*
* "inline: KEYSALT|MKI_ID:MKI_SZ"
* or
* "inline: KEYSALT|2^LIFETIME_BITS|MKI_ID:MKI_SZ"
*
* This points to singly linked list of key-material descriptions if there is more than one key-material present in this crypto attribute (this key is inserted as the head of the list in that case), or to NULL otherwise.
*/
struct switch_crypto_key_material_s *local_key_material_next; /* NULL if MKI not used for crypto set on outbound SRTP. */
unsigned long local_key_material_n; /* number of key_materials in the linked list for outbound SRTP */
struct switch_crypto_key_material_s *remote_key_material_next; /* NULL if MKI not used for crypto set on inbound SRTP. */
unsigned long remote_key_material_n; /* number of key_materials in the linked list for inbound SRTP */
} switch_secure_settings_t;
/* Default MKI index used for packets send from FS. We always use first key if multiple master keys are present in the crypto attribute. */
#define SWITCH_CRYPTO_MKI_INDEX 0
/* max number of MKI in a single crypto line supported */
#define SWITCH_CRYPTO_MKI_MAX 20
SWITCH_END_EXTERN_C
#endif
+1 -1
View File
@@ -391,7 +391,7 @@ static inline int switch_string_has_escaped_data(const char *in)
#endif
SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen);
SWITCH_DECLARE(switch_size_t) switch_b64_decode(char *in, char *out, switch_size_t olen);
SWITCH_DECLARE(switch_size_t) switch_b64_decode(const char *in, char *out, switch_size_t olen);
SWITCH_DECLARE(char *) switch_amp_encode(char *s, char *buf, switch_size_t len);
+385 -81
View File
@@ -64,16 +64,6 @@ typedef enum {
SMF_VB_PAUSED = (1 << 3)
} smh_flag_t;
typedef struct secure_settings_s {
int crypto_tag;
unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
switch_rtp_crypto_key_type_t crypto_type;
char *local_crypto_key;
char *remote_crypto_key;
} switch_secure_settings_t;
typedef struct core_video_globals_s {
int cpu_count;
int cur_cpu;
@@ -282,16 +272,16 @@ struct switch_media_handle_s {
};
static switch_srtp_crypto_suite_t SUITES[CRYPTO_INVALID] = {
{ "AEAD_AES_256_GCM_8", AEAD_AES_256_GCM_8, 44},
{ "AEAD_AES_128_GCM_8", AEAD_AES_128_GCM_8, 28},
{ "AES_CM_256_HMAC_SHA1_80", AES_CM_256_HMAC_SHA1_80, 46},
{ "AES_CM_192_HMAC_SHA1_80", AES_CM_192_HMAC_SHA1_80, 38},
{ "AES_CM_128_HMAC_SHA1_80", AES_CM_128_HMAC_SHA1_80, 30},
{ "AES_CM_256_HMAC_SHA1_32", AES_CM_256_HMAC_SHA1_32, 46},
{ "AES_CM_192_HMAC_SHA1_32", AES_CM_192_HMAC_SHA1_32, 38},
{ "AES_CM_128_HMAC_SHA1_32", AES_CM_128_HMAC_SHA1_32, 30},
{ "AES_CM_128_NULL_AUTH", AES_CM_128_NULL_AUTH, 30}
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}
};
SWITCH_DECLARE(switch_rtp_crypto_key_type_t) switch_core_media_crypto_str2type(const char *str)
@@ -315,12 +305,16 @@ SWITCH_DECLARE(const char *) switch_core_media_crypto_type2str(switch_rtp_crypto
}
SWITCH_DECLARE(int) switch_core_media_crypto_keylen(switch_rtp_crypto_key_type_t type)
SWITCH_DECLARE(int) switch_core_media_crypto_keysalt_len(switch_rtp_crypto_key_type_t type)
{
switch_assert(type < CRYPTO_INVALID);
return SUITES[type].keylen;
return SUITES[type].keysalt_len;
}
static const char* CRYPTO_KEY_PARAM_METHOD[CRYPTO_KEY_PARAM_METHOD_INVALID] = {
[CRYPTO_KEY_PARAM_METHOD_INLINE] = "inline",
};
static inline switch_media_flow_t sdp_media_flow(unsigned in)
{
switch(in) {
@@ -1161,16 +1155,14 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh
return SWITCH_STATUS_SUCCESS;
}
//#define SAME_KEY
#ifdef SAME_KEY
if (switch_channel_test_flag(channel, CF_AVPF) && type == SWITCH_MEDIA_TYPE_VIDEO) {
if (direction == SWITCH_RTP_CRYPTO_SEND) {
memcpy(engine->ssec[ctype].local_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.local_raw_key, SUITES[ctype].keylen);
memcpy(engine->ssec[ctype].local_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.local_raw_key, SUITES[ctype].keysalt_len);
key = engine->ssec[ctype].local_raw_key;
} else {
memcpy(engine->ssec[ctype].remote_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.remote_raw_key, SUITES[ctype].keylen);
memcpy(engine->ssec[ctype].remote_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.remote_raw_key, SUITES[ctype].keysalt_len);
key = engine->ssec[ctype].remote_raw_key;
}
} else {
@@ -1181,12 +1173,12 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh
key = engine->ssec[ctype].remote_raw_key;
}
switch_rtp_get_random(key, SUITES[ctype].keylen);
switch_rtp_get_random(key, SUITES[ctype].keysalt_len);
#ifdef SAME_KEY
}
#endif
switch_b64_encode(key, SUITES[ctype].keylen, b64_key, sizeof(b64_key));
switch_b64_encode(key, SUITES[ctype].keysalt_len, b64_key, sizeof(b64_key));
if (!switch_channel_var_true(channel, "rtp_pad_srtp_keys")) {
p = strrchr((char *) b64_key, '=');
@@ -1197,7 +1189,12 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh
if (index == SWITCH_NO_CRYPTO_TAG) index = ctype + 1;
engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, SUITES[ctype].name, b64_key);
if (switch_channel_get_variable(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);
} else {
engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, 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));
switch_channel_set_flag(smh->session->channel, CF_SECURE);
@@ -1216,17 +1213,180 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh
}
#define CRYPTO_KEY_MATERIAL_LIFETIME_MKI_ERR 0x0u
#define CRYPTO_KEY_MATERIAL_MKI 0x1u
#define CRYPTO_KEY_MATERIAL_LIFETIME 0x2u
#define RAW_BITS_PER_64_ENCODED_CHAR 6
/* Return uint32_t which contains all the info about the field found:
* XXXXXXXa | YYYYYYYY | YYYYYYYY | ZZZZZZZZ
* where:
* a - CRYPTO_KEY_MATERIAL_LIFETIME if LIFETIME, CRYPTO_KEY_MATERIAL_MKI if MKI
* YYYYYYYY and ZZZZZZZZ - depend on 'a':
* if a is LIFETIME then YYYYYYYY is decimal Base, ZZZZZZZZ is decimal Exponent
* if a is MKI, then YYYYYYYY is decimal MKI_ID, ZZZZZZZZ is decimal MKI_SIZE
*/
static uint32_t parse_lifetime_mki(const char **p, const char *end)
{
const char *field_begin;
const char *field_end;
const char *sep, *space;
uint32_t res = 0;
switch_status_t switch_core_media_add_crypto(switch_secure_settings_t *ssec, const char *key_str, switch_rtp_crypto_direction_t direction)
uint32_t val = 0;
int i;
switch_assert(*p != NULL);
switch_assert(end != NULL);
field_begin = strchr(*p, '|');
if (field_begin && (field_begin + 1 < end)) {
space = strchr(field_begin, ' ');
field_end = strchr(field_begin + 2, '|');
if (!field_end) {
field_end = end;
}
if (space) {
if ((field_end == NULL) || (space < field_end)) {
field_end = space;
}
}
if (field_end) {
/* Closing '|' found. */
sep = strchr(field_begin, ':'); /* The lifetime field never includes a colon, whereas the third field always does. (RFC 4568) */
if (sep && (sep + 1 < field_end) && isdigit(*(sep + 1))) {
res |= (CRYPTO_KEY_MATERIAL_MKI << 24);
for (i = 1, *p = sep - 1; *p != field_begin; --(*p), i *= 10) {
val += ((**p) - '0') * i;
}
res |= ((val << 8) & 0x00ffff00); /* MKI_ID */
val = 0;
for (i = 1, *p = field_end - 1; *p != sep; --(*p), i *= 10) {
val += ((**p) - '0') * i;
}
res |= (val & 0x000000ff); /* MKI_SIZE */
} else if (isdigit(*(field_begin + 1)) && (field_begin + 2) && (*(field_begin + 2) == '^') && (field_begin + 3) && isdigit(*(field_begin + 3))) {
res |= (CRYPTO_KEY_MATERIAL_LIFETIME << 24);
val = ((uint32_t) (*(field_begin + 1) - '0')) << 8;
res |= val; /* LIFETIME base. */
val = 0;
for (i = 1, *p = field_end - 1; *p != (field_begin + 2); --(*p), i *= 10) {
val += ((**p) - '0') * i;
}
res |= (val & 0x000000ff); /* LIFETIME exponent. */
}
}
*p = field_end;
}
return res;
}
static switch_crypto_key_material_t* switch_core_media_crypto_append_key_material(
switch_core_session_t *session,
switch_crypto_key_material_t *tail,
switch_rtp_crypto_key_param_method_type_t method,
unsigned char raw_key[SWITCH_RTP_MAX_CRYPTO_LEN],
int raw_key_len,
const char *key_material,
int key_material_len,
uint64_t lifetime,
unsigned int mki_id,
unsigned int mki_size)
{
struct switch_crypto_key_material_s *new_key_material;
new_key_material = switch_core_session_alloc(session, (sizeof(*new_key_material)));
if (new_key_material == NULL) {
return NULL;
}
new_key_material->method = method;
memcpy(new_key_material->raw_key, raw_key, raw_key_len);
new_key_material->crypto_key = switch_core_session_strdup(session, key_material);
new_key_material->lifetime = lifetime;
new_key_material->mki_id = mki_id;
new_key_material->mki_size = mki_size;
new_key_material->next = tail;
return new_key_material;
}
/*
* Skip all space and return pointer to the '\0' terminator of the char string candidate to be a key-material
* or pointer to first ' ' in the candidate string.
*/
static const char* switch_core_media_crypto_find_key_material_candidate_end(const char *p)
{
const char *end;
switch_assert(p != NULL);
if (p) {
end = strchr(p, ' '); /* find the end of the continuous string of characters in the candidate string */
if (end == NULL)
end = p + strlen(p);
}
return end;
}
switch_status_t switch_core_media_add_crypto(switch_core_session_t *session, switch_secure_settings_t *ssec, switch_rtp_crypto_direction_t direction)
{
unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
switch_rtp_crypto_key_type_t type;
char *p;
const char *p, *delimit;
const char *key_material_begin;
const char *key_material_end; /* begin and end of the current key material candidate */
int method_len;
int keysalt_len;
const char *opts;
uint32_t opt_field; /* LIFETIME or MKI */
switch_rtp_crypto_key_param_method_type_t method = CRYPTO_KEY_PARAM_METHOD_INLINE;
uint64_t lifetime = 0;
uint16_t lifetime_base = 0;
uint16_t lifetime_exp = 0;
uint16_t mki_id = 0;
uint16_t mki_size = 0;
switch_crypto_key_material_t *key_material = NULL;
unsigned long *key_material_n = NULL;
bool multiple_keys = false;
const char *key_param;
p = strchr(key_str, ' ');
if (direction == SWITCH_RTP_CRYPTO_SEND || direction == SWITCH_RTP_CRYPTO_SEND_RTCP) {
key_param = ssec->local_crypto_key;
key_material = ssec->local_key_material_next;
key_material_n = &ssec->local_key_material_n;
} else {
key_param = ssec->remote_crypto_key;
key_material = ssec->remote_key_material_next;
key_material_n = &ssec->remote_key_material_n;
}
if (zstr(key_param)) {
goto no_crypto_found;
}
*key_material_n = 0;
p = strchr(key_param, ' ');
if (p && *p && *(p + 1)) {
p++;
@@ -1234,36 +1394,192 @@ switch_status_t switch_core_media_add_crypto(switch_secure_settings_t *ssec, con
type = switch_core_media_crypto_str2type(p);
if (type == CRYPTO_INVALID) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
goto bad;
goto bad_crypto;
}
p = strchr(p, ' ');
if (p && *p && *(p + 1)) {
p++;
if (strncasecmp(p, "inline:", 7)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
goto bad;
}
p += 7;
switch_b64_decode(p, (char *) key, sizeof(key));
if (direction == SWITCH_RTP_CRYPTO_SEND) {
memcpy(ssec->local_raw_key, key, SUITES[type].keylen);
} else {
memcpy(ssec->remote_raw_key, key, SUITES[type].keylen);
}
return SWITCH_STATUS_SUCCESS;
p = strchr(p, ' '); /* skip the crypto suite description */
if (p == NULL) {
goto bad_crypto;
}
do {
if (*key_material_n == SWITCH_CRYPTO_MKI_MAX) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Skipping excess of MKIs due to max number of suppoerted MKIs %d exceeded\n", SWITCH_CRYPTO_MKI_MAX);
break;
}
p = switch_strip_spaces((char*) p, 0);
if (p) {
key_material_begin = p;
key_material_end = switch_core_media_crypto_find_key_material_candidate_end(p);
/* Parsing the key material candidate within [begin, end). */
if ((delimit = strchr(p, ':')) == NULL) {
goto bad_error_parsing_near;
}
method_len = delimit - p;
if (strncasecmp(p, CRYPTO_KEY_PARAM_METHOD[CRYPTO_KEY_PARAM_METHOD_INLINE], method_len)) {
goto bad_key_param_method;
}
method = CRYPTO_KEY_PARAM_METHOD_INLINE;
/* Valid key-material found. Save as default key in secure_settings_s. */
p = delimit + 1; /* skip ':' */
if (!(p && *p && *(p + 1))) {
goto bad_keysalt;
}
/* Check if '|' is present in currently considered key-material. */
if ((opts = strchr(p, '|')) && (opts < key_material_end)) {
keysalt_len = opts - p;
} else {
keysalt_len = key_material_end - p;
}
if (keysalt_len > sizeof(key)) {
goto bad_keysalt_len;
}
switch_b64_decode(p, (char *) key, keysalt_len);
if (!multiple_keys) { /* First key becomes default (used in case no MKI is found). */
if (direction == SWITCH_RTP_CRYPTO_SEND) {
memcpy(ssec->local_raw_key, key, SUITES[type].keysalt_len);
} else {
memcpy(ssec->remote_raw_key, key, SUITES[type].keysalt_len);
}
multiple_keys = true;
}
p += keysalt_len;
if (p < key_material_end) { /* Parse LIFETIME or MKI. */
if (opts) { /* if opts != NULL then opts points to first '|' in current key-material cadidate */
lifetime = 0;
mki_id = 0;
mki_size = 0;
for (int i = 0; i < 2 && (*opts == '|'); ++i) {
opt_field = parse_lifetime_mki(&opts, key_material_end);
switch ((opt_field >> 24) & 0x3) {
case CRYPTO_KEY_MATERIAL_LIFETIME:
lifetime_base = ((opt_field & 0x00ffff00) >> 8) & 0xffff;
lifetime_exp = (opt_field & 0x000000ff) & 0xffff;
lifetime = pow(lifetime_base, lifetime_exp);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "LIFETIME found in %s, base %u exp %u\n", p, lifetime_base, lifetime_exp);
break;
case CRYPTO_KEY_MATERIAL_MKI:
mki_id = ((opt_field & 0x00ffff00) >> 8) & 0xffff;
mki_size = (opt_field & 0x000000ff) & 0xffff;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "MKI found in %s, id %u size %u\n", p, mki_id, mki_size);
break;
default:
goto bad_key_lifetime_or_mki;
}
}
if (mki_id == 0 && lifetime == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Bad MKI found in %s, (parsed as: id %u size %u lifetime base %u exp %u\n", p, mki_id, mki_size, lifetime_base, lifetime_exp);
return SWITCH_STATUS_FALSE;
} else if (mki_id == 0 || lifetime == 0) {
if (mki_id == 0) {
if (key_material)
goto bad_key_no_mki_index;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Skipping MKI due to empty index\n");
} else {
if (mki_size == 0)
goto bad_key_no_mki_size;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Skipping MKI due to empty lifetime\n");
}
continue;
}
}
if (key_material) {
if (mki_id == 0) {
goto bad_key_no_mki_index;
}
if (mki_size != key_material->mki_size) {
goto bad_key_mki_size;
}
}
key_material = switch_core_media_crypto_append_key_material(session, key_material, method, (unsigned char*) key,
SUITES[type].keysalt_len, (char*) key_material_begin, key_material_end - key_material_begin, lifetime, mki_id, mki_size);
*key_material_n = *key_material_n + 1;
}
}
} while ((p = switch_strip_spaces((char*) key_material_end, 0)) && (*p != '\0'));
if (direction == SWITCH_RTP_CRYPTO_SEND || direction == SWITCH_RTP_CRYPTO_SEND_RTCP) {
ssec->local_key_material_next = key_material;
} else {
ssec->remote_key_material_next = key_material;
}
return SWITCH_STATUS_SUCCESS;
}
bad:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error!\n");
no_crypto_found:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! No crypto to parse\n");
return SWITCH_STATUS_FALSE;
bad_error_parsing_near:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
return SWITCH_STATUS_FALSE;
bad_crypto:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid format of crypto attribute %s\n", key_param);
return SWITCH_STATUS_FALSE;
bad_keysalt:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid keysalt in the crypto attribute %s\n", key_param);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
return SWITCH_STATUS_FALSE;
bad_keysalt_len:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid keysalt length in the crypto attribute %s\n", key_param);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
return SWITCH_STATUS_FALSE;
bad_key_lifetime_or_mki:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid key param MKI or LIFETIME in the crypto attribute %s\n", key_param);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
return SWITCH_STATUS_FALSE;
bad_key_no_mki_index:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto invalid: multiple keys in a single crypto MUST all have MKI indices, %s\n", key_param);
return SWITCH_STATUS_FALSE;
bad_key_no_mki_size:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto invalid: MKI index with no MKI size in %s\n", key_param);
return SWITCH_STATUS_FALSE;
bad_key_mki_size:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto invalid: MKI sizes differ in %s\n", key_param);
return SWITCH_STATUS_FALSE;
bad_key_param_method:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid key param method type in %s\n", key_param);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(void) switch_core_media_set_rtp_session(switch_core_session_t *session, switch_media_type_t type, switch_rtp_t *rtp_session)
@@ -1342,19 +1658,16 @@ static void switch_core_session_apply_crypto(switch_core_session_t *session, swi
}
if (engine->ssec[engine->crypto_type].remote_crypto_key && switch_channel_test_flag(session->channel, CF_SECURE)) {
switch_core_media_add_crypto(&engine->ssec[engine->crypto_type], engine->ssec[engine->crypto_type].remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
if (switch_channel_get_variable(session->channel, "rtp_secure_media_mki"))
switch_core_media_add_crypto(session, &engine->ssec[engine->crypto_type], SWITCH_RTP_CRYPTO_SEND);
switch_core_media_add_crypto(session, &engine->ssec[engine->crypto_type], SWITCH_RTP_CRYPTO_RECV);
switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, 1,
engine->ssec[engine->crypto_type].crypto_type,
engine->ssec[engine->crypto_type].local_raw_key,
SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen);
switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, 1, &engine->ssec[engine->crypto_type]);
switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV,
engine->ssec[engine->crypto_type].crypto_tag,
engine->ssec[engine->crypto_type].crypto_type,
engine->ssec[engine->crypto_type].remote_raw_key,
SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen);
switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec[engine->crypto_type].crypto_tag, &engine->ssec[engine->crypto_type]);
switch_channel_set_variable(session->channel, varname, "true");
@@ -1476,7 +1789,7 @@ 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] in [%s]\n", SUITES[j].name, crypto);
if (switch_stristr(SUITES[j].name, crypto)) {
ctype = SUITES[j].type;
@@ -1504,8 +1817,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_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), engine->ssec[engine->crypto_type].crypto_type,
engine->ssec[engine->crypto_type].local_raw_key, SUITES[ctype].keylen);
switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), &engine->ssec[engine->crypto_type]);
}
if (a && b && !strncasecmp(a, b, 23)) {
@@ -1532,9 +1844,8 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio
if (switch_rtp_ready(engine->rtp_session) && switch_channel_test_flag(session->channel, CF_SECURE)) {
switch_core_media_add_crypto(&engine->ssec[engine->crypto_type], engine->ssec[engine->crypto_type].remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec[engine->crypto_type].crypto_tag,
engine->ssec[engine->crypto_type].crypto_type, engine->ssec[engine->crypto_type].remote_raw_key, SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen);
switch_core_media_add_crypto(session, &engine->ssec[engine->crypto_type], SWITCH_RTP_CRYPTO_RECV);
switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec[engine->crypto_type].crypto_tag, &engine->ssec[engine->crypto_type]);
}
got_crypto++;
@@ -13414,20 +13725,13 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
int idx = atoi(tmp);
a_engine->ssec[a_engine->crypto_type].local_crypto_key = switch_core_session_strdup(session, tmp);
switch_core_media_add_crypto(&a_engine->ssec[a_engine->crypto_type], a_engine->ssec[a_engine->crypto_type].local_crypto_key, SWITCH_RTP_CRYPTO_SEND);
switch_core_media_add_crypto(&a_engine->ssec[a_engine->crypto_type], a_engine->ssec[a_engine->crypto_type].remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
switch_core_media_add_crypto(session, &a_engine->ssec[a_engine->crypto_type],SWITCH_RTP_CRYPTO_SEND);
switch_core_media_add_crypto(session, &a_engine->ssec[a_engine->crypto_type],SWITCH_RTP_CRYPTO_RECV);
switch_channel_set_flag(smh->session->channel, CF_SECURE);
switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, idx,
a_engine->crypto_type,
a_engine->ssec[a_engine->crypto_type].local_raw_key,
SUITES[a_engine->crypto_type].keylen);
switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, idx, &a_engine->ssec[a_engine->crypto_type]);
switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_RECV,
a_engine->ssec[a_engine->crypto_type].crypto_tag,
a_engine->crypto_type,
a_engine->ssec[a_engine->crypto_type].remote_raw_key,
SUITES[a_engine->crypto_type].keylen);
switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, a_engine->ssec[a_engine->crypto_type].crypto_tag, &a_engine->ssec[a_engine->crypto_type]);
}
+174 -50
View File
@@ -2321,8 +2321,14 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
#ifdef ENABLE_SRTP
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
int stat = 0;
int sbytes = (int) rtcp_bytes;
int stat = srtp_protect_rtcp(rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_send_msg.header, &sbytes);
if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI]) {
stat = srtp_protect_rtcp(rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_send_msg.header, &sbytes);
} else {
stat = srtp_protect_rtcp_mki(rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_send_msg.header, &sbytes, 1, SWITCH_CRYPTO_MKI_INDEX);
}
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
@@ -3068,18 +3074,27 @@ static const char *dtls_state_names(dtls_state_t s)
return dtls_state_names_t[s];
}
#define dtls_set_state(_dtls, _state) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Changing %s DTLS state from %s to %s\n", rtp_type(rtp_session), dtls_state_names(_dtls->state), dtls_state_names(_state)); _dtls->new_state = 1; _dtls->last_state = _dtls->state; _dtls->state = _state
#define cr_keylen 16
#define cr_saltlen 14
#define cr_kslen 30
static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
{
X509 *cert;
switch_secure_settings_t ssec; /* Used just to wrap over params in a call to switch_rtp_add_crypto_key. */
int r = 0;
const switch_size_t cr_kslen = SUITES[AES_CM_128_HMAC_SHA1_80].keysalt_len;
const switch_size_t cr_saltlen = SUITES[AES_CM_128_HMAC_SHA1_80].salt_len;
const switch_size_t cr_keylen = cr_kslen - cr_saltlen;
uint8_t raw_key_data[cr_kslen * 2];
unsigned char local_key_buf[cr_kslen];
unsigned char remote_key_buf[cr_kslen];
memset(&ssec, 0, sizeof(ssec));
memset(&raw_key_data, 0, cr_kslen * 2 * sizeof(uint8_t));
memset(&local_key_buf, 0, cr_kslen * sizeof(unsigned char));
memset(&remote_key_buf, 0, cr_kslen * sizeof(unsigned char));
if ((dtls->type & DTLS_TYPE_SERVER)) {
r = 1;
} else if ((cert = SSL_get_peer_certificate(dtls->ssl))) {
@@ -3093,9 +3108,7 @@ static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
dtls_set_state(dtls, DS_FAIL);
return -1;
} else {
uint8_t raw_key_data[cr_kslen*2] = { 0 };
unsigned char *local_key, *remote_key, *local_salt, *remote_salt;
unsigned char local_key_buf[cr_kslen] = {0}, remote_key_buf[cr_kslen] = {0};
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "%s Fingerprint Verified.\n", rtp_type(rtp_session));
@@ -3122,18 +3135,20 @@ static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
local_salt = remote_salt + cr_saltlen;
}
memcpy(local_key_buf, local_key, cr_keylen);
memcpy(local_key_buf + cr_keylen, local_salt, cr_saltlen);
memcpy(&ssec.local_raw_key, local_key, cr_keylen);
memcpy(&ssec.local_raw_key + cr_keylen, local_salt, cr_saltlen);
memcpy(remote_key_buf, remote_key, cr_keylen);
memcpy(remote_key_buf + cr_keylen, remote_salt, cr_saltlen);
memcpy(&ssec.remote_raw_key, remote_key, cr_keylen);
memcpy(&ssec.remote_raw_key + cr_keylen, remote_salt, cr_saltlen);
ssec.crypto_type = AES_CM_128_HMAC_SHA1_80;
if (dtls == rtp_session->rtcp_dtls && rtp_session->rtcp_dtls != rtp_session->dtls) {
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_SEND_RTCP, 0, AES_CM_128_HMAC_SHA1_80, local_key_buf, cr_kslen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_RECV_RTCP, 0, AES_CM_128_HMAC_SHA1_80, remote_key_buf, cr_kslen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_SEND_RTCP, 0, &ssec);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_RECV_RTCP, 0, &ssec);
} else {
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_SEND, 0, AES_CM_128_HMAC_SHA1_80, local_key_buf, cr_kslen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_RECV, 0, AES_CM_128_HMAC_SHA1_80, remote_key_buf, cr_kslen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_SEND, 0, &ssec);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_RECV, 0, &ssec);
}
}
@@ -3815,15 +3830,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
}
SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session,
switch_rtp_crypto_direction_t direction,
uint32_t index, switch_rtp_crypto_key_type_t type, unsigned char *key, switch_size_t keylen)
SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session, switch_rtp_crypto_direction_t direction, uint32_t index, switch_secure_settings_t *ssec)
{
#ifndef ENABLE_SRTP
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "SRTP NOT SUPPORTED IN THIS BUILD!\n");
return SWITCH_STATUS_FALSE;
#else
switch_rtp_crypto_key_t *crypto_key;
srtp_policy_t *policy;
srtp_err_status_t stat;
@@ -3834,12 +3847,43 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
int idx = 0;
const char *var;
unsigned char b64_key[512] = "";
unsigned char *keysalt = NULL;
switch_size_t keysalt_len = 0;
switch_crypto_key_material_t *key_material = NULL;
unsigned long *key_material_n = NULL;
srtp_master_key_t **mkis = NULL;
srtp_master_key_t *mki = NULL;
int mki_idx = 0;
if (direction >= SWITCH_RTP_CRYPTO_MAX || keylen > SWITCH_RTP_MAX_CRYPTO_LEN) {
keysalt_len = SUITES[ssec->crypto_type].keysalt_len;
if (direction >= SWITCH_RTP_CRYPTO_MAX || keysalt_len > SWITCH_RTP_MAX_CRYPTO_LEN) {
return SWITCH_STATUS_FALSE;
}
switch_b64_encode(key, keylen, b64_key, sizeof(b64_key));
if (direction == SWITCH_RTP_CRYPTO_RECV_RTCP) {
direction = SWITCH_RTP_CRYPTO_RECV;
rtp_session->srtp_idx_rtcp = idx = 1;
} else if (direction == SWITCH_RTP_CRYPTO_SEND_RTCP) {
direction = SWITCH_RTP_CRYPTO_SEND;
rtp_session->srtp_idx_rtcp = idx = 1;
}
if (direction == SWITCH_RTP_CRYPTO_RECV) {
policy = &rtp_session->recv_policy[idx];
keysalt = ssec->remote_raw_key;
key_material = ssec->remote_key_material_next;
key_material_n = &ssec->remote_key_material_n;
} else {
policy = &rtp_session->send_policy[idx];
keysalt = ssec->local_raw_key;
key_material = ssec->local_key_material_next;
key_material_n = &ssec->local_key_material_n;
}
switch_b64_encode(keysalt, keysalt_len, b64_key, sizeof(b64_key));
if (switch_true(switch_core_get_variable("rtp_retain_crypto_keys"))) {
switch(direction) {
@@ -3862,23 +3906,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
crypto_key = switch_core_alloc(rtp_session->pool, sizeof(*crypto_key));
if (direction == SWITCH_RTP_CRYPTO_RECV_RTCP) {
direction = SWITCH_RTP_CRYPTO_RECV;
rtp_session->srtp_idx_rtcp = idx = 1;
} else if (direction == SWITCH_RTP_CRYPTO_SEND_RTCP) {
direction = SWITCH_RTP_CRYPTO_SEND;
rtp_session->srtp_idx_rtcp = idx = 1;
}
if (direction == SWITCH_RTP_CRYPTO_RECV) {
policy = &rtp_session->recv_policy[idx];
} else {
policy = &rtp_session->send_policy[idx];
}
crypto_key->type = type;
crypto_key->type = ssec->crypto_type;
crypto_key->index = index;
memcpy(crypto_key->key, key, keylen);
memcpy(crypto_key->keysalt, keysalt, keysalt_len);
crypto_key->next = rtp_session->crypto_keys[direction];
rtp_session->crypto_keys[direction] = crypto_key;
@@ -3948,7 +3978,68 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
break;
}
policy->key = (uint8_t *) crypto_key->key;
/* Setup the policy with MKI if they are used. Number of key materials must be positive to use MKI. */
if (key_material && (*key_material_n > 0)) {
if (direction == SWITCH_RTP_CRYPTO_RECV) {
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV_MKI] = 1;
} else {
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI] = 1;
}
/* key must be NULL for libsrtp to work correctly with MKI. */
policy->key = NULL;
/* Allocate array for MKIs. */
mkis = switch_core_alloc(rtp_session->pool, *key_material_n * sizeof(srtp_master_key_t*));
if (!mkis) {
return SWITCH_STATUS_FALSE;
}
/* Build array of MKIs. */
mki_idx = 0;
while (key_material && (mki_idx < *key_material_n)) {
if (key_material->mki_size < 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "MKI bad key size at MKI %d\n", mki_idx);
return SWITCH_STATUS_FALSE;
}
mki = switch_core_alloc(rtp_session->pool, sizeof(srtp_master_key_t));
if (!mki) {
return SWITCH_STATUS_FALSE;
}
/* Setup MKI. */
mki->mki_id = switch_core_alloc(rtp_session->pool, sizeof(key_material->mki_size));
if (!mki->mki_id) {
return SWITCH_STATUS_FALSE;
}
mki->key = switch_core_alloc(rtp_session->pool, keysalt_len);
if (!mki->key) {
return SWITCH_STATUS_FALSE;
}
memcpy(mki->mki_id, &key_material->mki_id, key_material->mki_size);
mki->mki_size = key_material->mki_size;
memcpy(mki->key, key_material->raw_key, keysalt_len);
mkis[mki_idx] = mki;
key_material = key_material->next;
++mki_idx;
}
/* And pass the array of MKIs to libsrtp. */
policy->keys = mkis;
policy->num_master_keys = mki_idx;
} else {
policy->key = (uint8_t *) crypto_key->keysalt;
}
policy->next = NULL;
policy->window_size = 1024;
@@ -3969,8 +4060,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
}
if (status == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Activating %s Secure %s RECV\n",
rtp_type(rtp_session), idx ? "RTCP" : "RTP");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Activating %s Secure %s RECV%s\n",
rtp_type(rtp_session), idx ? "RTCP" : "RTP", rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV_MKI] ? " (with MKI)" : "");
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] = 1;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
@@ -3991,8 +4082,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
}
if (status == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Activating %s Secure %s SEND\n",
rtp_type(rtp_session), idx ? "RTCP" : "RTP");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Activating %s Secure %s SEND%s\n",
rtp_type(rtp_session), idx ? "RTCP" : "RTP", rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI] ? " (with MKI)" : "");
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND] = 1;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error allocating SRTP [%d]\n", stat);
@@ -5780,8 +5871,13 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
int sbytes = (int) *bytes;
srtp_err_status_t stat = 0;
if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV_MKI]) {
stat = srtp_unprotect_rtcp(rtp_session->recv_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_recv_msg_p->header, &sbytes);
} else {
stat = srtp_unprotect_rtcp_mki(rtp_session->recv_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_recv_msg_p->header, &sbytes, 1);
}
if ((stat = srtp_unprotect_rtcp(rtp_session->recv_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_recv_msg_p->header, &sbytes))) {
if (stat) {
//++rtp_session->srtp_errs[rtp_session->srtp_idx_rtp]++;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "RTCP UNPROTECT ERR\n");
} else {
@@ -5975,7 +6071,14 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
}
if (!(*flags & SFF_PLC) && rtp_session->recv_ctx[rtp_session->srtp_idx_rtp]) {
stat = srtp_unprotect(rtp_session->recv_ctx[rtp_session->srtp_idx_rtp], &rtp_session->recv_msg.header, &sbytes);
stat = 0;
if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV_MKI]) {
stat = srtp_unprotect(rtp_session->recv_ctx[rtp_session->srtp_idx_rtp], &rtp_session->recv_msg.header, &sbytes);
} else {
stat = srtp_unprotect_mki(rtp_session->recv_ctx[rtp_session->srtp_idx_rtp], &rtp_session->recv_msg.header, &sbytes, 1);
}
if (rtp_session->flags[SWITCH_RTP_FLAG_NACK] && stat == srtp_err_status_replay_fail) {
/* false alarm nack */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "REPLAY ERR, FALSE NACK\n");
@@ -6743,7 +6846,13 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
srtp_err_status_t stat = 0;
if ((stat = srtp_unprotect_rtcp(rtp_session->recv_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_recv_msg_p->header, &sbytes))) {
if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV_MKI]) {
stat = srtp_unprotect_rtcp(rtp_session->recv_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_recv_msg_p->header, &sbytes);
} else {
stat = srtp_unprotect_rtcp_mki(rtp_session->recv_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_recv_msg_p->header, &sbytes, 1);
}
if (stat) {
//++rtp_session->srtp_errs[rtp_session->srtp_idx_rtp]++;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "RTCP UNPROTECT ERR\n");
} else {
@@ -7192,8 +7301,15 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
#ifdef ENABLE_SRTP
if (switch_rtp_test_flag(other_rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
int stat = 0;
int sbytes = (int) rtcp_bytes;
int stat = srtp_protect_rtcp(other_rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &other_rtp_session->rtcp_send_msg.header, &sbytes);
if (!other_rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI]) {
stat = srtp_protect_rtcp(other_rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &other_rtp_session->rtcp_send_msg.header, &sbytes);
} else {
stat = srtp_protect_rtcp_mki(other_rtp_session->send_ctx[other_rtp_session->srtp_idx_rtcp], &other_rtp_session->rtcp_send_msg.header, &sbytes, 1, SWITCH_CRYPTO_MKI_INDEX);
}
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
}
@@ -8235,8 +8351,11 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
}
}
stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &send_msg->header, &sbytes);
if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI]) {
stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &send_msg->header, &sbytes);
} else {
stat = srtp_protect_mki(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &send_msg->header, &sbytes, 1, SWITCH_CRYPTO_MKI_INDEX);
}
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR,
@@ -8820,7 +8939,12 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_write_raw(switch_rtp_t *rtp_session,
}
}
stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->write_msg.header, &sbytes);
if (!rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND_MKI]) {
stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->write_msg.header, &sbytes);
} else {
stat = srtp_protect_mki(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &rtp_session->write_msg.header, &sbytes, 1, SWITCH_CRYPTO_MKI_INDEX);
}
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP protection failed with code %d\n", stat);
}
+3 -2
View File
@@ -955,12 +955,13 @@ SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_size_t) switch_b64_decode(char *in, char *out, switch_size_t olen)
SWITCH_DECLARE(switch_size_t) switch_b64_decode(const char *in, char *out, switch_size_t olen)
{
char l64[256];
int b = 0, c, l = 0, i;
char *ip, *op = out;
const char *ip;
char *op = out;
size_t ol = 0;
for (i = 0; i < 256; i++) {