Skip to content

Commit 23d70f3

Browse files
committed
Properly support null crypto and null auth scenario
Currently, it is silently assumed that we always have master key provided, even when the policy says we don't use encryption and authentication. This results in streams with such policy to fail. Fix that by properly calculating the expected master key length by taking in account authentication type too. Correctly set expected key length for null crypto policy to 0. Do not assume we have HMAC if the policy is set to not have. Add a test case for null/null policy while at it. Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
1 parent 76f23aa commit 23d70f3

2 files changed

Lines changed: 213 additions & 11 deletions

File tree

srtp/srtp.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,7 @@ static inline size_t full_key_length(const srtp_cipher_type_t *cipher)
11761176
{
11771177
switch (cipher->id) {
11781178
case SRTP_NULL_CIPHER:
1179+
return 0;
11791180
case SRTP_AES_ICM_128:
11801181
return SRTP_AES_ICM_128_KEY_LEN_WSALT;
11811182
case SRTP_AES_ICM_192:
@@ -1191,6 +1192,19 @@ static inline size_t full_key_length(const srtp_cipher_type_t *cipher)
11911192
}
11921193
}
11931194

1195+
/* Get the key length that the application should supply for the given auth */
1196+
static inline int full_auth_key_length(const srtp_auth_type_t *auth)
1197+
{
1198+
switch (auth->id) {
1199+
case SRTP_NULL_AUTH:
1200+
return 0;
1201+
case SRTP_HMAC_SHA1:
1202+
return SRTP_AES_ICM_128_KEY_LEN_WSALT;
1203+
default:
1204+
return 0;
1205+
}
1206+
}
1207+
11941208
srtp_err_status_t srtp_get_session_keys(srtp_stream_ctx_t *stream,
11951209
size_t mki_index,
11961210
srtp_session_keys_t **session_keys)
@@ -1224,7 +1238,7 @@ srtp_err_status_t srtp_stream_init_keys(srtp_session_keys_t *session_keys,
12241238
srtp_err_status_t stat;
12251239
srtp_kdf_t kdf;
12261240
uint8_t tmp_key[MAX_SRTP_KEY_LEN];
1227-
size_t input_keylen, input_keylen_rtcp;
1241+
size_t input_keylen, full_keylen;
12281242
size_t kdf_keylen = 30, rtp_keylen, rtcp_keylen;
12291243
size_t rtp_base_key_len, rtp_salt_len;
12301244
size_t rtcp_base_key_len, rtcp_salt_len;
@@ -1252,9 +1266,17 @@ srtp_err_status_t srtp_stream_init_keys(srtp_session_keys_t *session_keys,
12521266
}
12531267

12541268
input_keylen = full_key_length(session_keys->rtp_cipher->type);
1255-
input_keylen_rtcp = full_key_length(session_keys->rtcp_cipher->type);
1256-
if (input_keylen_rtcp > input_keylen) {
1257-
input_keylen = input_keylen_rtcp;
1269+
full_keylen = full_auth_key_length(session_keys->rtp_auth->type);
1270+
if (full_keylen > input_keylen) {
1271+
input_keylen = full_keylen;
1272+
}
1273+
full_keylen = full_key_length(session_keys->rtcp_cipher->type);
1274+
if (full_keylen > input_keylen) {
1275+
input_keylen = full_keylen;
1276+
}
1277+
full_keylen = full_auth_key_length(session_keys->rtcp_auth->type);
1278+
if (full_keylen > input_keylen) {
1279+
input_keylen = full_keylen;
12581280
}
12591281

12601282
rtp_keylen = srtp_cipher_get_key_length(session_keys->rtp_cipher);
@@ -3713,8 +3735,7 @@ void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p)
37133735
*/
37143736

37153737
p->cipher_type = SRTP_NULL_CIPHER;
3716-
p->cipher_key_len =
3717-
SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */
3738+
p->cipher_key_len = 0;
37183739
p->auth_type = SRTP_NULL_AUTH;
37193740
p->auth_key_len = 0;
37203741
p->auth_tag_len = 0;

test/srtp_driver.c

Lines changed: 186 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ srtp_err_status_t srtp_validate(void);
6464

6565
srtp_err_status_t srtp_validate_mki(void);
6666

67-
srtp_err_status_t srtp_validate_null(void);
67+
srtp_err_status_t srtp_validate_null_sha1_80(void);
68+
69+
srtp_err_status_t srtp_validate_null_null(void);
6870

6971
srtp_err_status_t srtp_validate_cryptex(void);
7072

@@ -702,8 +704,17 @@ int main(int argc, char *argv[])
702704
}
703705

704706
printf("testing srtp_protect and srtp_unprotect against "
705-
"reference packet using null cipher and HMAC\n");
706-
if (srtp_validate_null() == srtp_err_status_ok) {
707+
"reference packet using null cipher and SHA1-80 HMAC\n");
708+
if (srtp_validate_null_sha1_80() == srtp_err_status_ok) {
709+
printf("passed\n\n");
710+
} else {
711+
printf("failed\n");
712+
exit(1);
713+
}
714+
715+
printf("testing srtp_protect and srtp_unprotect against "
716+
"reference packet using null cipher and null HMAC\n");
717+
if (srtp_validate_null_null() == srtp_err_status_ok) {
707718
printf("passed\n\n");
708719
} else {
709720
printf("failed\n");
@@ -2614,13 +2625,13 @@ srtp_err_status_t srtp_validate_mki(void)
26142625
}
26152626

26162627
/*
2617-
* srtp_validate_null() verifies the correctness of libsrtp by comparing
2628+
* srtp_validate_null_sha1_80() verifies the correctness of libsrtp by comparing
26182629
* some computed packets against some pre-computed reference values.
26192630
* These packets were made with a policy that applies null encryption
26202631
* and HMAC authentication.
26212632
*/
26222633

2623-
srtp_err_status_t srtp_validate_null(void)
2634+
srtp_err_status_t srtp_validate_null_sha1_80(void)
26242635
{
26252636
// clang-format off
26262637
uint8_t srtp_plaintext_ref[28] = {
@@ -2772,6 +2783,176 @@ srtp_err_status_t srtp_validate_null(void)
27722783
return srtp_err_status_ok;
27732784
}
27742785

2786+
/*
2787+
* srtp_validate_null_null() verifies the correctness of libsrtp by comparing
2788+
* some computed packets against some pre-computed reference values.
2789+
* These packets were made with a policy that applies null encryption
2790+
* and null authentication.
2791+
*/
2792+
2793+
srtp_err_status_t srtp_validate_null_null(void)
2794+
{
2795+
// clang-format off
2796+
uint8_t srtp_plaintext_ref[28] = {
2797+
0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
2798+
0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
2799+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2800+
0xab, 0xab, 0xab, 0xab
2801+
};
2802+
uint8_t srtp_plaintext[28] = {
2803+
0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
2804+
0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
2805+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2806+
0xab, 0xab, 0xab, 0xab,
2807+
};
2808+
uint8_t srtp_ciphertext[28] = {
2809+
0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
2810+
0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
2811+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2812+
0xab, 0xab, 0xab, 0xab,
2813+
};
2814+
uint8_t rtcp_plaintext_ref[24] = {
2815+
0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
2816+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2817+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2818+
};
2819+
uint8_t rtcp_plaintext[28] = {
2820+
0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
2821+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2822+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2823+
0x00, 0x00, 0x00, 0x00,
2824+
};
2825+
uint8_t srtcp_ciphertext[28] = {
2826+
0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
2827+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2828+
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
2829+
0x00, 0x00, 0x00, 0x01,
2830+
};
2831+
// clang-format on
2832+
2833+
srtp_t srtp_snd, srtp_recv;
2834+
srtp_err_status_t status;
2835+
size_t len;
2836+
srtp_policy_t policy;
2837+
2838+
/*
2839+
* create a session with a single stream using the default srtp
2840+
* policy and with the SSRC value 0xcafebabe
2841+
*/
2842+
memset(&policy, 0, sizeof(policy));
2843+
srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtp);
2844+
srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtcp);
2845+
policy.ssrc.type = ssrc_specific;
2846+
policy.ssrc.value = 0xcafebabe;
2847+
/*
2848+
* We need some non-zero value set here
2849+
*/
2850+
policy.key = (void *)(uintptr_t)-1;
2851+
policy.window_size = 128;
2852+
policy.allow_repeat_tx = false;
2853+
policy.next = NULL;
2854+
2855+
status = srtp_create(&srtp_snd, &policy);
2856+
if (status) {
2857+
return status;
2858+
}
2859+
2860+
/*
2861+
* protect plaintext, then compare with ciphertext
2862+
*/
2863+
len = 28;
2864+
status = call_srtp_protect(srtp_snd, srtp_plaintext, &len, 0);
2865+
if (!status && (len != 28)) {
2866+
status = srtp_err_status_fail;
2867+
}
2868+
if (status) {
2869+
return status;
2870+
}
2871+
2872+
debug_print(mod_driver, "ciphertext:\n %s",
2873+
octet_string_hex_string(srtp_plaintext, len));
2874+
debug_print(mod_driver, "ciphertext reference:\n %s",
2875+
octet_string_hex_string(srtp_ciphertext, len));
2876+
2877+
if (!srtp_octet_string_equal(srtp_plaintext, srtp_ciphertext, len)) {
2878+
return srtp_err_status_fail;
2879+
}
2880+
2881+
/*
2882+
* protect plaintext rtcp, then compare with srtcp ciphertext
2883+
*/
2884+
len = 24;
2885+
status = call_srtp_protect_rtcp(srtp_snd, rtcp_plaintext, &len, 0);
2886+
if (!status && (len != 28)) {
2887+
status = srtp_err_status_fail;
2888+
}
2889+
if (status) {
2890+
return status;
2891+
}
2892+
2893+
debug_print(mod_driver, "srtcp ciphertext:\n %s",
2894+
octet_string_hex_string(rtcp_plaintext, len));
2895+
debug_print(mod_driver, "srtcp ciphertext reference:\n %s",
2896+
octet_string_hex_string(srtcp_ciphertext, len));
2897+
2898+
if (!srtp_octet_string_equal(rtcp_plaintext, srtcp_ciphertext, len)) {
2899+
return srtp_err_status_fail;
2900+
}
2901+
2902+
/*
2903+
* create a receiver session context comparable to the one created
2904+
* above - we need to do this so that the replay checking doesn't
2905+
* complain
2906+
*/
2907+
status = srtp_create(&srtp_recv, &policy);
2908+
if (status) {
2909+
return status;
2910+
}
2911+
2912+
/*
2913+
* unprotect ciphertext, then compare with plaintext
2914+
*/
2915+
status = call_srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
2916+
if (!status && (len != 28)) {
2917+
status = srtp_err_status_fail;
2918+
}
2919+
if (status) {
2920+
return status;
2921+
}
2922+
2923+
if (!srtp_octet_string_equal(srtp_ciphertext, srtp_plaintext_ref, len)) {
2924+
return srtp_err_status_fail;
2925+
}
2926+
2927+
/*
2928+
* unprotect srtcp ciphertext, then compare with rtcp plaintext
2929+
*/
2930+
len = 28;
2931+
status = call_srtp_unprotect_rtcp(srtp_recv, srtcp_ciphertext, &len);
2932+
if (!status && (len != 24)) {
2933+
status = srtp_err_status_fail;
2934+
}
2935+
if (status) {
2936+
return status;
2937+
}
2938+
2939+
if (!srtp_octet_string_equal(srtcp_ciphertext, rtcp_plaintext_ref, len)) {
2940+
return srtp_err_status_fail;
2941+
}
2942+
2943+
status = srtp_dealloc(srtp_snd);
2944+
if (status) {
2945+
return status;
2946+
}
2947+
2948+
status = srtp_dealloc(srtp_recv);
2949+
if (status) {
2950+
return status;
2951+
}
2952+
2953+
return srtp_err_status_ok;
2954+
}
2955+
27752956
/*
27762957
* srtp_validate_cryptex() verifies the correctness of libsrtp by comparing
27772958
* some computed packets against some pre-computed reference values.

0 commit comments

Comments
 (0)