Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for cryptex #511

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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 @@ -333,6 +333,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 */
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
/**< 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 @@ -149,6 +149,7 @@ typedef struct srtp_stream_ctx_t_ {
int *enc_xtn_hdr;
int enc_xtn_hdr_count;
uint32_t pending_roc;
unsigned int use_cryptex;
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
struct srtp_stream_ctx_t_ *next; /* linked list of streams */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next was removed, I guess this slipped in while merging ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There have been a lot of changes in main, are you sure the merge went well ? All builds are failing.
Also the input buffer to the protect/unprotect functions is now const, not sure you should just cast that away and move the memory around.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think I have been too optimistic about my rebasing 😅

Wil try to get a look next week

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I had a quick attempt a few weeks ago and understood that this was not an easy merge :( . Let me know if you want to discuss anything.

} strp_stream_ctx_t_;

Expand Down
241 changes: 208 additions & 33 deletions srtp/srtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,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 @@ -548,7 +550,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 @@ -1694,6 +1696,9 @@ 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;
uint32_t xtn_hdr_profile_and_value = 0;

debug_print0(mod_srtp, "function srtp_protect_aead");

Expand Down Expand Up @@ -1723,10 +1728,41 @@ 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) {
/* Change profiles by cryptex values */
if (xtn_profile_specific == 0xbede) {
xtn_hdr_profile_and_value = htonl(0xc0de << 16 | xtn_hdr_length);
} else if (xtn_profile_specific == 0x1000) {
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
xtn_hdr_profile_and_value = htonl(0xc2de << 16 | xtn_hdr_length);
} else {
return srtp_err_status_parse_err;
}
/* Get CSRCs block position or profile if no CSRCs */
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Move CSRCS so block is contiguous with extension header block */
for (unsigned char i = hdr->cc; i > 0; --i)
csrcs[i] = csrcs[i - 1];
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
/* Move profile and length before the CSRCs */
csrcs[0] = xtn_hdr_profile_and_value;
/* Start encrypting in the CSRCS block new position */
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);
}
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
}
/* note: the passed size is without the auth tag */
if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len))
Expand Down Expand Up @@ -1808,6 +1844,17 @@ static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx,
if (status) {
return srtp_err_status_cipher_fail;
}

/* Restore CSRCs block before sending if using cryptex */
if (stream->use_cryptex && xtn_hdr && hdr->cc) {
/* Restore CSRCS to its original position */
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i] = csrcs[i + 1];
/* Restore extension header profile and length */
*(uint32_t *)xtn_hdr = xtn_hdr_profile_and_value;
}

/*
* If we're doing GCM, we need to get the tag
* and append that to the output
Expand Down Expand Up @@ -1855,6 +1902,10 @@ 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;
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
int xtn_profile_specific = 0;
unsigned int use_cryptex = 0;
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
uint32_t xtn_hdr_profile_and_value = 0;

debug_print0(mod_srtp, "function srtp_unprotect_aead");

Expand Down Expand Up @@ -1896,10 +1947,32 @@ 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) {
/* Get the 4 bytes of defined by profile and length */
xtn_hdr_profile_and_value = *(uint32_t *)xtn_hdr;
/* Get CSRCs block position or profile if no CSRCs */
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Move CSRCS so block is contiguous with extension header block */
for (unsigned char i = hdr->cc; i > 0; --i)
csrcs[i] = csrcs[i - 1];
/* Move defined by profile before the CSRCs block */
csrcs[0] = xtn_hdr_profile_and_value;
/* Start encrypting in the CSRCS block new position */
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 @@ -1955,6 +2028,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 cryptex 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 @@ -2056,6 +2145,9 @@ 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;
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
int xtn_profile_specific = 0;
uint32_t xtn_hdr_profile_and_value = 0;

debug_print0(mod_srtp, "function srtp_protect");

Expand Down Expand Up @@ -2165,10 +2257,42 @@ 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) {
/* Change profiles by cryptex values */
if (xtn_profile_specific == 0xbede) {
xtn_hdr_profile_and_value =
htonl(0xc0de << 16 | xtn_hdr_length);
} else if (xtn_profile_specific == 0x1000) {
xtn_hdr_profile_and_value =
htonl(0xc2de << 16 | xtn_hdr_length);
} else {
return srtp_err_status_parse_err;
}
/* Get CSRCs block position or profile if no CSRCs */
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Move CSRCS so block is contiguous with extension header block */
for (unsigned char i = hdr->cc; i > 0; --i)
Copy link
Contributor

@paulej paulej Aug 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to do this vs. memcpy() or memmove()? Loops are usually slower, but maybe this doesn't matter.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just thought it would be easier to review the change and check it was spec compliant, I can change it to memcpy or memmove if needed

csrcs[i] = csrcs[i - 1];
/* Move profile and length before the CSRCs */
csrcs[0] = xtn_hdr_profile_and_value;
/* Start encrypting in the CSRCS block new position */
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 @@ -2315,6 +2439,15 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
(unsigned int *)&enc_octet_len);
if (status)
return srtp_err_status_cipher_fail;
/* Restore CSRCs block before sending if using cryptex */
if (stream->use_cryptex && xtn_hdr && hdr->cc) {
/* Restore CSRCS to its original position */
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
for (unsigned char i = 0; i < hdr->cc; ++i)
csrcs[i] = csrcs[i + 1];
/* Restore extension header profile and length */
*(uint32_t *)xtn_hdr = xtn_hdr_profile_and_value;
}
}

/*
Expand Down Expand Up @@ -2386,6 +2519,10 @@ 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;
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
int xtn_profile_specific = 0;
unsigned int use_cryptex = 0;
murillo128 marked this conversation as resolved.
Show resolved Hide resolved
uint32_t xtn_hdr_profile_and_value = 0;

debug_print0(mod_srtp, "function srtp_unprotect");

Expand Down Expand Up @@ -2534,29 +2671,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 @@ -2618,6 +2732,51 @@ 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) {
/* Get the 4 bytes of defined by profile and length */
xtn_hdr_profile_and_value = *(uint32_t *)xtn_hdr;
/* Get CSRCs block position or profile if no CSRCs */
uint32_t *csrcs = (uint32_t *)hdr + uint32s_in_rtp_header;
/* Move CSRCS so block is contiguous with extension header block */
for (unsigned char i = hdr->cc; i > 0; --i)
csrcs[i] = csrcs[i - 1];
/* Move defined by profile before the CSRCs block */
csrcs[0] = xtn_hdr_profile_and_value;
/* Start encrypting in the CSRCS block new position */
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 @@ -2650,6 +2809,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 cryptex 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