Merge pull request #136 from fancycode/unprotect_empty_payload
Allow empty payloads when unprotecting.
diff --git a/srtp/srtp.c b/srtp/srtp.c
index 1b86a74..c9a5bee 100644
--- a/srtp/srtp.c
+++ b/srtp/srtp.c
@@ -1460,7 +1460,7 @@
xtn_hdr = (srtp_hdr_xtnd_t*)enc_start;
enc_start += (ntohs(xtn_hdr->length) + 1);
}
- if (!((uint8_t*)enc_start < (uint8_t*)hdr + (*pkt_octet_len - tag_len)))
+ if (!((uint8_t*)enc_start <= (uint8_t*)hdr + (*pkt_octet_len - tag_len)))
return srtp_err_status_parse_err;
/*
* We pass the tag down to the cipher when doing GCM mode
@@ -2010,7 +2010,7 @@
xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
enc_start += (ntohs(xtn_hdr->length) + 1);
}
- if (!((uint8_t*)enc_start < (uint8_t*)hdr + (*pkt_octet_len - tag_len)))
+ if (!((uint8_t*)enc_start <= (uint8_t*)hdr + (*pkt_octet_len - tag_len)))
return srtp_err_status_parse_err;
enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len -
((uint8_t*)enc_start - (uint8_t*)hdr));
diff --git a/test/srtp_driver.c b/test/srtp_driver.c
index 0e6efa3..4929ca4 100644
--- a/test/srtp_driver.c
+++ b/test/srtp_driver.c
@@ -81,6 +81,14 @@
srtp_dealloc_big_policy(srtp_policy_t *list);
srtp_err_status_t
+srtp_test_empty_payload(void);
+
+#ifdef OPENSSL
+srtp_err_status_t
+srtp_test_empty_payload_gcm(void);
+#endif
+
+srtp_err_status_t
srtp_test_remove_stream(void);
srtp_err_status_t
@@ -359,6 +367,28 @@
}
/*
+ * test packets with empty payload
+ */
+ printf("testing srtp_protect and srtp_unprotect against "
+ "packets with empty payload\n");
+ if (srtp_test_empty_payload() == srtp_err_status_ok) {
+ printf("passed\n");
+ } else{
+ printf("failed\n");
+ exit(1);
+ }
+#ifdef OPENSSL
+ printf("testing srtp_protect and srtp_unprotect against "
+ "packets with empty payload (GCM)\n");
+ if (srtp_test_empty_payload_gcm() == srtp_err_status_ok) {
+ printf("passed\n");
+ } else{
+ printf("failed\n");
+ exit(1);
+ }
+#endif
+
+ /*
* test the function srtp_remove_stream()
*/
printf("testing srtp_remove_stream()...");
@@ -1927,6 +1957,161 @@
return srtp_err_status_ok;
}
+srtp_err_status_t
+srtp_test_empty_payload()
+{
+ srtp_t srtp_snd, srtp_recv;
+ srtp_err_status_t status;
+ int len;
+ srtp_policy_t policy;
+ srtp_hdr_t *mesg;
+
+ /*
+ * create a session with a single stream using the default srtp
+ * policy and with the SSRC value 0xcafebabe
+ */
+ memset(&policy, 0, sizeof(policy));
+ srtp_crypto_policy_set_rtp_default(&policy.rtp);
+ srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
+ policy.ssrc.type = ssrc_specific;
+ policy.ssrc.value = 0xcafebabe;
+ policy.key = test_key;
+ policy.ekt = NULL;
+ policy.window_size = 128;
+ policy.allow_repeat_tx = 0;
+ policy.next = NULL;
+
+ status = srtp_create(&srtp_snd, &policy);
+ if (status) {
+ return status;
+ }
+
+ mesg = srtp_create_test_packet(0, policy.ssrc.value);
+ if (mesg == NULL) {
+ return srtp_err_status_fail;
+ }
+
+ len = 12; /* only the header */
+ status = srtp_protect(srtp_snd, mesg, &len);
+ if (status) {
+ return status;
+ } else if (len != 12 + 10) {
+ return srtp_err_status_fail;
+ }
+
+ /*
+ * create a receiver session context comparable to the one created
+ * above - we need to do this so that the replay checking doesn't
+ * complain
+ */
+ status = srtp_create(&srtp_recv, &policy);
+ if (status) {
+ return status;
+ }
+
+ /*
+ * unprotect ciphertext, then compare with plaintext
+ */
+ status = srtp_unprotect(srtp_recv, mesg, &len);
+ if (status) {
+ return status;
+ } else if (len != 12) {
+ return srtp_err_status_fail;
+ }
+
+ status = srtp_dealloc(srtp_snd);
+ if (status) {
+ return status;
+ }
+
+ status = srtp_dealloc(srtp_recv);
+ if (status) {
+ return status;
+ }
+
+ free(mesg);
+
+ return srtp_err_status_ok;
+}
+
+#ifdef OPENSSL
+srtp_err_status_t
+srtp_test_empty_payload_gcm()
+{
+ srtp_t srtp_snd, srtp_recv;
+ srtp_err_status_t status;
+ int len;
+ srtp_policy_t policy;
+ srtp_hdr_t *mesg;
+
+ /*
+ * create a session with a single stream using the default srtp
+ * policy and with the SSRC value 0xcafebabe
+ */
+ memset(&policy, 0, sizeof(policy));
+ srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
+ srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
+ policy.ssrc.type = ssrc_specific;
+ policy.ssrc.value = 0xcafebabe;
+ policy.key = test_key;
+ policy.ekt = NULL;
+ policy.window_size = 128;
+ policy.allow_repeat_tx = 0;
+ policy.next = NULL;
+
+ status = srtp_create(&srtp_snd, &policy);
+ if (status) {
+ return status;
+ }
+
+ mesg = srtp_create_test_packet(0, policy.ssrc.value);
+ if (mesg == NULL) {
+ return srtp_err_status_fail;
+ }
+
+ len = 12; /* only the header */
+ status = srtp_protect(srtp_snd, mesg, &len);
+ if (status) {
+ return status;
+ } else if (len != 12 + 8) {
+ return srtp_err_status_fail;
+ }
+
+ /*
+ * create a receiver session context comparable to the one created
+ * above - we need to do this so that the replay checking doesn't
+ * complain
+ */
+ status = srtp_create(&srtp_recv, &policy);
+ if (status) {
+ return status;
+ }
+
+ /*
+ * unprotect ciphertext, then compare with plaintext
+ */
+ status = srtp_unprotect(srtp_recv, mesg, &len);
+ if (status) {
+ return status;
+ } else if (len != 12) {
+ return srtp_err_status_fail;
+ }
+
+ status = srtp_dealloc(srtp_snd);
+ if (status) {
+ return status;
+ }
+
+ status = srtp_dealloc(srtp_recv);
+ if (status) {
+ return status;
+ }
+
+ free(mesg);
+
+ return srtp_err_status_ok;
+}
+#endif // OPENSSL
srtp_err_status_t
srtp_test_remove_stream ()