Skip to content

Commit b06b4a2

Browse files
authored
Merge pull request #820 from pabuhler/rcc-unprotect-ssrc-collision
srtp: detect SSRC collisions on RCC unprotect
2 parents 2f82ec0 + 2e04a15 commit b06b4a2

2 files changed

Lines changed: 87 additions & 12 deletions

File tree

‎srtp/srtp.c‎

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3001,6 +3001,22 @@ srtp_err_status_t srtp_unprotect(srtp_t ctx,
30013001
rcc_carry = stream->rcc_mode != srtp_rcc_mode_none &&
30023002
(ntohs(hdr->seq) % stream->roc_tx_rate) == 0;
30033003

3004+
/*
3005+
* Verify that stream is for received traffic - this check will
3006+
* detect SSRC collisions, since a stream that appears in both
3007+
* srtp_protect() and srtp_unprotect() will fail this test in one of
3008+
* those functions.
3009+
*
3010+
* Skip it for the provisional template stream, which is not yet a
3011+
* real sender or receiver stream. RCC packets still have to run
3012+
* this check: deferring index estimation for ROC-carrying (and
3013+
* mode 3) packets must not also skip collision detection.
3014+
*/
3015+
if (!from_template && stream->direction == dir_srtp_sender) {
3016+
srtp_handle_event(ctx, stream, event_ssrc_collision);
3017+
return srtp_err_status_direction_mismatch;
3018+
}
3019+
30043020
if (from_template || rcc_carry || stream->rcc_mode == srtp_rcc_mode_3) {
30053021
/*
30063022
* set estimated packet index to sequence number from header,
@@ -3009,18 +3025,6 @@ srtp_err_status_t srtp_unprotect(srtp_t ctx,
30093025
est = (srtp_xtd_seq_num_t)ntohs(hdr->seq);
30103026
delta = (int)est;
30113027
} else {
3012-
/*
3013-
* Verify that stream is for received traffic - this check will
3014-
* detect SSRC collisions, since a stream that appears in both
3015-
* srtp_protect() and srtp_unprotect() will fail this test in one of
3016-
* those functions.
3017-
*
3018-
*/
3019-
if (stream->direction == dir_srtp_sender) {
3020-
srtp_handle_event(ctx, stream, event_ssrc_collision);
3021-
return srtp_err_status_direction_mismatch;
3022-
}
3023-
30243028
status = srtp_get_est_pkt_index(hdr, stream, &est, &delta);
30253029

30263030
if (status && (status != srtp_err_status_pkt_idx_adv)) {

‎test/rcc_test.c‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,27 @@ static void rcc_roundtrip(srtp_t snd, srtp_t rcv, uint16_t seq, const char *msg)
165165
CHECK_BUFFER_EQUAL(dec, pkt, len);
166166
}
167167

168+
/*
169+
* Protect a packet on policy, then try to unprotect it on the same session.
170+
* After srtp_protect() the stream is a sender, so unprotect must report an
171+
* SSRC collision rather than decrypting the packet.
172+
*/
173+
static void rcc_sender_must_reject_unprotect(srtp_policy_t policy, uint16_t seq)
174+
{
175+
srtp_t sess;
176+
uint8_t pkt[256], enc[256], dec[256];
177+
size_t len, enc_len, dec_len;
178+
179+
CHECK_OK(srtp_create(&sess, policy));
180+
len = make_rtp(pkt, seq, "sender unprotect");
181+
enc_len = sizeof(enc);
182+
CHECK_OK(srtp_protect(sess, pkt, len, enc, &enc_len, 0));
183+
dec_len = sizeof(dec);
184+
CHECK_RETURN(srtp_unprotect(sess, enc, enc_len, dec, &dec_len),
185+
srtp_err_status_direction_mismatch);
186+
CHECK_OK(srtp_dealloc(sess));
187+
}
188+
168189
/* advance the sender's ROC to 1 by walking the sequence number past a wrap */
169190
static void advance_sender_roc(srtp_t snd)
170191
{
@@ -660,6 +681,36 @@ static void rcc_mode2_carry_out_of_order_keeps_window(void)
660681
CHECK_OK(srtp_shutdown());
661682
}
662683

684+
/*
685+
* An RCC-enabled sender stream must still reject unprotect as an SSRC
686+
* collision. ROC-carrying packets (and every mode-3 packet) used to skip
687+
* that check because their index is estimated later.
688+
*/
689+
static void rcc_mode2_sender_rejects_unprotect(void)
690+
{
691+
srtp_policy_t p;
692+
693+
CHECK_OK(srtp_init());
694+
create_cm_rcc_policy(&p, srtp_rcc_mode_2, 1);
695+
/* R == 1: every packet carries the ROC */
696+
rcc_sender_must_reject_unprotect(p, 4);
697+
srtp_policy_destroy(p);
698+
CHECK_OK(srtp_shutdown());
699+
}
700+
701+
static void rcc_mode1_sender_rejects_unprotect(void)
702+
{
703+
srtp_policy_t p;
704+
705+
CHECK_OK(srtp_init());
706+
create_cm_rcc_policy(&p, srtp_rcc_mode_1, 4);
707+
/* seq 0 is ROC-carrying; seq 1 is untagged. Both must collide. */
708+
rcc_sender_must_reject_unprotect(p, 0);
709+
rcc_sender_must_reject_unprotect(p, 1);
710+
srtp_policy_destroy(p);
711+
CHECK_OK(srtp_shutdown());
712+
}
713+
663714
#ifdef GCM
664715
/*
665716
* AES-GCM round trips (mode 3, RFC 7714 layout)
@@ -977,6 +1028,20 @@ static void rcc_gcm_mode3_carry_replay_rejected(void)
9771028
srtp_policy_destroy(rp);
9781029
CHECK_OK(srtp_shutdown());
9791030
}
1031+
1032+
static void rcc_gcm_mode3_sender_rejects_unprotect(void)
1033+
{
1034+
srtp_policy_t p;
1035+
1036+
CHECK_OK(srtp_init());
1037+
create_gcm_rcc_policy(&p, srtp_rcc_mode_3, 4);
1038+
/* seq 0 carries the ROC; seq 1 does not. Mode 3 skipped the check on
1039+
* both. */
1040+
rcc_sender_must_reject_unprotect(p, 0);
1041+
rcc_sender_must_reject_unprotect(p, 1);
1042+
srtp_policy_destroy(p);
1043+
CHECK_OK(srtp_shutdown());
1044+
}
9801045
#endif /* GCM */
9811046

9821047
TEST_LIST = {
@@ -1000,6 +1065,10 @@ TEST_LIST = {
10001065
{ "rcc_mode2_carry_replay_rejected()", rcc_mode2_carry_replay_rejected },
10011066
{ "rcc_mode2_carry_out_of_order_keeps_window()",
10021067
rcc_mode2_carry_out_of_order_keeps_window },
1068+
{ "rcc_mode2_sender_rejects_unprotect()",
1069+
rcc_mode2_sender_rejects_unprotect },
1070+
{ "rcc_mode1_sender_rejects_unprotect()",
1071+
rcc_mode1_sender_rejects_unprotect },
10031072
#ifdef GCM
10041073
{ "rcc_gcm_mode2_rejected_at_create()", rcc_gcm_mode2_rejected_at_create },
10051074
{ "rcc_gcm_mode3_basic_roundtrip()", rcc_gcm_mode3_basic_roundtrip },
@@ -1014,6 +1083,8 @@ TEST_LIST = {
10141083
rcc_gcm_mode3_wildcard_inbound_late_join },
10151084
{ "rcc_gcm_mode3_carry_replay_rejected()",
10161085
rcc_gcm_mode3_carry_replay_rejected },
1086+
{ "rcc_gcm_mode3_sender_rejects_unprotect()",
1087+
rcc_gcm_mode3_sender_rejects_unprotect },
10171088
#endif
10181089
{ 0 }
10191090
};

0 commit comments

Comments
 (0)