Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/srtp.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ typedef struct srtp_policy_t {
int *enc_xtn_hdr; /**< List of header ids to encrypt. */
int enc_xtn_hdr_count; /**< Number of entries in list of header */
/**< ids. */
unsigned int use_cryptex; /**< Encrypt header block and CSRCS with */
/**< cryptex. */
struct srtp_policy_t *next; /**< Pointer to next stream policy. */
} srtp_policy_t;

Expand Down
1 change: 1 addition & 0 deletions include/srtp_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ typedef struct srtp_stream_ctx_t_ {
int *enc_xtn_hdr;
int enc_xtn_hdr_count;
uint32_t pending_roc;
unsigned int use_cryptex;
struct srtp_stream_ctx_t_ *next; /* linked list of streams */
} strp_stream_ctx_t_;

Expand Down
218 changes: 182 additions & 36 deletions srtp/srtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ srtp_err_status_t srtp_stream_dealloc(srtp_stream_ctx_t *stream,
}

/*
* deallocate cipher, if it is not the same as that in template
*/
* deallocate cipher, if it is not the same as that in template
*/
if (template_session_keys &&
session_keys->rtp_cipher == template_session_keys->rtp_cipher) {
/* do nothing */
Expand Down Expand Up @@ -437,6 +437,8 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
str->enc_xtn_hdr_count = 0;
}

str->use_cryptex = p->use_cryptex;

return srtp_err_status_ok;
}

Expand Down Expand Up @@ -547,7 +549,7 @@ srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
/* copy information about extensions header encryption */
str->enc_xtn_hdr = stream_template->enc_xtn_hdr;
str->enc_xtn_hdr_count = stream_template->enc_xtn_hdr_count;

str->use_cryptex = stream_template->use_cryptex;
/* defensive coding */
str->next = NULL;
return srtp_err_status_ok;
Expand Down Expand Up @@ -878,7 +880,7 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp,
/* If RTP or RTCP have a key length > AES-128, assume matching kdf. */
/* TODO: kdf algorithm, master key length, and master salt length should
* be part of srtp_policy_t.
*/
*/
session_keys = &srtp->session_keys[current_mki_index];

/* initialize key limit to maximum value */
Expand Down Expand Up @@ -1698,6 +1700,8 @@ static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx,
srtp_hdr_xtnd_t *xtn_hdr = NULL;
unsigned int mki_size = 0;
uint8_t *mki_location = NULL;
int xtn_hdr_length = 0;
int xtn_profile_specific = 0;

debug_print0(mod_srtp, "function srtp_protect_aead");

Expand Down Expand Up @@ -1727,10 +1731,29 @@ static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx,
* extension, if present; otherwise, it starts after the last csrc,
* if any are present
*/
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;

/* Cryptex can only encrypt CSRCS if header extension is present*/
if (stream->use_cryptex && hdr->cc && !hdr->x) {
return srtp_err_status_parse_err;
}
if (hdr->x == 1) {
xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
enc_start += (ntohs(xtn_hdr->length) + 1);
xtn_hdr = (srtp_hdr_xtnd_t *)(uint32_t *)hdr + uint32s_in_rtp_header +
hdr->cc;
xtn_hdr_length = ntohs(xtn_hdr->length);
xtn_profile_specific = ntohs(xtn_hdr->profile_specific);
}
/* If no header extension is present cryptex has no effect */
if (stream->use_cryptex && hdr->x) {
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Move CSRCS so it is contiguos with extension header block */
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i + 1] = csrcs[i];
enc_start = csrcs + 1;
} else {
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
if (hdr->x == 1) {
enc_start += (xtn_hdr_length + 1);
}
}
/* note: the passed size is without the auth tag */
if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len))
Expand Down Expand Up @@ -1812,6 +1835,23 @@ static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx,
if (status) {
return srtp_err_status_cipher_fail;
}

if (stream->use_cryptex && xtn_hdr) {
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Restore CSRCS to its original position */
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i] = csrcs[i + 1];
/* Restore extension header and change profiles by crytex values*/
xtn_hdr->length = htons(xtn_hdr_length);
if (xtn_profile_specific == 0xbede) {
xtn_hdr->profile_specific = htons(0xc0de);
} else if (xtn_profile_specific == 0x1000) {
xtn_hdr->profile_specific = htons(0xc2de);
} else {
return srtp_err_status_parse_err;
}
}

/*
* If we're doing GCM, we need to get the tag
* and append that to the output
Expand Down Expand Up @@ -1859,6 +1899,9 @@ static srtp_err_status_t srtp_unprotect_aead(srtp_ctx_t *ctx,
int tag_len;
unsigned int aad_len;
srtp_hdr_xtnd_t *xtn_hdr = NULL;
int xtn_hdr_length = 0;
int xtn_profile_specific = 0;
unsigned int use_cryptex = 0;

debug_print0(mod_srtp, "function srtp_unprotect_aead");

Expand Down Expand Up @@ -1900,10 +1943,26 @@ static srtp_err_status_t srtp_unprotect_aead(srtp_ctx_t *ctx,
* extension, if present; otherwise, it starts after the last csrc,
* if any are present
*/
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
if (hdr->x == 1) {
xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
enc_start += (ntohs(xtn_hdr->length) + 1);
xtn_hdr = (srtp_hdr_xtnd_t *)(uint32_t *)hdr + uint32s_in_rtp_header +
hdr->cc;
xtn_hdr_length = ntohs(xtn_hdr->length);
xtn_profile_specific = ntohs(xtn_hdr->profile_specific);
}

/* Check if the profile is the one for cryptex */
if (xtn_profile_specific == 0xc0de || xtn_profile_specific == 0xc2de) {
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Move CSRCS so it is contiguos with extension header block */
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i + 1] = csrcs[i];
enc_start = csrcs + 1;
use_cryptex = 1;
} else {
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
if (hdr->x == 1) {
enc_start += (xtn_hdr_length + 1);
}
}
if (!((uint8_t *)enc_start <=
(uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size)))
Expand Down Expand Up @@ -1959,6 +2018,22 @@ static srtp_err_status_t srtp_unprotect_aead(srtp_ctx_t *ctx,
return status;
}

if (use_cryptex) {
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Restore CSRCS to its original position */
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i] = csrcs[i + 1];
/* Restore extension header and change profiles by crytex values*/
xtn_hdr->length = htons(xtn_hdr_length);
if (xtn_profile_specific == 0xc0de) {
xtn_hdr->profile_specific = htons(0xbede);
} else if (xtn_profile_specific == 0xc2de) {
xtn_hdr->profile_specific = htons(0x1000);
} else {
return srtp_err_status_parse_err;
}
}

if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) {
/*
* extensions header encryption RFC 6904
Expand Down Expand Up @@ -2060,6 +2135,8 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
srtp_session_keys_t *session_keys = NULL;
uint8_t *mki_location = NULL;
int advance_packet_index = 0;
int xtn_hdr_length = 0;
int xtn_profile_specific = 0;

debug_print0(mod_srtp, "function srtp_protect");

Expand Down Expand Up @@ -2169,10 +2246,28 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
* if we're not providing confidentiality, set enc_start to NULL
*/
if (stream->rtp_services & sec_serv_conf) {
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
/* Cryptex can only encrypt CSRCS if header extension is present*/
if (stream->use_cryptex && hdr->cc && !hdr->x) {
return srtp_err_status_parse_err;
}
if (hdr->x == 1) {
xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
enc_start += (ntohs(xtn_hdr->length) + 1);
xtn_hdr = (srtp_hdr_xtnd_t *)(uint32_t *)hdr +
uint32s_in_rtp_header + hdr->cc;
xtn_hdr_length = ntohs(xtn_hdr->length);
xtn_profile_specific = ntohs(xtn_hdr->profile_specific);
}
/* If no header extension is present cryptex has no effect */
if (stream->use_cryptex && hdr->x) {
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Move CSRCS so it is contiguos with extension header block */
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i + 1] = csrcs[i];
enc_start = csrcs + 1;
} else {
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
if (hdr->x == 1) {
enc_start += (xtn_hdr_length + 1);
}
}
/* note: the passed size is without the auth tag */
if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len))
Expand Down Expand Up @@ -2319,6 +2414,22 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
(unsigned int *)&enc_octet_len);
if (status)
return srtp_err_status_cipher_fail;

if (stream->use_cryptex && xtn_hdr) {
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Restore CSRCS to its original position */
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i] = csrcs[i + 1];
/* Restore extension header and change profiles by crytex values*/
xtn_hdr->length = htons(xtn_hdr_length);
if (xtn_profile_specific == 0xbede) {
xtn_hdr->profile_specific = htons(0xc0de);
} else if (xtn_profile_specific == 0x1000) {
xtn_hdr->profile_specific = htons(0xc2de);
} else {
return srtp_err_status_parse_err;
}
}
}

/*
Expand Down Expand Up @@ -2390,6 +2501,9 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx,
int advance_packet_index = 0;
uint32_t roc_to_set = 0;
uint16_t seq_to_set = 0;
int xtn_hdr_length = 0;
int xtn_profile_specific = 0;
unsigned int use_cryptex = 0;

debug_print0(mod_srtp, "function srtp_unprotect");

Expand Down Expand Up @@ -2538,29 +2652,6 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx,
est = be64_to_cpu(est << 16);
#endif

/*
* find starting point for decryption and length of data to be
* decrypted - the encrypted portion starts after the rtp header
* extension, if present; otherwise, it starts after the last csrc,
* if any are present
*
* if we're not providing confidentiality, set enc_start to NULL
*/
if (stream->rtp_services & sec_serv_conf) {
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
if (hdr->x == 1) {
xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
enc_start += (ntohs(xtn_hdr->length) + 1);
}
if (!((uint8_t *)enc_start <=
(uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size)))
return srtp_err_status_parse_err;
enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - mki_size -
((uint8_t *)enc_start - (uint8_t *)hdr));
} else {
enc_start = NULL;
}

/*
* if we're providing authentication, set the auth_start and auth_tag
* pointers to the proper locations; otherwise, set auth_start to NULL
Expand Down Expand Up @@ -2622,6 +2713,45 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx,
return srtp_err_status_auth_fail;
}

/*
* find starting point for decryption and length of data to be
* decrypted - the encrypted portion starts after the rtp header
* extension, if present; otherwise, it starts after the last csrc,
* if any are present
*
* if we're not providing confidentiality, set enc_start to NULL
*/
if (stream->rtp_services & sec_serv_conf) {
if (hdr->x == 1) {
xtn_hdr = (srtp_hdr_xtnd_t *)(uint32_t *)hdr +
uint32s_in_rtp_header + hdr->cc;
xtn_hdr_length = ntohs(xtn_hdr->length);
xtn_profile_specific = ntohs(xtn_hdr->profile_specific);
}

/* Check if the profile is the one for cryptex */
if (xtn_profile_specific == 0xc0de || xtn_profile_specific == 0xc2de) {
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Move CSRCS so it is contiguos with extension header block */
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i + 1] = csrcs[i];
enc_start = csrcs + 1;
use_cryptex = 1;
} else {
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
if (hdr->x == 1) {
enc_start += (xtn_hdr_length + 1);
}
}
if (!((uint8_t *)enc_start <=
(uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size)))
return srtp_err_status_parse_err;
enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - mki_size -
((uint8_t *)enc_start - (uint8_t *)hdr));
} else {
enc_start = NULL;
}

/*
* update the key usage limit, and check it to make sure that we
* didn't just hit either the soft limit or the hard limit, and call
Expand Down Expand Up @@ -2654,6 +2784,22 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx,
(uint8_t *)enc_start, &enc_octet_len);
if (status)
return srtp_err_status_cipher_fail;

if (use_cryptex) {
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Restore CSRCS to its original position */
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i] = csrcs[i + 1];
/* Restore extension header and change profiles by crytex values*/
xtn_hdr->length = htons(xtn_hdr_length);
if (xtn_profile_specific == 0xc0de) {
xtn_hdr->profile_specific = htons(0xbede);
} else if (xtn_profile_specific == 0xc2de) {
xtn_hdr->profile_specific = htons(0x1000);
} else {
return srtp_err_status_parse_err;
}
}
}

/*
Expand Down
Loading