diff options
author | Pascal Bühler <pabuhler@cisco.com> | 2017-05-02 09:26:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-02 09:26:45 +0200 |
commit | 5c50354c68b073583a0ef82639130565d85ef571 (patch) | |
tree | c46ab82402e91b1354c95c42b98f32888469ab06 /srtp | |
parent | cf18080ee5883014b3018e6a3ed7d36283af4f6b (diff) | |
parent | 1d76a867b9009c21416a179e5678b9bd430281e8 (diff) | |
download | libsrtp2-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.c | 217 |
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; +} |