aboutsummaryrefslogtreecommitdiff
path: root/srtp
diff options
context:
space:
mode:
authorPascal Bühler <pabuhler@cisco.com>2017-05-02 09:26:45 +0200
committerGitHub <noreply@github.com>2017-05-02 09:26:45 +0200
commit5c50354c68b073583a0ef82639130565d85ef571 (patch)
treec46ab82402e91b1354c95c42b98f32888469ab06 /srtp
parentcf18080ee5883014b3018e6a3ed7d36283af4f6b (diff)
parent1d76a867b9009c21416a179e5678b9bd430281e8 (diff)
downloadlibsrtp2-5c50354c68b073583a0ef82639130565d85ef571.tar.gz
Merge pull request #289 from ulfolsson/set_and_get_roc
Added support for set and get the roll-over-counter
Diffstat (limited to 'srtp')
-rw-r--r--srtp/srtp.c217
1 files changed, 195 insertions, 22 deletions
diff --git a/srtp/srtp.c b/srtp/srtp.c
index 3cc026a..c5909b9 100644
--- a/srtp/srtp.c
+++ b/srtp/srtp.c
@@ -559,10 +559,13 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
}
srtp_rdb_init(&str->rtcp_rdb);
str->allow_repeat_tx = stream_template->allow_repeat_tx;
-
+
/* set ssrc to that provided */
str->ssrc = ssrc;
+ /* reset pending ROC */
+ str->pending_roc = 0;
+
/* set direction and security services */
str->direction = stream_template->direction;
str->rtp_services = stream_template->rtp_services;
@@ -1218,6 +1221,9 @@ srtp_stream_init(srtp_stream_ctx_t *srtp,
/* set the SSRC value */
srtp->ssrc = htonl(p->ssrc.value);
+ /* reset pending ROC */
+ srtp->pending_roc = 0;
+
/* set the security service flags */
srtp->rtp_services = p->rtp.sec_serv;
srtp->rtcp_services = p->rtcp.sec_serv;
@@ -1545,6 +1551,110 @@ srtp_get_session_keys(srtp_stream_ctx_t *stream, uint8_t* hdr,
return NULL;
}
+static srtp_err_status_t
+srtp_estimate_index(srtp_rdbx_t *rdbx,
+ uint32_t roc,
+ srtp_xtd_seq_num_t *est,
+ srtp_sequence_number_t seq,
+ int *delta)
+{
+#ifdef NO_64BIT_MATH
+ uint32_t internal_pkt_idx_reduced;
+ uint32_t external_pkt_idx_reduced;
+ uint32_t internal_roc;
+ uint32_t roc_difference;
+#endif
+
+#ifdef NO_64BIT_MATH
+ *est = (srtp_xtd_seq_num_t)make64(roc >> 16, (roc << 16) | seq);
+ *delta = low32(est) - rdbx->index;
+#else
+ *est = (srtp_xtd_seq_num_t)(((uint64_t)roc) << 16) | seq;
+ *delta = (int)(*est - rdbx->index);
+#endif
+
+ if (*est > rdbx->index) {
+#ifdef NO_64BIT_MATH
+ internal_roc = (uint32_t)(rdbx->index >> 16);
+ roc_difference = roc - internal_roc;
+ if (roc_difference > 1) {
+ *delta = 0;
+ return srtp_err_status_pkt_idx_adv;
+ }
+
+ internal_pkt_idx_reduced = (uint32_t)(rdbx->index & 0xFFFF);
+ external_pkt_idx_reduced = (uint32_t)((roc_difference << 16) | seq);
+
+ if (external_pkt_idx_reduced - internal_pkt_idx_reduced >
+ seq_num_median) {
+ *delta = 0;
+ return srtp_err_status_pkt_idx_adv;
+ }
+#else
+ if (*est - rdbx->index > seq_num_median) {
+ *delta = 0;
+ return srtp_err_status_pkt_idx_adv;
+ }
+#endif
+ } else if (*est < rdbx->index) {
+#ifdef NO_64BIT_MATH
+
+ internal_roc = (uint32_t)(rdbx->index >> 16);
+ roc_difference = internal_roc - roc;
+ if (roc_difference > 1) {
+ *delta = 0;
+ return srtp_err_status_pkt_idx_adv;
+ }
+
+ internal_pkt_idx_reduced =
+ (uint32_t)((roc_difference << 16) | rdbx->index & 0xFFFF);
+ external_pkt_idx_reduced = (uint32_t)(seq);
+
+ if (internal_pkt_idx_reduced - external_pkt_idx_reduced >
+ seq_num_median) {
+ *delta = 0;
+ return srtp_err_status_pkt_idx_old;
+ }
+#else
+ if (rdbx->index - *est > seq_num_median) {
+ *delta = 0;
+ return srtp_err_status_pkt_idx_old;
+ }
+#endif
+ }
+
+ return srtp_err_status_ok;
+}
+
+static srtp_err_status_t
+srtp_get_est_pkt_index(srtp_hdr_t *hdr,
+ srtp_stream_ctx_t *stream,
+ srtp_xtd_seq_num_t *est,
+ int *delta)
+{
+ srtp_err_status_t result = srtp_err_status_ok;
+
+ if (stream->pending_roc) {
+ result = srtp_estimate_index(&stream->rtp_rdbx,
+ stream->pending_roc,
+ est,
+ ntohs(hdr->seq),
+ delta);
+ } else {
+ /* estimate packet index from seq. num. in header */
+ *delta = srtp_rdbx_estimate_index(&stream->rtp_rdbx,
+ est,
+ ntohs(hdr->seq));
+ }
+
+#ifdef NO_64BIT_MATH
+ debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(*est), low32(*est));
+#else
+ debug_print(mod_srtp, "estimated u_packet index: %016llx", *est);
+#endif
+ return result;
+}
+
/*
* This function handles outgoing SRTP packets while in AEAD mode,
* which currently supports AES-GCM encryption. All packets are
@@ -1914,6 +2024,7 @@ srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len,
unsigned int mki_size = 0;
srtp_session_keys_t *session_keys = NULL;
uint8_t* mki_location = NULL;
+ int advance_packet_index = 0;
debug_print(mod_srtp, "function srtp_protect", NULL);
@@ -2050,18 +2161,35 @@ srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len,
auth_tag = NULL;
}
- /*
- * estimate the packet index using the start of the replay window
- * and the sequence number from the header
- */
- delta = srtp_rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
- status = srtp_rdbx_check(&stream->rtp_rdbx, delta);
- if (status) {
- if (status != srtp_err_status_replay_fail || !stream->allow_repeat_tx)
- return status; /* we've been asked to reuse an index */
- }
- else
- srtp_rdbx_add_index(&stream->rtp_rdbx, delta);
+ /*
+ * estimate the packet index using the start of the replay window
+ * and the sequence number from the header
+ */
+ status = srtp_get_est_pkt_index(hdr,
+ stream,
+ &est,
+ &delta);
+
+ if (status && (status != srtp_err_status_pkt_idx_adv))
+ return status;
+
+ if (status == srtp_err_status_pkt_idx_adv)
+ advance_packet_index = 1;
+
+ if (advance_packet_index) {
+ srtp_rdbx_set_roc_seq(&stream->rtp_rdbx,
+ (uint32_t)(est >> 16),
+ (uint16_t)(est & 0xFFFF));
+ stream->pending_roc = 0;
+ srtp_rdbx_add_index(&stream->rtp_rdbx, 0);
+ } else {
+ status = srtp_rdbx_check(&stream->rtp_rdbx, delta);
+ if (status) {
+ if (status != srtp_err_status_replay_fail || !stream->allow_repeat_tx)
+ return status; /* we've been asked to reuse an index */
+ }
+ srtp_rdbx_add_index(&stream->rtp_rdbx, delta);
+ }
#ifdef NO_64BIT_MATH
debug_print2(mod_srtp, "estimated packet index: %08x%08x",
@@ -2215,6 +2343,7 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len,
srtp_hdr_xtnd_t *xtn_hdr = NULL;
unsigned int mki_size = 0;
srtp_session_keys_t *session_keys = NULL;
+ int advance_packet_index = 0;
debug_print(mod_srtp, "function srtp_unprotect", NULL);
@@ -2263,14 +2392,24 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len,
return srtp_err_status_no_ctx;
}
} else {
-
- /* estimate packet index from seq. num. in header */
- delta = srtp_rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
-
- /* check replay database */
- status = srtp_rdbx_check(&stream->rtp_rdbx, delta);
- if (status)
+ status = srtp_get_est_pkt_index(hdr,
+ stream,
+ &est,
+ &delta);
+
+ if (status && (status != srtp_err_status_pkt_idx_adv))
return status;
+
+ if (status == srtp_err_status_pkt_idx_adv) {
+ advance_packet_index = 1;
+ }
+
+ /* check replay database */
+ if (!advance_packet_index) {
+ status = srtp_rdbx_check(&stream->rtp_rdbx, delta);
+ if (status)
+ return status;
+ }
}
#ifdef NO_64BIT_MATH
@@ -2516,12 +2655,20 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len,
/* set stream (the pointer used in this function) */
stream = new_stream;
}
-
+
/*
* the message authentication function passed, so add the packet
* index into the replay database
*/
- srtp_rdbx_add_index(&stream->rtp_rdbx, delta);
+ if (advance_packet_index) {
+ srtp_rdbx_set_roc_seq(&stream->rtp_rdbx,
+ (uint32_t)(est >> 16),
+ (uint16_t)(est & 0xFFFF));
+ stream->pending_roc = 0;
+ srtp_rdbx_add_index(&stream->rtp_rdbx, 0);
+ } else {
+ srtp_rdbx_add_index(&stream->rtp_rdbx, delta);
+ }
/* decrease the packet length by the length of the auth tag */
*pkt_octet_len -= tag_len;
@@ -4474,3 +4621,29 @@ srtp_err_status_t srtp_install_log_handler(srtp_log_handler_func_t func, void *
}
return srtp_err_status_ok;
}
+
+srtp_err_status_t
+srtp_set_stream_roc(srtp_t session, uint32_t ssrc, uint32_t roc) {
+ srtp_stream_t stream;
+
+ stream = srtp_get_stream(session, htonl(ssrc));
+ if (stream == NULL)
+ return srtp_err_status_bad_param;
+
+ stream->pending_roc = roc;
+
+ return srtp_err_status_ok;
+}
+
+srtp_err_status_t
+srtp_get_stream_roc(srtp_t session, uint32_t ssrc, uint32_t *roc) {
+ srtp_stream_t stream;
+
+ stream = srtp_get_stream(session, htonl(ssrc));
+ if (stream == NULL)
+ return srtp_err_status_bad_param;
+
+ *roc = srtp_rdbx_get_roc(&stream->rtp_rdbx);
+
+ return srtp_err_status_ok;
+}