Skip to content

Commit

Permalink
add test for ROC mіsmatch
Browse files Browse the repository at this point in the history
illustrating the reason why one should carefully pick the initial
sequence number low enough to avoid a rollover.

See
  https://webrtc-review.googlesource.com/c/src/+/358360
  • Loading branch information
fippo committed Sep 30, 2024
1 parent 2de20dd commit 609f579
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 4 deletions.
2 changes: 1 addition & 1 deletion format.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ done
m=`git ls-files -m`
if [ -n "$m" ]; then
v=`$CLANG_FORMAT -version`
echo "Fromatting required when checking with $v"
echo "Formatting required when checking with $v"
echo
echo "The following files required formatting:"
for f in $m; do
Expand Down
108 changes: 105 additions & 3 deletions test/srtp_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ srtp_err_status_t srtp_test_get_roc(void);

srtp_err_status_t srtp_test_set_receiver_roc(void);

srtp_err_status_t srtp_test_roc_mismatch(void);

srtp_err_status_t srtp_test_set_sender_roc(void);

double srtp_bits_per_second(size_t msg_len_octets, const srtp_policy_t *policy);
Expand Down Expand Up @@ -841,6 +843,14 @@ int main(int argc, char *argv[])
exit(1);
}

printf("testing srtp_test_roc_mismatch()...");
if (srtp_test_roc_mismatch() == srtp_err_status_ok) {
printf("passed\n");
} else {
printf("failed\n");
exit(1);
}

printf("testing srtp_test_set_sender_roc()...");
if (srtp_test_set_sender_roc() == srtp_err_status_ok) {
printf("passed\n");
Expand Down Expand Up @@ -4021,7 +4031,7 @@ srtp_err_status_t srtp_test_out_of_order_after_rollover(void)
uint32_t i;
uint32_t stream_roc;

/* Create sender */
/* Create the sender */
memset(&sender_policy, 0, sizeof(sender_policy));
#ifdef GCM
srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtp);
Expand Down Expand Up @@ -4311,7 +4321,7 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets,
size_t protected_msg_len_octets_1;
size_t protected_msg_len_octets_2;

/* Create sender */
/* Create the sender */
memset(&sender_policy, 0, sizeof(sender_policy));
#ifdef GCM
srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtp);
Expand Down Expand Up @@ -4472,7 +4482,7 @@ static srtp_err_status_t test_set_sender_roc(uint16_t seq, uint32_t roc_to_set)
size_t msg_len_octets = 32;
size_t protected_msg_len_octets;

/* Create sender */
/* Create the sender */
memset(&sender_policy, 0, sizeof(sender_policy));
#ifdef GCM
srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtp);
Expand Down Expand Up @@ -4670,6 +4680,98 @@ srtp_err_status_t srtp_test_set_sender_roc(void)
return srtp_err_status_ok;
}

/* This test illustrates how the ROC can be mismatched between
* sender and receiver when a packets are lost before the initial
* sequence number wraparound. In a nutshell:
* - Sender encrypts sequence numbers 65535, 0, 1, ...
* - Receiver only receives 1 initially.
* In that state the receiver will assume the sender used ROC=0 to
* encrypt the packet with sequence number 0.
* This is a long-standing problem that is best avoided by a choice
* of initial sequence number in the lower half of the sequence number
* space.
*/
srtp_err_status_t srtp_test_roc_mismatch(void)
{
srtp_policy_t sender_policy;
srtp_t sender_session;

srtp_policy_t receiver_policy;
srtp_t receiver_session;

const uint32_t num_pkts = 3;
uint8_t *pkts[3];
size_t pkt_len_octets[3];

const uint16_t seq = 0xffff;
uint32_t i;

/* Create the sender */
memset(&sender_policy, 0, sizeof(sender_policy));
#ifdef GCM
srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtp);
srtp_crypto_policy_set_aes_gcm_128_16_auth(&sender_policy.rtcp);
sender_policy.key = test_key_gcm;
#else
srtp_crypto_policy_set_rtp_default(&sender_policy.rtp);
srtp_crypto_policy_set_rtcp_default(&sender_policy.rtcp);
sender_policy.key = test_key;
#endif
sender_policy.ssrc.type = ssrc_specific;
sender_policy.ssrc.value = 0xcafebabe;
sender_policy.window_size = 128;

CHECK_OK(srtp_create(&sender_session, &sender_policy));

/* Create the receiver */
memset(&receiver_policy, 0, sizeof(receiver_policy));
#ifdef GCM
srtp_crypto_policy_set_aes_gcm_128_16_auth(&receiver_policy.rtp);
srtp_crypto_policy_set_aes_gcm_128_16_auth(&receiver_policy.rtcp);
receiver_policy.key = test_key_gcm;
#else
srtp_crypto_policy_set_rtp_default(&receiver_policy.rtp);
srtp_crypto_policy_set_rtcp_default(&receiver_policy.rtcp);
receiver_policy.key = test_key;
#endif
receiver_policy.ssrc.type = ssrc_specific;
receiver_policy.ssrc.value = sender_policy.ssrc.value;
receiver_policy.window_size = 128;

CHECK_OK(srtp_create(&receiver_session, &receiver_policy));

/* Create and protect packets to get to get ROC == 1 */
for (i = 0; i < num_pkts; i++) {
pkts[i] = create_rtp_test_packet(64, sender_policy.ssrc.value,
(uint16_t)(seq + i), 0, false,
&pkt_len_octets[i], NULL);
CHECK_OK(
call_srtp_protect(sender_session, pkts[i], &pkt_len_octets[i], 0));
}

/* Decrypt in reverse order (1, 0, 65535) */
CHECK_RETURN(
call_srtp_unprotect(receiver_session, pkts[2], &pkt_len_octets[2]),
srtp_err_status_auth_fail);
CHECK_RETURN(
call_srtp_unprotect(receiver_session, pkts[1], &pkt_len_octets[1]),
srtp_err_status_auth_fail);
CHECK_OK(
call_srtp_unprotect(receiver_session, pkts[0], &pkt_len_octets[0]));
/* After decryption of the previous ROC rollover will work as expected */
CHECK_OK(
call_srtp_unprotect(receiver_session, pkts[1], &pkt_len_octets[1]));
CHECK_OK(
call_srtp_unprotect(receiver_session, pkts[2], &pkt_len_octets[2]));

for (i = 0; i < num_pkts; i++) {
free(pkts[i]);
}
CHECK_OK(srtp_dealloc(sender_session));
CHECK_OK(srtp_dealloc(receiver_session));
return srtp_err_status_ok;
}

/*
* srtp policy definitions - these definitions are used above
*/
Expand Down

0 comments on commit 609f579

Please sign in to comment.