TT#42500 fix only one crypto suite being offered.

We should offer all crypto suites that we support. If passing through
SDES, we should amend the list of crypto suites with all additional ones
that we support that weren't included in the received offer.

closes #577

Change-Id: I9b6c16e8eadecf01cdbc8043bd8361e0f683e456
changes/85/23185/3
Richard Fuchs 7 years ago
parent 135dfb73ae
commit cab9d895b2

@ -1014,9 +1014,13 @@ static int __init_stream(struct packet_stream *ps) {
if (MEDIA_ISSET(media, SDES)) {
for (GList *l = ps->sfds.head; l; l = l->next) {
struct stream_fd *sfd = l->data;
crypto_init(&sfd->crypto, &media->sdes_in.params);
struct crypto_params_sdes *cps = media->sdes_in.head
? media->sdes_in.head->data : NULL;
crypto_init(&sfd->crypto, cps ? &cps->params : NULL);
}
crypto_init(&ps->crypto, &media->sdes_out.params);
struct crypto_params_sdes *cps = media->sdes_out.head
? media->sdes_out.head->data : NULL;
crypto_init(&ps->crypto, cps ? &cps->params : NULL);
}
if (MEDIA_ISSET(media, DTLS) && !PS_ISSET(ps, FALLBACK_RTCP)) {
@ -1214,14 +1218,17 @@ static void __ice_offer(const struct sdp_ng_flags *flags, struct call_media *thi
static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_media *this,
struct call_media *other)
{
struct crypto_params *cp = &this->sdes_out.params,
*cp_in = &this->sdes_in.params;
//struct crypto_params *cp = &this->sdes_out.params,
//*cp_in = &this->sdes_in.params;
GQueue *cpq = &this->sdes_out;
GQueue *cpq_in = &this->sdes_in;
GQueue *offered_cpq = &other->sdes_in;
if (!flags)
return;
if (!this->protocol || !this->protocol->srtp || MEDIA_ISSET(this, PASSTHRU)) {
cp->crypto_suite = NULL;
crypto_params_sdes_queue_clear(cpq);
/* clear crypto for the this leg b/c we are in passthrough mode */
MEDIA_CLEAR(this, DTLS);
MEDIA_CLEAR(this, SDES);
@ -1279,43 +1286,136 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi
/* SDES parameters below */
/* for answer case, otherwise we default to one */
this->sdes_out.tag = cp_in->crypto_suite ? this->sdes_in.tag : 1;
if (other->sdes_in.params.crypto_suite) {
/* SRTP <> SRTP case, copy from other stream */
cp->session_params = cp_in->session_params;
crypto_params_copy(cp, &other->sdes_in.params, (flags->opmode == OP_OFFER) ? 1 : 0);
}
if (cp->crypto_suite)
goto apply_sdes_flags;
cp->crypto_suite = cp_in->crypto_suite;
if (!cp->crypto_suite)
cp->crypto_suite = &crypto_suites[0];
random_string((unsigned char *) cp->master_key,
cp->crypto_suite->master_key_len);
random_string((unsigned char *) cp->master_salt,
cp->crypto_suite->master_salt_len);
/* mki = mki_len = 0 */
cp->session_params.unencrypted_srtp = cp_in->session_params.unencrypted_srtp;
cp->session_params.unencrypted_srtcp = cp_in->session_params.unencrypted_srtcp;
cp->session_params.unauthenticated_srtp = cp_in->session_params.unauthenticated_srtp;
apply_sdes_flags:
if (flags->sdes_unencrypted_srtp && flags->opmode == OP_OFFER)
cp_in->session_params.unencrypted_srtp = cp->session_params.unencrypted_srtp = 1;
else if (flags->sdes_encrypted_srtp)
cp_in->session_params.unencrypted_srtp = cp->session_params.unencrypted_srtp = 0;
if (flags->sdes_unencrypted_srtcp && flags->opmode == OP_OFFER)
cp_in->session_params.unencrypted_srtcp = cp->session_params.unencrypted_srtcp = 1;
else if (flags->sdes_encrypted_srtcp)
cp_in->session_params.unencrypted_srtcp = cp->session_params.unencrypted_srtcp = 0;
if (flags->sdes_unauthenticated_srtp && flags->opmode == OP_OFFER)
cp_in->session_params.unauthenticated_srtp = cp->session_params.unauthenticated_srtp = 1;
else if (flags->sdes_authenticated_srtp)
cp_in->session_params.unauthenticated_srtp = cp->session_params.unauthenticated_srtp = 0;
// XXX tests:
// generate all offers
// copy offered suites
// amend offered suites
// ignore suites not supported
// params copy on answer
if (flags->opmode == OP_OFFER) {
if (!cpq->head) {
// generate a new set of params
// if we were offered some crypto suites, copy those first into our offer
unsigned int c_tag = 1; // tag for next crypto suite generated by us
unsigned long types_offered = 0;
// make sure our bit field is large enough
assert(num_crypto_suites <= sizeof(types_offered) * 8);
for (GList *l = offered_cpq->head; l; l = l->next) {
struct crypto_params_sdes *offered_cps = l->data;
struct crypto_params_sdes *cps = g_slice_alloc0(sizeof(*cps));
g_queue_push_tail(cpq, cps);
cps->tag = offered_cps->tag;
// our own offered tags will be higher than the ones we received
if (cps->tag >= c_tag)
c_tag = cps->tag + 1;
crypto_params_copy(&cps->params, &offered_cps->params, 1);
// we use a bit field to keep track of which types we've seen here
types_offered |= 1 << cps->params.crypto_suite->idx;
}
// generate crypto suite offers for any types that we haven't seen above
for (unsigned int i = 0; i < num_crypto_suites; i++) {
if ((types_offered & (1 << i)))
continue;
struct crypto_params_sdes *cps = g_slice_alloc0(sizeof(*cps));
g_queue_push_tail(cpq, cps);
cps->tag = c_tag++;
cps->params.crypto_suite = &crypto_suites[i];
random_string((unsigned char *) cps->params.master_key,
cps->params.crypto_suite->master_key_len);
random_string((unsigned char *) cps->params.master_salt,
cps->params.crypto_suite->master_salt_len);
/* mki = mki_len = 0 */
// XXX cps->params.session_params.unencrypted_srtp
// XXX = cp_in->session_params.unencrypted_srtp;
// XXX cps->params.session_params.unencrypted_srtcp
// XXX = cp_in->session_params.unencrypted_srtcp;
// XXX cps->params.session_params.unauthenticated_srtp
// XXX = cp_in->session_params.unauthenticated_srtp;
}
}
}
else {
// we pick the first supported crypto suite
struct crypto_params_sdes *cps = cpq->head ? cpq->head->data : NULL;
struct crypto_params_sdes *cps_in = cpq_in->head ? cpq_in->head->data : NULL;
struct crypto_params_sdes *offered_cps = offered_cpq->head ? offered_cpq->head->data : NULL;
if (offered_cps) {
// check if we can do SRTP<>SRTP passthrough. the crypto suite that was accepted
// must have been present in what was offered to us
for (GList *l = cpq_in->head; l; l = l->next) {
struct crypto_params_sdes *check_cps = l->data;
if (check_cps->params.crypto_suite == offered_cps->params.crypto_suite) {
cps_in = check_cps;
break;
}
}
}
if (cps_in && (!cps || cps->params.crypto_suite != cps_in->params.crypto_suite)) {
crypto_params_sdes_queue_clear(cpq);
cps = g_slice_alloc0(sizeof(*cps));
g_queue_push_tail(cpq, cps);
cps->tag = cps_in->tag;
cps->params.crypto_suite = cps_in->params.crypto_suite;
if (offered_cps && offered_cps->params.crypto_suite == cps->params.crypto_suite) {
// SRTP<>SRTP passthrough
cps->params.session_params = cps_in->params.session_params; // XXX verify
crypto_params_copy(&cps->params, &offered_cps->params, 1);
}
else {
random_string((unsigned char *) cps->params.master_key,
cps->params.crypto_suite->master_key_len);
random_string((unsigned char *) cps->params.master_salt,
cps->params.crypto_suite->master_salt_len);
/* mki = mki_len = 0 */
cps->params.session_params = cps_in->params.session_params;
// XXX cps->params.session_params.unencrypted_srtp
// XXX = cp_in->session_params.unencrypted_srtp;
// XXX cps->params.session_params.unencrypted_srtcp
// XXX = cp_in->session_params.unencrypted_srtcp;
// XXX cps->params.session_params.unauthenticated_srtp
// XXX = cp_in->session_params.unauthenticated_srtp;
}
}
}
// XXX if (cp->crypto_suite)
// XXX goto apply_sdes_flags; // XXX ?
// cp->crypto_suite = cp_in->crypto_suite;
// if (!cp->crypto_suite)
// cp->crypto_suite = &crypto_suites[0];
// random_string((unsigned char *) cp->master_key,
// cp->crypto_suite->master_key_len);
// random_string((unsigned char *) cp->master_salt,
// cp->crypto_suite->master_salt_len);
// /* mki = mki_len = 0 */
// cp->session_params.unencrypted_srtp = cp_in->session_params.unencrypted_srtp;
// cp->session_params.unencrypted_srtcp = cp_in->session_params.unencrypted_srtcp;
// cp->session_params.unauthenticated_srtp = cp_in->session_params.unauthenticated_srtp;
// XXXapply_sdes_flags:
// XXX if (flags->sdes_unencrypted_srtp && flags->opmode == OP_OFFER)
// XXX cp_in->session_params.unencrypted_srtp = cp->session_params.unencrypted_srtp = 1;
// XXX else if (flags->sdes_encrypted_srtp)
// XXX cp_in->session_params.unencrypted_srtp = cp->session_params.unencrypted_srtp = 0;
// XXX if (flags->sdes_unencrypted_srtcp && flags->opmode == OP_OFFER)
// XXX cp_in->session_params.unencrypted_srtcp = cp->session_params.unencrypted_srtcp = 1;
// XXX else if (flags->sdes_encrypted_srtcp)
// XXX cp_in->session_params.unencrypted_srtcp = cp->session_params.unencrypted_srtcp = 0;
// XXX if (flags->sdes_unauthenticated_srtp && flags->opmode == OP_OFFER)
// XXX cp_in->session_params.unauthenticated_srtp = cp->session_params.unauthenticated_srtp = 1;
// XXX else if (flags->sdes_authenticated_srtp)
// XXX cp_in->session_params.unauthenticated_srtp = cp->session_params.unauthenticated_srtp = 0;
skip_sdes:
;
@ -1637,9 +1737,12 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams,
SHARED_FLAG_RTCP_MUX | SHARED_FLAG_ASYMMETRIC | SHARED_FLAG_UNIDIRECTIONAL |
SHARED_FLAG_ICE | SHARED_FLAG_TRICKLE_ICE | SHARED_FLAG_ICE_LITE);
crypto_params_copy(&other_media->sdes_in.params, &sp->crypto, 1);
other_media->sdes_in.tag = sp->sdes_tag;
if (other_media->sdes_in.params.crypto_suite)
// steal the entire queue of offered crypto params
crypto_params_sdes_queue_clear(&other_media->sdes_in);
other_media->sdes_in = sp->sdes_params;
g_queue_init(&sp->sdes_params);
if (other_media->sdes_in.length)
MEDIA_SET(other_media, SDES);
}
@ -2053,8 +2156,8 @@ static void __call_free(void *p) {
while (c->medias.head) {
md = g_queue_pop_head(&c->medias);
crypto_params_cleanup(&md->sdes_in.params);
crypto_params_cleanup(&md->sdes_out.params);
crypto_params_sdes_queue_clear(&md->sdes_in);
crypto_params_sdes_queue_clear(&md->sdes_out);
g_queue_clear(&md->streams);
g_queue_clear(&md->endpoint_maps);
g_hash_table_destroy(md->codecs_recv);

@ -288,10 +288,9 @@ static void rtp_pt_free(void *p) {
static void sp_free(void *p) {
struct stream_params *s = p;
if (s->crypto.mki)
free(s->crypto.mki);
g_queue_clear_full(&s->rtp_payload_types, rtp_pt_free);
ice_candidates_free(&s->ice_candidates);
crypto_params_sdes_queue_clear(&s->sdes_params);
g_slice_free1(sizeof(*s), s);
}
static void streams_free(GQueue *q) {

@ -277,7 +277,7 @@ struct crypto_suite __crypto_suites[] = {
};
const struct crypto_suite *crypto_suites = __crypto_suites;
const int num_crypto_suites = G_N_ELEMENTS(__crypto_suites);
const unsigned int num_crypto_suites = G_N_ELEMENTS(__crypto_suites);
@ -726,8 +726,9 @@ void crypto_dump_keys(struct crypto_context *in, struct crypto_context *out) {
void crypto_init_main() {
struct crypto_suite *cs;
for (int i = 0; i < num_crypto_suites; i++) {
for (unsigned int i = 0; i < num_crypto_suites; i++) {
cs = &__crypto_suites[i];
cs->idx = i;
switch(cs->master_key_len) {
case 16:
cs->lib_cipher_ptr = EVP_aes_128_ecb();

@ -1037,7 +1037,7 @@ err1:
}
/* can return 1, 0 or -1 */
static int redis_hash_get_crypto_params(struct crypto_params *out, const struct redis_hash *h, const char *k) {
static int redis_hash_get_sdes_params1(struct crypto_params *out, const struct redis_hash *h, const char *k) {
str s;
int i;
const char *err;
@ -1078,6 +1078,31 @@ err:
rlog(LOG_ERR, "Crypto params error: %s", err);
return -1;
}
static int redis_hash_get_sdes_params(GQueue *out, const struct redis_hash *h, const char *k) {
char key[32], tagkey[32];
const char *kk = k;
unsigned int tag;
unsigned int iter = 0;
while (1) {
snprintf(tagkey, sizeof(tagkey), "%s_tag", kk);
if (redis_hash_get_unsigned(&tag, h, tagkey))
break;
struct crypto_params_sdes *cps = g_slice_alloc0(sizeof(cps));
cps->tag = tag;
int ret = redis_hash_get_sdes_params1(&cps->params, h, kk);
if (ret) {
g_slice_free1(sizeof(*cps), cps);
if (ret == 1)
return 0;
return -1;
}
snprintf(key, sizeof(key), "%s-%u", k, iter++);
kk = key;
}
return 0;
}
static int redis_sfds(struct call *c, struct redis_list *sfds) {
unsigned int i;
@ -1259,16 +1284,13 @@ static int json_medias(struct call *c, struct redis_list *medias, JsonReader *ro
med->logical_intf = get_logical_interface(NULL, med->desired_family, 0);
}
if (redis_hash_get_unsigned(&med->sdes_in.tag, rh, "sdes_in_tag"))
return -1;
if (redis_hash_get_unsigned(&med->sdes_out.tag, rh, "sdes_out_tag"))
return -1;
if (redis_hash_get_unsigned((unsigned int *) &med->media_flags, rh,
"media_flags"))
return -1;
if (redis_hash_get_crypto_params(&med->sdes_in.params, rh, "sdes_in") < 0)
if (redis_hash_get_sdes_params(&med->sdes_in, rh, "sdes_in") < 0)
return -1;
if (redis_hash_get_crypto_params(&med->sdes_out.params, rh, "sdes_out") < 0)
if (redis_hash_get_sdes_params(&med->sdes_out, rh, "sdes_out") < 0)
return -1;
json_build_list_cb(NULL, c, "payload_types", i, NULL, rbl_cb_plts_r, med, root_reader);
@ -1750,25 +1772,37 @@ err:
#define JSON_SET_SIMPLE_CSTR(a,d) JSON_SET_SIMPLE_LEN(a, strlen(d), d)
#define JSON_SET_SIMPLE_STR(a,d) JSON_SET_SIMPLE_LEN(a, (d)->len, (d)->s)
static int json_update_crypto_params(JsonBuilder *builder, const char *pref,
static int json_update_sdes_params(JsonBuilder *builder, const char *pref,
unsigned int unique_id,
const char *key, const struct crypto_params *p)
const char *k, GQueue *q)
{
char tmp[2048];
unsigned int iter = 0;
char keybuf[32];
const char *key = k;
if (!p->crypto_suite)
return -1;
for (GList *l = q->head; l; l = l->next) {
struct crypto_params_sdes *cps = l->data;
struct crypto_params *p = &cps->params;
JSON_SET_NSTRING_CSTR("%s-crypto_suite",key,p->crypto_suite->name);
JSON_SET_NSTRING_LEN("%s-master_key",key, sizeof(p->master_key), (char *) p->master_key);
JSON_SET_NSTRING_LEN("%s-master_salt",key, sizeof(p->master_salt), (char *) p->master_salt);
if (!p->crypto_suite)
return -1;
JSON_SET_NSTRING("%s_tag", key, "%u", cps->tag);
JSON_SET_NSTRING_CSTR("%s-crypto_suite",key,p->crypto_suite->name);
JSON_SET_NSTRING_LEN("%s-master_key",key, sizeof(p->master_key), (char *) p->master_key);
JSON_SET_NSTRING_LEN("%s-master_salt",key, sizeof(p->master_salt), (char *) p->master_salt);
JSON_SET_NSTRING("%s-unenc-srtp",key,"%i",p->session_params.unencrypted_srtp);
JSON_SET_NSTRING("%s-unenc-srtcp",key,"%i",p->session_params.unencrypted_srtcp);
JSON_SET_NSTRING("%s-unauth-srtp",key,"%i",p->session_params.unauthenticated_srtp);
JSON_SET_NSTRING("%s-unenc-srtp",key,"%i",p->session_params.unencrypted_srtp);
JSON_SET_NSTRING("%s-unenc-srtcp",key,"%i",p->session_params.unencrypted_srtcp);
JSON_SET_NSTRING("%s-unauth-srtp",key,"%i",p->session_params.unauthenticated_srtp);
if (p->mki) {
JSON_SET_NSTRING_LEN("%s-mki",key, p->mki_len, (char *) p->mki);
}
if (p->mki) {
JSON_SET_NSTRING_LEN("%s-mki",key, p->mki_len, (char *) p->mki);
snprintf(keybuf, sizeof(keybuf), "%s-%u", k, iter++);
key = keybuf;
}
return 0;
@ -1975,16 +2009,14 @@ char* redis_encode_json(struct call *c) {
JSON_SET_SIMPLE_STR("type",&media->type);
JSON_SET_SIMPLE_CSTR("protocol",media->protocol ? media->protocol->name : "");
JSON_SET_SIMPLE_CSTR("desired_family",media->desired_family ? media->desired_family->rfc_name : "");
JSON_SET_SIMPLE("sdes_in_tag","%u",media->sdes_in.tag);
JSON_SET_SIMPLE("sdes_out_tag","%u",media->sdes_out.tag);
JSON_SET_SIMPLE_STR("logical_intf",&media->logical_intf->name);
JSON_SET_SIMPLE("ptime","%i",media->ptime);
JSON_SET_SIMPLE("media_flags","%u",media->media_flags);
json_update_crypto_params(builder, "media", media->unique_id, "sdes_in",
&media->sdes_in.params);
json_update_crypto_params(builder, "media", media->unique_id, "sdes_out",
&media->sdes_out.params);
json_update_sdes_params(builder, "media", media->unique_id, "sdes_in",
&media->sdes_in);
json_update_sdes_params(builder, "media", media->unique_id, "sdes_out",
&media->sdes_out);
json_update_dtls_fingerprint(builder, "media", media->unique_id, &media->fingerprint);
}
json_builder_end_object (builder);

@ -1267,24 +1267,28 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl
goto error;
/* a=crypto */
attr = attr_get_by_id(&media->attributes, ATTR_CRYPTO);
if (attr) {
sp->crypto.crypto_suite = attr->u.crypto.crypto_suite;
sp->crypto.mki_len = attr->u.crypto.mki_len;
if (sp->crypto.mki_len) {
sp->crypto.mki = malloc(sp->crypto.mki_len);
memcpy(sp->crypto.mki, attr->u.crypto.mki, sp->crypto.mki_len);
GQueue *attrs = attr_list_get_by_id(&media->attributes, ATTR_CRYPTO);
for (GList *ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
attr = ll->data;
struct crypto_params_sdes *cps = g_slice_alloc0(sizeof(*cps));
g_queue_push_tail(&sp->sdes_params, cps);
cps->params.crypto_suite = attr->u.crypto.crypto_suite;
cps->params.mki_len = attr->u.crypto.mki_len;
if (cps->params.mki_len) {
cps->params.mki = malloc(cps->params.mki_len);
memcpy(cps->params.mki, attr->u.crypto.mki, cps->params.mki_len);
}
sp->sdes_tag = attr->u.crypto.tag;
assert(sizeof(sp->crypto.master_key) >= attr->u.crypto.master_key.len);
assert(sizeof(sp->crypto.master_salt) >= attr->u.crypto.salt.len);
memcpy(sp->crypto.master_key, attr->u.crypto.master_key.s,
cps->tag = attr->u.crypto.tag;
assert(sizeof(cps->params.master_key) >= attr->u.crypto.master_key.len);
assert(sizeof(cps->params.master_salt) >= attr->u.crypto.salt.len);
memcpy(cps->params.master_key, attr->u.crypto.master_key.s,
attr->u.crypto.master_key.len);
memcpy(sp->crypto.master_salt, attr->u.crypto.salt.s,
memcpy(cps->params.master_salt, attr->u.crypto.salt.s,
attr->u.crypto.salt.len);
sp->crypto.session_params.unencrypted_srtp = attr->u.crypto.unencrypted_srtp;
sp->crypto.session_params.unencrypted_srtcp = attr->u.crypto.unencrypted_srtcp;
sp->crypto.session_params.unauthenticated_srtp = attr->u.crypto.unauthenticated_srtp;
cps->params.session_params.unencrypted_srtp = attr->u.crypto.unencrypted_srtp;
cps->params.session_params.unencrypted_srtcp = attr->u.crypto.unencrypted_srtcp;
cps->params.session_params.unauthenticated_srtp = attr->u.crypto.unauthenticated_srtp;
}
/* a=sendrecv/sendonly/recvonly/inactive */
@ -1910,44 +1914,50 @@ static void insert_dtls(struct call_media *media, struct sdp_chopper *chop) {
chopper_append_c(chop, "\r\n");
}
static void insert_crypto(struct call_media *media, struct sdp_chopper *chop) {
static void insert_crypto1(struct call_media *media, struct sdp_chopper *chop, struct crypto_params_sdes *cps) {
char b64_buf[((SRTP_MAX_MASTER_KEY_LEN + SRTP_MAX_MASTER_SALT_LEN) / 3 + 1) * 4 + 4];
char *p;
int state = 0, save = 0, i;
struct crypto_params *cp = &media->sdes_out.params;
unsigned long long ull;
if (!cp->crypto_suite || !MEDIA_ISSET(media, SDES) || MEDIA_ISSET(media, PASSTHRU))
if (!cps->params.crypto_suite || !MEDIA_ISSET(media, SDES) || MEDIA_ISSET(media, PASSTHRU))
return;
p = b64_buf;
p += g_base64_encode_step((unsigned char *) cp->master_key,
cp->crypto_suite->master_key_len, 0,
p += g_base64_encode_step((unsigned char *) cps->params.master_key,
cps->params.crypto_suite->master_key_len, 0,
p, &state, &save);
p += g_base64_encode_step((unsigned char *) cp->master_salt,
cp->crypto_suite->master_salt_len, 0,
p += g_base64_encode_step((unsigned char *) cps->params.master_salt,
cps->params.crypto_suite->master_salt_len, 0,
p, &state, &save);
p += g_base64_encode_close(0, p, &state, &save);
// truncate trailing ==
while (p > b64_buf && p[-1] == '=')
p--;
chopper_append_c(chop, "a=crypto:");
chopper_append_printf(chop, "%u ", media->sdes_out.tag);
chopper_append_c(chop, cp->crypto_suite->name);
chopper_append_printf(chop, "%u ", cps->tag);
chopper_append_c(chop, cps->params.crypto_suite->name);
chopper_append_c(chop, " inline:");
chopper_append(chop, b64_buf, p - b64_buf);
if (cp->mki_len) {
if (cps->params.mki_len) {
ull = 0;
for (i = 0; i < cp->mki_len && i < sizeof(ull); i++)
ull |= (unsigned long long) cp->mki[cp->mki_len - i - 1] << (i * 8);
chopper_append_printf(chop, "|%llu:%u", ull, cp->mki_len);
for (i = 0; i < cps->params.mki_len && i < sizeof(ull); i++)
ull |= (unsigned long long) cps->params.mki[cps->params.mki_len - i - 1] << (i * 8);
chopper_append_printf(chop, "|%llu:%u", ull, cps->params.mki_len);
}
if (cp->session_params.unencrypted_srtp)
if (cps->params.session_params.unencrypted_srtp)
chopper_append_c(chop, " UNENCRYPTED_SRTP");
if (cp->session_params.unencrypted_srtcp)
if (cps->params.session_params.unencrypted_srtcp)
chopper_append_c(chop, " UNENCRYPTED_SRTCP");
if (cp->session_params.unauthenticated_srtp)
if (cps->params.session_params.unauthenticated_srtp)
chopper_append_c(chop, " UNAUTHENTICATED_SRTP");
chopper_append_c(chop, "\r\n");
}
static void insert_crypto(struct call_media *media, struct sdp_chopper *chop) {
for (GList *l = media->sdes_out.head; l; l = l->next)
insert_crypto1(media, chop, l->data);
}
/* called with call->master_lock held in W */

@ -232,8 +232,7 @@ struct stream_params {
struct endpoint rtcp_endpoint;
unsigned int consecutive_ports;
const struct transport_protocol *protocol;
struct crypto_params crypto;
unsigned int sdes_tag;
GQueue sdes_params; // slice-alloc'd
str direction[2];
sockfamily_t *desired_family;
struct dtls_fingerprint fingerprint;
@ -321,12 +320,7 @@ struct call_media {
struct ice_agent *ice_agent;
struct {
struct crypto_params params;
unsigned int tag;
} sdes_in,
sdes_out;
GQueue sdes_in, sdes_out;
struct dtls_fingerprint fingerprint; /* as received */
GQueue streams; /* normally RTP + RTCP */

@ -55,8 +55,9 @@ struct crypto_suite {
hash_func_rtcp hash_rtcp;
session_key_init_func session_key_init;
session_key_cleanup_func session_key_cleanup;
const char *dtls_profile_code;
//const char *dtls_profile_code; // unused
const void *lib_cipher_ptr;
unsigned int idx; // filled in during crypto_init_main()
};
struct crypto_session_params {
@ -75,6 +76,11 @@ struct crypto_params {
struct crypto_session_params session_params;
};
struct crypto_params_sdes {
struct crypto_params params;
unsigned int tag;
};
struct crypto_context {
struct crypto_params params;
@ -92,7 +98,7 @@ struct crypto_context {
extern const struct crypto_suite *crypto_suites;
extern const int num_crypto_suites;
extern const unsigned int num_crypto_suites;
@ -166,7 +172,8 @@ INLINE void crypto_params_copy(struct crypto_params *o, const struct crypto_para
}
INLINE void crypto_init(struct crypto_context *c, const struct crypto_params *p) {
crypto_cleanup(c);
crypto_params_copy(&c->params, p, 1);
if (p)
crypto_params_copy(&c->params, p, 1);
}
INLINE int crypto_params_cmp(const struct crypto_params *a, const struct crypto_params *b) {
if (a->crypto_suite != b->crypto_suite)
@ -185,6 +192,13 @@ INLINE int crypto_params_cmp(const struct crypto_params *a, const struct crypto_
return 1;
return 0;
}
INLINE void crypto_params_sdes_free(struct crypto_params_sdes *cps) {
crypto_params_cleanup(&cps->params);
g_slice_free1(sizeof(*cps), cps);
}
INLINE void crypto_params_sdes_queue_clear(GQueue *q) {
g_queue_clear_full(q, (GDestroyNotify) crypto_params_sdes_free);
}

@ -366,11 +366,19 @@ sub rtp_savp {
sub savp_crypto {
my ($sdp, $ctx, $ctx_o) = @_;
my @aa = $sdp =~ /[\r\n]a=crypto:(\d+) (\w+) inline:([\w\/+=]{40,})(?:\|(?:2\^(\d+)|(\d+)))?(?:\|(\d+):(\d+))?(?: (.*?))?[\r\n]/sig;
my @aa = $sdp =~ /[\r\n](?:a=crypto:(\d+) (\w+) inline:([\w\/+=]{40,})(?:\|(?:2\^(\d+)|(\d+)))?(?:\|(\d+):(\d+))?(?: (.*?))?|(m)=.*?)[\r\n]/sig;
@aa or die;
my $i = 0;
while (@aa >= 8) {
$$ctx[$i]{in}{crypto_suite} = $NGCP::Rtpclient::SRTP::crypto_suites{$aa[1]} or die;
my $i = -1;
my @done;
while (@aa >= 9) {
if (defined($aa[8]) && $aa[8] eq 'm') {
$i++;
next;
}
$i >= 0 or die;
$done[$i] and next;
$$ctx[$i]{in}{crypto_suite} = $NGCP::Rtpclient::SRTP::crypto_suites{$aa[1]} or next;
$$ctx[$i]{in}{crypto_tag} = $aa[0];
($$ctx[$i]{in}{rtp_master_key}, $$ctx[$i]{in}{rtp_master_salt})
= NGCP::Rtpclient::SRTP::decode_inline_base64($aa[2], $$ctx[$i]{in}{crypto_suite});
@ -382,8 +390,10 @@ sub savp_crypto {
($aa[7] || '') =~ /UNENCRYPTED_SRTCP/ and $$ctx[$i]{in}{unenc_srtcp} = 1;
($aa[7] || '') =~ /UNAUTHENTICATED_SRTP/ and $$ctx[$i]{in}{unauth_srtp} = 1;
$i++;
@aa = @aa[8 .. $#aa];
$done[$i] = 1;
}
continue {
@aa = @aa[9 .. $#aa];
}
}

Loading…
Cancel
Save