Merge "bump libsrtp to 2.6.0 from upstream code" into main
diff --git a/BUILD.gn b/BUILD.gn
index 45033b7..dab9e50 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -82,18 +82,19 @@
public_configs = [ ":libsrtp_config" ]
sources = [
# includes
- "include/ekt.h",
"include/srtp.h",
# headers
+ "crypto/cipher/cipher_test_cases.h",
+ "crypto/hash/auth_test_cases.h",
"crypto/include/aes.h",
"crypto/include/aes_gcm.h",
- "crypto/include/cipher_priv.h",
"crypto/include/aes_icm.h",
"crypto/include/aes_icm_ext.h",
"crypto/include/alloc.h",
"crypto/include/auth.h",
"crypto/include/cipher.h",
+ "crypto/include/cipher_priv.h",
"crypto/include/cipher_types.h",
"crypto/include/crypto_kernel.h",
"crypto/include/crypto_types.h",
@@ -105,7 +106,6 @@
"crypto/include/null_cipher.h",
"crypto/include/rdb.h",
"crypto/include/rdbx.h",
- "crypto/include/stat.h",
"include/srtp_priv.h",
"include/ut_sim.h",
@@ -113,8 +113,10 @@
"crypto/cipher/aes_gcm_ossl.c",
"crypto/cipher/aes_icm_ossl.c",
"crypto/cipher/cipher.c",
+ "crypto/cipher/cipher_test_cases.c",
"crypto/cipher/null_cipher.c",
"crypto/hash/auth.c",
+ "crypto/hash/auth_test_cases.c",
"crypto/hash/hmac_ossl.c",
"crypto/hash/null_auth.c",
"crypto/kernel/alloc.c",
@@ -122,10 +124,8 @@
"crypto/kernel/err.c",
"crypto/kernel/key.c",
"crypto/math/datatypes.c",
- "crypto/math/stat.c",
"crypto/replay/rdb.c",
"crypto/replay/rdbx.c",
- "srtp/ekt.c",
"srtp/srtp.c",
# TODO(bugs.webrtc.org/11915): The following files are not needed by
@@ -165,17 +165,15 @@
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
configs += [ ":srtp_test_config" ]
- deps = [
- ":libsrtp",
- ]
+ deps = [ ":libsrtp" ]
sources = [
- "crypto/replay/ut_sim.c",
- "include/getopt_s.h",
- "include/ut_sim.h",
- "test/getopt_s.c",
- "test/util.c",
- "test/util.h",
- ] + invoker.sources
+ "crypto/replay/ut_sim.c",
+ "include/getopt_s.h",
+ "include/ut_sim.h",
+ "test/getopt_s.c",
+ "test/util.c",
+ "test/util.h",
+ ] + invoker.sources
testonly = true
}
}
@@ -216,9 +214,7 @@
configs += [ "//build/config/compiler:no_chromium_code" ]
configs += [ ":srtp_test_config" ]
output_dir = "${root_out_dir}/srtp_tests"
- deps = [
- ":libsrtp",
- ]
+ deps = [ ":libsrtp" ]
sources = [
"include/getopt_s.h",
"test/getopt_s.c",
@@ -242,19 +238,13 @@
"test/rtpw_test.sh",
"test/rtpw_test_gcm.sh",
]
- outputs = [
- "${root_out_dir}/srtp_tests/{{source_file_part}}",
- ]
+ outputs = [ "${root_out_dir}/srtp_tests/{{source_file_part}}" ]
testonly = true
}
copy("test_data") {
- sources = [
- "test/words.txt",
- ]
- outputs = [
- "${root_out_dir}/srtp_tests/{{source_file_part}}",
- ]
+ sources = [ "test/words.txt" ]
+ outputs = [ "${root_out_dir}/srtp_tests/{{source_file_part}}" ]
testonly = true
}
@@ -269,9 +259,9 @@
":roc_driver",
":rtpw",
":srtp_driver",
- ":test_srtp",
- ":test_scripts",
":test_data",
+ ":test_scripts",
+ ":test_srtp",
]
testonly = true
}
diff --git a/CHANGES b/CHANGES
index 181a31b..81319a8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,118 @@
Changelog
-2.4.0-pre (This version)
+2.6.0
+
+#667 - remove use of pointers to 32bit values
+
+#666 - Cleaning up cmake and enabled more warnings.
+
+#665 - start using const on internal arguments
+
+#662 - Some srtp_driver fixes
+
+#661 - remove travis reference from README.md
+
+#660 - meson.build: implement mbedtls support
+
+#649 - iv length is constant so set only once
+
+#507 - Add x86 SIMD optimizations to crypto datatypes
+
+#643 - Add a missing typedef for stream list ctx
+
+#641 - cmake: Rename TEST_APPS as LIBSRTP_TEST_APPS option
+
+#640 - cmake: Support configuring as subproject
+
+2.5.0
+
+#636 - Make mbedtls hmac less restrictive in line with RFC and library capabilities
+
+#612 - Allow overriding stream list implementation
+
+#629 - update min openssl version to 1.1.0
+
+#602 - Openssl 3 support for EVP MAC
+
+#628 - Add android build to CI
+
+#616 - add CIFuzz Github action to workflows
+
+#621 - Add policy_set_aes_cm_192_xxx symbols to def file
+
+#617 - Use current directions in stream update test
+
+#614 - Call `set_aad` and `get_tag` in AEAD performance tests
+
+#611 - Create alias for srtp2 as libSRTP::srtp2
+
+#593 - Remove compatibility code for legacy OpenSSL to fix LibreSSL build
+
+#573 - Export CMake Targets
+
+#586 - Avoid initializing local char table when converting nibble to hex
+
+#591 - EVP_CIPHER_CTX_cleanup() is deprecated in OpenSSL 1.1.0
+
+#589 - Correct null cipher key sizes and be more defensive
+
+#570 - Include directory should point to 'include' not to 'include/srtp2'
+
+#551 - Count blocks instead of bytes in AES-ICM limit computation
+
+#561 - Rtp decoder support ssrc and roc
+
+#559 - Use a full-length key even with null ciphers
+
+#558 - Fix set ROC functionality with gcm
+
+2.4.0
+
+Major changes
+
+#529 - Remove EKT files, this was never completed and the draft has since changed.
+
+#512 - Adds support for Mbedtls as a crypto backend.
+
+#503 - Support apple silicon build.
+
+#495 - Adds support for the Meson build system. This is an alternative to Cmake and auto tools.
+
+Other changes
+
+#546 - Improve OpenSSL KDF check.
+
+#542 - Add void to function declarations for EVP_EncryptInit check.
+
+#531 - Remove dead code.
+
+#524 - Support running against nss >= 3.52.
+
+#521 - Remove references to dtls from libsrtp.
+
+#520 - Use nss based hmac when nss enabled.
+
+#519 - Move selftest vectors form backends to common files.
+
+#515 - Extend cmake support.
+
+#514 - Fix gcc11 warning by defining output length.
+
+#502 - Remove visual studio build files.
+
+#501 - cmake: Set the VERSION property of the srtp2 library.
+
+#500 - Fixed issue #499 with buffer overflow.
+
+#498 - Feature/additional error checks.
+
+#496 - Rework check for OPENSSL_cleanse().
+
+#492 - Avoid non-existing compiler flag -O4.
+
+#491 - Fix two-byte RTP header extension encryption.
+
+#478 - Modify cmake to install crypto_types.h instead of cipher_types.h
2.3.0
@@ -8,10 +120,12 @@
A fuzzer was added to the project based on libFuzzer. This is run as part of Google oss-fuzz, the current status can be found at https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libsrtp . Details available in PR #442 and issue #393.
-CMake support was added as an alternative build system. This was primarily added to replace the Visual Studio project files currently checked in but has been extend to support building on all platforms. Initial PR #449 and #455 but has been support has been continuously improved.
+CMake support was added as an alternative build system. This was primarily added to replace the Visual Studio project files currently checked in but has been extend to support building on all platforms. Initial PR #449 and #455 but has been support has been continuously improved.
NSS support for crypto backend was added. This is can be used as an alternative to openssl. Initial PR #413 but there has been numerous improvements.
+Other changes
+
PR #474 - Add flag to disable pcap dependency when build test apps.
PR #472 - Add ci builds for ios and android.
diff --git a/LIBSRTP_VERSION b/LIBSRTP_VERSION
index d54c6a8..a277c3d 100644
--- a/LIBSRTP_VERSION
+++ b/LIBSRTP_VERSION
@@ -1 +1 @@
-860492290f7d1f25e2bd45da6471bfd4cd4d7add
+fd08747fa6800b321d53e15feb34da12dc697dee
diff --git a/README.chromium b/README.chromium
index 9bc8907..3dddce4 100644
--- a/README.chromium
+++ b/README.chromium
@@ -1,14 +1,14 @@
Name: libsrtp
URL: https://github.com/cisco/libsrtp
-Version: 860492290f7d1f25e2bd45da6471bfd4cd4d7add
+Version: fd08747fa6800b321d53e15feb34da12dc697dee
License: 3-clause BSD
License File: LICENSE
Security Critical: Yes
Shipped: yes
Description:
- Libsrtp provides secure media transmission in a real
- time communication. It's used with libjingle which
+ libsrtp provides secure media transmission in real
+ time communications. It's used with WebRTC which
provides the p2p session setup.
Local Modifications:
diff --git a/README.md b/README.md
index 3f1e5bb..66a0013 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
-[](https://travis-ci.org/cisco/libsrtp)
+[](https://github.com/cisco/libsrtp/actions/workflows/cmake.yml)
+[](https://github.com/cisco/libsrtp/actions/workflows/autotools.yml)
[](https://scan.coverity.com/projects/cisco-libsrtp)
+[](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libsrtp)
<a name="introduction-to-libsrtp"></a>
# Introduction to libSRTP
@@ -12,10 +14,10 @@
This document describes libSRTP, the Open Source Secure RTP library
from Cisco Systems, Inc. RTP is the Real-time Transport Protocol, an
IETF standard for the transport of real-time data such as telephony,
-audio, and video, defined by [RFC 3550](https://www.ietf.org/rfc/rfc3550.txt).
+audio, and video, defined by [RFC 3550](https://tools.ietf.org/html/rfc3550).
Secure RTP (SRTP) is an RTP profile for providing confidentiality to RTP data
and authentication to the RTP header and payload. SRTP is an IETF Standard,
-defined in [RFC 3711](https://www.ietf.org/rfc/rfc3711.txt), and was developed
+defined in [RFC 3711](https://tools.ietf.org/html/rfc3711), and was developed
in the IETF Audio/Video Transport (AVT) Working Group. This library supports
all of the mandatory features of SRTP, but not all of the optional features. See
the [Supported Features](#supported-features) section for more detailed information.
@@ -31,7 +33,7 @@
--------------------------------------------------------------------------------
-<a name="contact"></a>
+<a name="contact-us"></a>
# Contact Us
- [libsrtp@lists.packetizer.com](mailto:libsrtp@lists.packetizer.com) general mailing list for news / announcements / discussions. This is an open list, see
@@ -46,7 +48,7 @@
## Contents
- [Introduction to libSRTP](#introduction-to-libsrtp)
- - [Contact Us](#contact)
+- [Contact Us](#contact-us)
- [Contents](#contents)
- [License and Disclaimer](#license-and-disclaimer)
- [libSRTP Overview](#libsrtp-overview)
@@ -55,6 +57,7 @@
- [Implementation Notes](#implementation-notes)
- [Installing and Building libSRTP](#installing-and-building-libsrtp)
- [Changing Build Configuration](#changing-build-configuration)
+ - [Using Visual Studio](#using-visual-studio)
- [Applications](#applications)
- [Example Code](#example-code)
- [Credits](#credits)
@@ -137,16 +140,16 @@
list of `srtp_policy_t` structures is equivalent to a session policy.
In such a policy, we refer to a single `srtp_policy_t` as an *element*.
-An `srtp_policy_t` strucutre contains two `crypto_policy_t` structures
+An `srtp_policy_t` structure contains two `srtp_crypto_policy_t` structures
that describe the cryptograhic policies for RTP and RTCP, as well as
the SRTP master key and the SSRC value. The SSRC describes what to
-protect (e.g. which stream), and the `crypto_policy_t` structures
+protect (e.g. which stream), and the `srtp_crypto_policy_t` structures
describe how to protect it. The key is contained in a policy element
because it simplifies the interface to the library. In many cases, it
is desirable to use the same cryptographic policies across all of the
streams in a session, but to use a distinct key for each stream. A
-`crypto_policy_t` structure can be initialized by using either the
-`crypto_policy_set_rtp_default()` or `crypto_policy_set_rtcp_default()`
+`srtp_crypto_policy_t` structure can be initialized by using either the
+`srtp_crypto_policy_set_rtp_default()` or `srtp_crypto_policy_set_rtcp_default()`
functions, which set a crypto policy structure to the default policies
for RTP and RTCP protection, respectively.
@@ -195,7 +198,7 @@
## Supported Features
This library supports all of the mandatory-to-implement features of
-SRTP (as defined in [RFC 3711](https://www.ietf.org/rfc/rfc3711.txt)). Some of these
+SRTP (as defined in [RFC 3711](https://tools.ietf.org/html/rfc3711)). Some of these
features can be selected (or de-selected) at run time by setting an
appropriate policy; this is done using the structure `srtp_policy_t`.
Some other behaviors of the protocol can be adapted by defining an
@@ -209,18 +212,28 @@
- the cipher F8,
- the use of the packet index to select between master keys.
-The user should be aware that it is possible to misuse this libary,
+The user should be aware that it is possible to misuse this library,
and that the result may be that the security level it provides is
inadequate. If you are implementing a feature using this library, you
-will want to read the Security Considerations section of [RFC 3711](https://www.ietf.org/rfc/rfc3711.txt).
+will want to read the Security Considerations section of [RFC 3711](https://tools.ietf.org/html/rfc3711#section-9).
In addition, it is important that you read and understand the
terms outlined in the [License and Disclaimer](#license-and-disclaimer) section.
+This library also supports the AES-GCM Authenticated Encryption methods
+described in [RFC 7714](https://tools.ietf.org/html/rfc7714)
+
--------------------------------------------------------------------------------
<a name="implementation-notes"></a>
## Implementation Notes
+ * It is possible to configure which 3rd party (ie openssl/nss/etc) crypto backend
+ libSRTP will be built with. If no 3rd party backend is set then libSRTP provides
+ an internal implementation of AES and Sha1. The internal implementation only
+ supports AES-128 & AES-256, so to use AES-192 or the AES-GCM group of ciphers a
+ 3rd party crypto backend must be configured. For this and performance reasons it
+ is highly recommended to use a 3rd party crypto backend.
+
* The `srtp_protect()` function assumes that the buffer holding the
rtp packet has enough storage allocated that the authentication
tag can be written to the end of that packet. If this assumption
@@ -279,11 +292,13 @@
-------------------------------|--------------------
\-\-help \-h | Display help
\-\-enable-debug-logging | Enable debug logging in all modules
-\-\-enable-log-stdout | Enable logging to stdout
\-\-enable-openssl | Enable OpenSSL crypto engine
+\-\-enable-nss | Enable NSS crypto engine
\-\-enable-openssl-kdf | Enable OpenSSL KDF algorithm
-\-\-with-log-file | Use file for logging
+\-\-enable-log-stdout | Enable logging to stdout
\-\-with-openssl-dir | Location of OpenSSL installation
+\-\-with-nss-dir | Location of NSS installation
+\-\-with-log-file | Use file for logging
By default there is no log output, logging can be enabled to be output to stdout
or a given file using the configure options.
@@ -314,6 +329,56 @@
```
--------------------------------------------------------------------------------
+<a name="using-visual-studio"></a>
+## Using Visual Studio
+
+On Windows one can use Visual Studio via CMake. CMake can be downloaded here:
+https://cmake.org/ . To create Visual Studio build files, for example run the
+following commands:
+
+```
+# Create build subdirectory
+mkdir build
+cd build
+
+# Make project files
+cmake .. -G "Visual Studio 15 2017"
+
+# Or for 64 bit project files
+cmake .. -G "Visual Studio 15 2017 Win64"
+```
+
+--------------------------------------------------------------------------------
+<a name="using-meson"></a>
+## Using Meson
+
+On all platforms including Windows, one can build using [Meson](https://mesonbuild.com).
+Steps to download Meson are here: https://mesonbuild.com/Getting-meson.html
+
+To build with Meson, you can do something like:
+
+```
+# Setup the build subdirectory
+meson setup --prefix=/path/to/prefix builddir
+
+# Build the project
+meson compile -C builddir
+
+# Run tests
+meson test -C builddir
+
+# Optionally, install
+meson install -C builddir
+```
+
+To build with Visual Studio, run the above commands from inside a Visual Studio
+command prompt, or run `vcvarsall.bat` with the appropriate arguments inside
+a Command Prompt.
+
+Note that you can also replace the above commands with the appropriate `ninja`
+targets: `ninja -C build`, `ninja -C build test`, `ninja -C build install`.
+
+--------------------------------------------------------------------------------
<a name="applications"></a>
# Applications
@@ -425,8 +490,8 @@
memset(&policy, 0x0, sizeof(srtp_policy_t));
// set policy to describe a policy for an SRTP stream
-crypto_policy_set_rtp_default(&policy.rtp);
-crypto_policy_set_rtcp_default(&policy.rtcp);
+srtp_crypto_policy_set_rtp_default(&policy.rtp);
+srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
policy.ssrc = ssrc;
policy.key = key;
policy.next = NULL;
@@ -475,13 +540,13 @@
SRTP and ICM References
September, 2005
-Secure RTP is defined in [RFC 3711](https://www.ietf.org/rfc/rfc3711.txt).
-The counter mode definition is in Section 4.1.1.
+Secure RTP is defined in [RFC 3711](https://tools.ietf.org/html/rfc3711).
+The counter mode definition is in [Section 4.1.1](https://tools.ietf.org/html/rfc3711#section-4.1.1).
SHA-1 is defined in [FIPS PUB 180-4](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
-HMAC is defined in [RFC 2104](https://www.ietf.org/rfc/rfc2104.txt)
+HMAC is defined in [RFC 2104](https://tools.ietf.org/html/rfc2104)
and HMAC-SHA1 test vectors are available
-in [RFC 2202](https://www.ietf.org/rfc/rfc2202.txt).
+in [RFC 2202](https://tools.ietf.org/html/rfc2202#section-3).
-AES-GCM usage in SRTP is defined in [RFC 7714](https://www.ietf.org/html/rfc7714)
+AES-GCM usage in SRTP is defined in [RFC 7714](https://tools.ietf.org/html/rfc7714)
diff --git a/crypto/Makefile.in b/crypto/Makefile.in
index 44f29ad..8c2c4fa 100644
--- a/crypto/Makefile.in
+++ b/crypto/Makefile.in
@@ -61,12 +61,12 @@
# test applications
ifneq (1, $(USE_EXTERNAL_CRYPTO))
AES_CALC = test/aes_calc$(EXE)
+SHA1_DRIVER = test/sha1_driver$(EXE)
endif
testapp = test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \
- test/stat_driver$(EXE) test/sha1_driver$(EXE) \
- test/kernel_driver$(EXE) $(AES_CALC) \
- test/env$(EXE)
+ $(SHA1_DRIVER) test/kernel_driver$(EXE) \
+ $(AES_CALC) test/env$(EXE)
# data values used to test the aes_calc application for AES-128
k128=000102030405060708090a0b0c0d0e0f
@@ -86,11 +86,10 @@
ifneq (1, $(USE_EXTERNAL_CRYPTO))
$(FIND_LIBRARIES) test `test/aes_calc $(k128) $(p128)` = $(c128)
$(FIND_LIBRARIES) test `test/aes_calc $(k256) $(p256)` = $(c256)
+ $(FIND_LIBRARIES) test/sha1_driver$(EXE) -v >/dev/null
endif
$(FIND_LIBRARIES) test/cipher_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) test/datatypes_driver$(EXE) -v >/dev/null
- $(FIND_LIBRARIES) test/stat_driver$(EXE) >/dev/null
- $(FIND_LIBRARIES) test/sha1_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) test/kernel_driver$(EXE) -v >/dev/null
@echo "crypto test applications passed."
diff --git a/crypto/cipher/aes_gcm_ossl.c b/crypto/cipher/aes_gcm_ossl.c
index 375d63c..a769c9b 100644
--- a/crypto/cipher/aes_gcm_ossl.c
+++ b/crypto/cipher/aes_gcm_ossl.c
@@ -54,6 +54,7 @@
#include "err.h" /* for srtp_debug */
#include "crypto_types.h"
#include "cipher_types.h"
+#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_gcm = {
0, /* debugging is off by default */
@@ -192,11 +193,16 @@
break;
}
- EVP_CIPHER_CTX_cleanup(c->ctx);
+ EVP_CIPHER_CTX_reset(c->ctx);
+
if (!EVP_CipherInit_ex(c->ctx, evp, NULL, key, NULL, 0)) {
return (srtp_err_status_init_fail);
}
+ if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) {
+ return (srtp_err_status_init_fail);
+ }
+
return (srtp_err_status_ok);
}
@@ -220,10 +226,6 @@
debug_print(srtp_mod_aes_gcm, "setting iv: %s",
srtp_octet_string_hex_string(iv, 12));
- if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) {
- return (srtp_err_status_init_fail);
- }
-
if (!EVP_CipherInit_ex(c->ctx, NULL, NULL, NULL, iv,
(c->dir == srtp_direction_encrypt ? 1 : 0))) {
return (srtp_err_status_init_fail);
@@ -274,7 +276,7 @@
}
rv = EVP_Cipher(c->ctx, NULL, aad, aad_len);
- if (rv != aad_len) {
+ if (rv < 0 || (uint32_t)rv != aad_len) {
return (srtp_err_status_algo_fail);
} else {
return (srtp_err_status_ok);
@@ -393,174 +395,6 @@
"AES-256 GCM using openssl";
/*
- * KAT values for AES self-test. These
- * values we're derived from independent test code
- * using OpenSSL.
- */
-/* clang-format off */
-static const uint8_t srtp_aes_gcm_test_case_0_key[SRTP_AES_GCM_128_KEY_LEN_WSALT] = {
- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c,
-};
-/* clang-format on */
-
-/* clang-format off */
-static uint8_t srtp_aes_gcm_test_case_0_iv[12] = {
- 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
- 0xde, 0xca, 0xf8, 0x88
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_gcm_test_case_0_plaintext[60] = {
- 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
- 0xba, 0x63, 0x7b, 0x39
-};
-
-/* clang-format off */
-static const uint8_t srtp_aes_gcm_test_case_0_aad[20] = {
- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
- 0xab, 0xad, 0xda, 0xd2
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_gcm_test_case_0_ciphertext[76] = {
- 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
- 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
- 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
- 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
- 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
- 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
- 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
- 0x3d, 0x58, 0xe0, 0x91,
- /* the last 16 bytes are the tag */
- 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
- 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47,
-};
-/* clang-format on */
-
-static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_0a = {
- SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */
- srtp_aes_gcm_test_case_0_key, /* key */
- srtp_aes_gcm_test_case_0_iv, /* packet index */
- 60, /* octets in plaintext */
- srtp_aes_gcm_test_case_0_plaintext, /* plaintext */
- 68, /* octets in ciphertext */
- srtp_aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */
- 20, /* octets in AAD */
- srtp_aes_gcm_test_case_0_aad, /* AAD */
- GCM_AUTH_TAG_LEN_8, /* */
- NULL /* pointer to next testcase */
-};
-
-static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_0 = {
- SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */
- srtp_aes_gcm_test_case_0_key, /* key */
- srtp_aes_gcm_test_case_0_iv, /* packet index */
- 60, /* octets in plaintext */
- srtp_aes_gcm_test_case_0_plaintext, /* plaintext */
- 76, /* octets in ciphertext */
- srtp_aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */
- 20, /* octets in AAD */
- srtp_aes_gcm_test_case_0_aad, /* AAD */
- GCM_AUTH_TAG_LEN, /* */
- &srtp_aes_gcm_test_case_0a /* pointer to next testcase */
-};
-
-/* clang-format off */
-static const uint8_t srtp_aes_gcm_test_case_1_key[SRTP_AES_GCM_256_KEY_LEN_WSALT] = {
- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
- 0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c,
- 0xaf, 0xf5, 0x26, 0x9a, 0x21, 0xd5, 0x14, 0xb2,
- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c,
-};
-/* clang-format on */
-
-/* clang-format off */
-static uint8_t srtp_aes_gcm_test_case_1_iv[12] = {
- 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
- 0xde, 0xca, 0xf8, 0x88
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_gcm_test_case_1_plaintext[60] = {
- 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
- 0xba, 0x63, 0x7b, 0x39
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_gcm_test_case_1_aad[20] = {
- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
- 0xab, 0xad, 0xda, 0xd2
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_gcm_test_case_1_ciphertext[76] = {
- 0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46,
- 0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a,
- 0x94, 0x82, 0xca, 0xab, 0x3e, 0x39, 0xd7, 0x86,
- 0x1b, 0xc7, 0x93, 0xed, 0x75, 0x7f, 0x23, 0x5a,
- 0xda, 0xfd, 0xd3, 0xe2, 0x0e, 0x80, 0x87, 0xa9,
- 0x6d, 0xd7, 0xe2, 0x6a, 0x7d, 0x5f, 0xb4, 0x80,
- 0xef, 0xef, 0xc5, 0x29, 0x12, 0xd1, 0xaa, 0x10,
- 0x09, 0xc9, 0x86, 0xc1,
- /* the last 16 bytes are the tag */
- 0x45, 0xbc, 0x03, 0xe6, 0xe1, 0xac, 0x0a, 0x9f,
- 0x81, 0xcb, 0x8e, 0x5b, 0x46, 0x65, 0x63, 0x1d,
-};
-/* clang-format on */
-
-static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1a = {
- SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */
- srtp_aes_gcm_test_case_1_key, /* key */
- srtp_aes_gcm_test_case_1_iv, /* packet index */
- 60, /* octets in plaintext */
- srtp_aes_gcm_test_case_1_plaintext, /* plaintext */
- 68, /* octets in ciphertext */
- srtp_aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */
- 20, /* octets in AAD */
- srtp_aes_gcm_test_case_1_aad, /* AAD */
- GCM_AUTH_TAG_LEN_8, /* */
- NULL /* pointer to next testcase */
-};
-
-static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1 = {
- SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */
- srtp_aes_gcm_test_case_1_key, /* key */
- srtp_aes_gcm_test_case_1_iv, /* packet index */
- 60, /* octets in plaintext */
- srtp_aes_gcm_test_case_1_plaintext, /* plaintext */
- 76, /* octets in ciphertext */
- srtp_aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */
- 20, /* octets in AAD */
- srtp_aes_gcm_test_case_1_aad, /* AAD */
- GCM_AUTH_TAG_LEN, /* */
- &srtp_aes_gcm_test_case_1a /* pointer to next testcase */
-};
-
-/*
* This is the vector function table for this crypto engine.
*/
const srtp_cipher_type_t srtp_aes_gcm_128 = {
@@ -573,7 +407,7 @@
srtp_aes_gcm_openssl_set_iv,
srtp_aes_gcm_openssl_get_tag,
srtp_aes_gcm_128_openssl_description,
- &srtp_aes_gcm_test_case_0,
+ &srtp_aes_gcm_128_test_case_0,
SRTP_AES_GCM_128
};
@@ -590,6 +424,6 @@
srtp_aes_gcm_openssl_set_iv,
srtp_aes_gcm_openssl_get_tag,
srtp_aes_gcm_256_openssl_description,
- &srtp_aes_gcm_test_case_1,
+ &srtp_aes_gcm_256_test_case_0,
SRTP_AES_GCM_256
};
diff --git a/crypto/cipher/aes_icm_ossl.c b/crypto/cipher/aes_icm_ossl.c
index 451cd18..911e9f8 100644
--- a/crypto/cipher/aes_icm_ossl.c
+++ b/crypto/cipher/aes_icm_ossl.c
@@ -58,6 +58,7 @@
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
+#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_icm = {
0, /* debugging is off by default */
@@ -111,6 +112,7 @@
int tlen)
{
srtp_aes_icm_ctx_t *icm;
+ (void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d",
key_len);
@@ -167,7 +169,7 @@
break;
}
- /* set key size */
+ /* set key size */
(*c)->key_len = key_len;
return srtp_err_status_ok;
@@ -248,11 +250,10 @@
break;
}
- EVP_CIPHER_CTX_cleanup(c->ctx);
+ EVP_CIPHER_CTX_reset(c->ctx);
+
if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) {
return srtp_err_status_fail;
- } else {
- return srtp_err_status_ok;
}
return srtp_err_status_ok;
@@ -269,6 +270,7 @@
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
v128_t nonce;
+ (void)dir;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
@@ -282,9 +284,9 @@
if (!EVP_EncryptInit_ex(c->ctx, NULL, NULL, NULL, c->counter.v8)) {
return srtp_err_status_fail;
- } else {
- return srtp_err_status_ok;
}
+
+ return srtp_err_status_ok;
}
/*
@@ -328,165 +330,6 @@
"AES-256 counter mode using openssl";
/*
- * KAT values for AES self-test. These
- * values came from the legacy libsrtp code.
- */
-/* clang-format off */
-static const uint8_t srtp_aes_icm_128_test_case_0_key[SRTP_AES_ICM_128_KEY_LEN_WSALT] = {
- 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
- 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
-};
-/* clang-format on */
-
-/* clang-format off */
-static uint8_t srtp_aes_icm_128_test_case_0_nonce[16] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_icm_128_test_case_0_plaintext[32] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_icm_128_test_case_0_ciphertext[32] = {
- 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
- 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
- 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
- 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
-};
-/* clang-format on */
-
-static const srtp_cipher_test_case_t srtp_aes_icm_128_test_case_0 = {
- SRTP_AES_ICM_128_KEY_LEN_WSALT, /* octets in key */
- srtp_aes_icm_128_test_case_0_key, /* key */
- srtp_aes_icm_128_test_case_0_nonce, /* packet index */
- 32, /* octets in plaintext */
- srtp_aes_icm_128_test_case_0_plaintext, /* plaintext */
- 32, /* octets in ciphertext */
- srtp_aes_icm_128_test_case_0_ciphertext, /* ciphertext */
- 0, /* */
- NULL, /* */
- 0, /* */
- NULL /* pointer to next testcase */
-};
-
-/*
- * KAT values for AES-192-CTR self-test. These
- * values came from section 7 of RFC 6188.
- */
-/* clang-format off */
-static const uint8_t srtp_aes_icm_192_test_case_0_key[SRTP_AES_ICM_192_KEY_LEN_WSALT] = {
- 0xea, 0xb2, 0x34, 0x76, 0x4e, 0x51, 0x7b, 0x2d,
- 0x3d, 0x16, 0x0d, 0x58, 0x7d, 0x8c, 0x86, 0x21,
- 0x97, 0x40, 0xf6, 0x5f, 0x99, 0xb6, 0xbc, 0xf7,
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
-};
-/* clang-format on */
-
-/* clang-format off */
-static uint8_t srtp_aes_icm_192_test_case_0_nonce[16] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_icm_192_test_case_0_plaintext[32] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_icm_192_test_case_0_ciphertext[32] = {
- 0x35, 0x09, 0x6c, 0xba, 0x46, 0x10, 0x02, 0x8d,
- 0xc1, 0xb5, 0x75, 0x03, 0x80, 0x4c, 0xe3, 0x7c,
- 0x5d, 0xe9, 0x86, 0x29, 0x1d, 0xcc, 0xe1, 0x61,
- 0xd5, 0x16, 0x5e, 0xc4, 0x56, 0x8f, 0x5c, 0x9a
-};
-/* clang-format on */
-
-static const srtp_cipher_test_case_t srtp_aes_icm_192_test_case_0 = {
- SRTP_AES_ICM_192_KEY_LEN_WSALT, /* octets in key */
- srtp_aes_icm_192_test_case_0_key, /* key */
- srtp_aes_icm_192_test_case_0_nonce, /* packet index */
- 32, /* octets in plaintext */
- srtp_aes_icm_192_test_case_0_plaintext, /* plaintext */
- 32, /* octets in ciphertext */
- srtp_aes_icm_192_test_case_0_ciphertext, /* ciphertext */
- 0, /* */
- NULL, /* */
- 0, /* */
- NULL /* pointer to next testcase */
-};
-
-/*
- * KAT values for AES-256-CTR self-test. These
- * values came from section 7 of RFC 6188.
- */
-/* clang-format off */
-static const uint8_t srtp_aes_icm_256_test_case_0_key[SRTP_AES_ICM_256_KEY_LEN_WSALT] = {
- 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
- 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
- 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
- 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
-};
-/* clang-format on */
-
-/* clang-format off */
-static uint8_t srtp_aes_icm_256_test_case_0_nonce[16] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_icm_256_test_case_0_plaintext[32] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_aes_icm_256_test_case_0_ciphertext[32] = {
- 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
- 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
- 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
- 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
-};
-/* clang-format on */
-
-static const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0 = {
- SRTP_AES_ICM_256_KEY_LEN_WSALT, /* octets in key */
- srtp_aes_icm_256_test_case_0_key, /* key */
- srtp_aes_icm_256_test_case_0_nonce, /* packet index */
- 32, /* octets in plaintext */
- srtp_aes_icm_256_test_case_0_plaintext, /* plaintext */
- 32, /* octets in ciphertext */
- srtp_aes_icm_256_test_case_0_ciphertext, /* ciphertext */
- 0, /* */
- NULL, /* */
- 0, /* */
- NULL /* pointer to next testcase */
-};
-
-/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
diff --git a/crypto/cipher/cipher.c b/crypto/cipher/cipher.c
index de93bc9..ddb265e 100644
--- a/crypto/cipher/cipher.c
+++ b/crypto/cipher/cipher.c
@@ -632,8 +632,11 @@
clock_t timer;
unsigned char *enc_buf;
unsigned int len = octets_in_buffer;
+ uint32_t tag_len = SRTP_MAX_TAG_LEN;
+ unsigned char aad[4] = { 0, 0, 0, 0 };
+ uint32_t aad_len = 4;
- enc_buf = (unsigned char *)srtp_crypto_alloc(octets_in_buffer);
+ enc_buf = (unsigned char *)srtp_crypto_alloc(octets_in_buffer + tag_len);
if (enc_buf == NULL) {
return 0; /* indicate bad parameters by returning null */
}
@@ -641,15 +644,35 @@
v128_set_to_zero(&nonce);
timer = clock();
for (i = 0; i < num_trials; i++, nonce.v32[3] = i) {
+ // Set IV
if (srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt) !=
srtp_err_status_ok) {
srtp_crypto_free(enc_buf);
return 0;
}
+
+ // Set (empty) AAD if supported by the cipher
+ if (c->type->set_aad) {
+ if (srtp_cipher_set_aad(c, aad, aad_len) != srtp_err_status_ok) {
+ srtp_crypto_free(enc_buf);
+ return 0;
+ }
+ }
+
+ // Encrypt the buffer
if (srtp_cipher_encrypt(c, enc_buf, &len) != srtp_err_status_ok) {
srtp_crypto_free(enc_buf);
return 0;
}
+
+ // Get tag if supported by the cipher
+ if (c->type->get_tag) {
+ if (srtp_cipher_get_tag(c, (uint8_t *)(enc_buf + len), &tag_len) !=
+ srtp_err_status_ok) {
+ srtp_crypto_free(enc_buf);
+ return 0;
+ }
+ }
}
timer = clock() - timer;
diff --git a/crypto/cipher/cipher_test_cases.c b/crypto/cipher/cipher_test_cases.c
new file mode 100644
index 0000000..e4b8f0f
--- /dev/null
+++ b/crypto/cipher/cipher_test_cases.c
@@ -0,0 +1,365 @@
+/*
+ *
+ * Copyright (c) 2013-2021, Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "cipher_test_cases.h"
+#include <stddef.h>
+
+/*
+ * KAT values for AES self-test. These
+ * values came from the legacy libsrtp code.
+ */
+/* clang-format off */
+static const uint8_t srtp_aes_icm_128_test_case_0_key[SRTP_AES_ICM_128_KEY_LEN_WSALT] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
+};
+/* clang-format on */
+
+/* clang-format off */
+static uint8_t srtp_aes_icm_128_test_case_0_nonce[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_icm_128_test_case_0_plaintext[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_icm_128_test_case_0_ciphertext[32] = {
+ 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
+ 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
+ 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
+ 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
+};
+/* clang-format on */
+
+const srtp_cipher_test_case_t srtp_aes_icm_128_test_case_0 = {
+ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* octets in key */
+ srtp_aes_icm_128_test_case_0_key, /* key */
+ srtp_aes_icm_128_test_case_0_nonce, /* packet index */
+ 32, /* octets in plaintext */
+ srtp_aes_icm_128_test_case_0_plaintext, /* plaintext */
+ 32, /* octets in ciphertext */
+ srtp_aes_icm_128_test_case_0_ciphertext, /* ciphertext */
+ 0, /* */
+ NULL, /* */
+ 0, /* */
+ NULL /* pointer to next testcase */
+};
+
+/*
+ * KAT values for AES-192-CTR self-test. These
+ * values came from section 7 of RFC 6188.
+ */
+/* clang-format off */
+static const uint8_t srtp_aes_icm_192_test_case_0_key[SRTP_AES_ICM_192_KEY_LEN_WSALT] = {
+ 0xea, 0xb2, 0x34, 0x76, 0x4e, 0x51, 0x7b, 0x2d,
+ 0x3d, 0x16, 0x0d, 0x58, 0x7d, 0x8c, 0x86, 0x21,
+ 0x97, 0x40, 0xf6, 0x5f, 0x99, 0xb6, 0xbc, 0xf7,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
+};
+/* clang-format on */
+
+/* clang-format off */
+static uint8_t srtp_aes_icm_192_test_case_0_nonce[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_icm_192_test_case_0_plaintext[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_icm_192_test_case_0_ciphertext[32] = {
+ 0x35, 0x09, 0x6c, 0xba, 0x46, 0x10, 0x02, 0x8d,
+ 0xc1, 0xb5, 0x75, 0x03, 0x80, 0x4c, 0xe3, 0x7c,
+ 0x5d, 0xe9, 0x86, 0x29, 0x1d, 0xcc, 0xe1, 0x61,
+ 0xd5, 0x16, 0x5e, 0xc4, 0x56, 0x8f, 0x5c, 0x9a
+};
+/* clang-format on */
+
+const srtp_cipher_test_case_t srtp_aes_icm_192_test_case_0 = {
+ SRTP_AES_ICM_192_KEY_LEN_WSALT, /* octets in key */
+ srtp_aes_icm_192_test_case_0_key, /* key */
+ srtp_aes_icm_192_test_case_0_nonce, /* packet index */
+ 32, /* octets in plaintext */
+ srtp_aes_icm_192_test_case_0_plaintext, /* plaintext */
+ 32, /* octets in ciphertext */
+ srtp_aes_icm_192_test_case_0_ciphertext, /* ciphertext */
+ 0, /* */
+ NULL, /* */
+ 0, /* */
+ NULL /* pointer to next testcase */
+};
+
+/*
+ * KAT values for AES-256-CTR self-test. These
+ * values came from section 7 of RFC 6188.
+ */
+/* clang-format off */
+static const uint8_t srtp_aes_icm_256_test_case_0_key[SRTP_AES_ICM_256_KEY_LEN_WSALT] = {
+ 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
+ 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
+ 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
+ 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
+};
+/* clang-format on */
+
+/* clang-format off */
+static uint8_t srtp_aes_icm_256_test_case_0_nonce[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_icm_256_test_case_0_plaintext[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_icm_256_test_case_0_ciphertext[32] = {
+ 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
+ 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
+ 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
+ 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
+};
+/* clang-format on */
+
+const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0 = {
+ SRTP_AES_ICM_256_KEY_LEN_WSALT, /* octets in key */
+ srtp_aes_icm_256_test_case_0_key, /* key */
+ srtp_aes_icm_256_test_case_0_nonce, /* packet index */
+ 32, /* octets in plaintext */
+ srtp_aes_icm_256_test_case_0_plaintext, /* plaintext */
+ 32, /* octets in ciphertext */
+ srtp_aes_icm_256_test_case_0_ciphertext, /* ciphertext */
+ 0, /* */
+ NULL, /* */
+ 0, /* */
+ NULL /* pointer to next testcase */
+};
+
+/*
+ * KAT values for AES self-test. These
+ * values we're derived from independent test code
+ * using OpenSSL.
+ */
+/* clang-format off */
+static const uint8_t srtp_aes_gcm_128_test_case_0_key[SRTP_AES_GCM_128_KEY_LEN_WSALT] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c,
+};
+/* clang-format on */
+
+/* clang-format off */
+static uint8_t srtp_aes_gcm_128_test_case_0_iv[12] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_gcm_128_test_case_0_plaintext[60] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+};
+
+/* clang-format off */
+static const uint8_t srtp_aes_gcm_128_test_case_0_aad[20] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_gcm_128_test_case_0_ciphertext[76] = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91,
+ /* the last 16 bytes are the tag */
+ 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+ 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47,
+};
+/* clang-format on */
+
+static const srtp_cipher_test_case_t srtp_aes_gcm_128_test_case_0a = {
+ SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */
+ srtp_aes_gcm_128_test_case_0_key, /* key */
+ srtp_aes_gcm_128_test_case_0_iv, /* packet index */
+ 60, /* octets in plaintext */
+ srtp_aes_gcm_128_test_case_0_plaintext, /* plaintext */
+ 68, /* octets in ciphertext */
+ srtp_aes_gcm_128_test_case_0_ciphertext, /* ciphertext + tag */
+ 20, /* octets in AAD */
+ srtp_aes_gcm_128_test_case_0_aad, /* AAD */
+ 8, /* */
+ NULL /* pointer to next testcase */
+};
+
+const srtp_cipher_test_case_t srtp_aes_gcm_128_test_case_0 = {
+ SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */
+ srtp_aes_gcm_128_test_case_0_key, /* key */
+ srtp_aes_gcm_128_test_case_0_iv, /* packet index */
+ 60, /* octets in plaintext */
+ srtp_aes_gcm_128_test_case_0_plaintext, /* plaintext */
+ 76, /* octets in ciphertext */
+ srtp_aes_gcm_128_test_case_0_ciphertext, /* ciphertext + tag */
+ 20, /* octets in AAD */
+ srtp_aes_gcm_128_test_case_0_aad, /* AAD */
+ 16, /* */
+ &srtp_aes_gcm_128_test_case_0a /* pointer to next testcase */
+};
+
+/* clang-format off */
+static const uint8_t srtp_aes_gcm_256_test_case_0_key[SRTP_AES_GCM_256_KEY_LEN_WSALT] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c,
+ 0xaf, 0xf5, 0x26, 0x9a, 0x21, 0xd5, 0x14, 0xb2,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c,
+};
+/* clang-format on */
+
+/* clang-format off */
+static uint8_t srtp_aes_gcm_256_test_case_0_iv[12] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_gcm_256_test_case_0_plaintext[60] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_gcm_256_test_case_0_aad[20] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_aes_gcm_256_test_case_0_ciphertext[76] = {
+ 0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46,
+ 0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a,
+ 0x94, 0x82, 0xca, 0xab, 0x3e, 0x39, 0xd7, 0x86,
+ 0x1b, 0xc7, 0x93, 0xed, 0x75, 0x7f, 0x23, 0x5a,
+ 0xda, 0xfd, 0xd3, 0xe2, 0x0e, 0x80, 0x87, 0xa9,
+ 0x6d, 0xd7, 0xe2, 0x6a, 0x7d, 0x5f, 0xb4, 0x80,
+ 0xef, 0xef, 0xc5, 0x29, 0x12, 0xd1, 0xaa, 0x10,
+ 0x09, 0xc9, 0x86, 0xc1,
+ /* the last 16 bytes are the tag */
+ 0x45, 0xbc, 0x03, 0xe6, 0xe1, 0xac, 0x0a, 0x9f,
+ 0x81, 0xcb, 0x8e, 0x5b, 0x46, 0x65, 0x63, 0x1d,
+};
+/* clang-format on */
+
+static const srtp_cipher_test_case_t srtp_aes_gcm_256_test_case_0a = {
+ SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */
+ srtp_aes_gcm_256_test_case_0_key, /* key */
+ srtp_aes_gcm_256_test_case_0_iv, /* packet index */
+ 60, /* octets in plaintext */
+ srtp_aes_gcm_256_test_case_0_plaintext, /* plaintext */
+ 68, /* octets in ciphertext */
+ srtp_aes_gcm_256_test_case_0_ciphertext, /* ciphertext + tag */
+ 20, /* octets in AAD */
+ srtp_aes_gcm_256_test_case_0_aad, /* AAD */
+ 8, /* */
+ NULL /* pointer to next testcase */
+};
+
+const srtp_cipher_test_case_t srtp_aes_gcm_256_test_case_0 = {
+ SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */
+ srtp_aes_gcm_256_test_case_0_key, /* key */
+ srtp_aes_gcm_256_test_case_0_iv, /* packet index */
+ 60, /* octets in plaintext */
+ srtp_aes_gcm_256_test_case_0_plaintext, /* plaintext */
+ 76, /* octets in ciphertext */
+ srtp_aes_gcm_256_test_case_0_ciphertext, /* ciphertext + tag */
+ 20, /* octets in AAD */
+ srtp_aes_gcm_256_test_case_0_aad, /* AAD */
+ 16, /* */
+ &srtp_aes_gcm_256_test_case_0a /* pointer to next testcase */
+};
diff --git a/crypto/include/stat.h b/crypto/cipher/cipher_test_cases.h
similarity index 74%
rename from crypto/include/stat.h
rename to crypto/cipher/cipher_test_cases.h
index 1894e04..c8a9284 100644
--- a/crypto/include/stat.h
+++ b/crypto/cipher/cipher_test_cases.h
@@ -1,15 +1,6 @@
/*
- * stats.h
*
- * interface to statistical test functions
- *
- * David A. McGrew
- * Cisco Systems, Inc.
- */
-
-/*
- *
- * Copyright(c) 2001-2017, Cisco Systems, Inc.
+ * Copyright (c) 2013-2021, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,24 +34,20 @@
*
*/
-#ifndef STAT_H
-#define STAT_H
+#ifndef CHIPHER_TEST_CASES_H
+#define CHIPHER_TEST_CASES_H
-#include "datatypes.h" /* for uint8_t */
-#include "err.h" /* for srtp_err_status_t */
-
-#ifdef __cplusplus
-extern "C" {
+#ifdef HAVE_CONFIG_H
+#include <config.h>
#endif
-srtp_err_status_t stat_test_monobit(uint8_t *data);
+#include "cipher.h"
-srtp_err_status_t stat_test_poker(uint8_t *data);
+extern const srtp_cipher_test_case_t srtp_aes_icm_128_test_case_0;
+extern const srtp_cipher_test_case_t srtp_aes_icm_192_test_case_0;
+extern const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0;
-srtp_err_status_t stat_test_runs(uint8_t *data);
+extern const srtp_cipher_test_case_t srtp_aes_gcm_128_test_case_0;
+extern const srtp_cipher_test_case_t srtp_aes_gcm_256_test_case_0;
-#ifdef __cplusplus
-}
#endif
-
-#endif /* STAT_H */
diff --git a/crypto/cipher/null_cipher.c b/crypto/cipher/null_cipher.c
index 9697246..a58ba5c 100644
--- a/crypto/cipher/null_cipher.c
+++ b/crypto/cipher/null_cipher.c
@@ -59,6 +59,7 @@
int tlen)
{
extern const srtp_cipher_type_t srtp_null_cipher;
+ (void)tlen;
debug_print(srtp_mod_cipher, "allocating cipher with key length %d",
key_len);
@@ -96,7 +97,8 @@
static srtp_err_status_t srtp_null_cipher_init(void *cv, const uint8_t *key)
{
/* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */
-
+ (void)cv;
+ (void)key;
debug_print0(srtp_mod_cipher, "initializing null cipher");
return srtp_err_status_ok;
@@ -107,6 +109,9 @@
srtp_cipher_direction_t dir)
{
/* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */
+ (void)cv;
+ (void)iv;
+ (void)dir;
return srtp_err_status_ok;
}
@@ -115,6 +120,9 @@
unsigned int *bytes_to_encr)
{
/* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */
+ (void)cv;
+ (void)buf;
+ (void)bytes_to_encr;
return srtp_err_status_ok;
}
diff --git a/crypto/hash/auth.c b/crypto/hash/auth.c
index f19327d..9be0ccf 100644
--- a/crypto/hash/auth.c
+++ b/crypto/hash/auth.c
@@ -123,6 +123,12 @@
return status;
}
+ status = srtp_auth_start(a);
+ if (status) {
+ srtp_auth_dealloc(a);
+ return status;
+ }
+
/* zeroize tag then compute */
octet_string_set_to_zero(tag, test_case->tag_length_octets);
status = srtp_auth_compute(a, test_case->data,
diff --git a/crypto/hash/auth_test_cases.c b/crypto/hash/auth_test_cases.c
new file mode 100644
index 0000000..22b9418
--- /dev/null
+++ b/crypto/hash/auth_test_cases.c
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright (c) 2013-2021, Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "auth_test_cases.h"
+#include <stddef.h>
+
+/* clang-format off */
+static const uint8_t srtp_hmac_test_case_0_key[20] = {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_hmac_test_case_0_data[8] = {
+ 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */
+};
+/* clang-format on */
+
+/* clang-format off */
+static const uint8_t srtp_hmac_test_case_0_tag[20] = {
+ 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
+ 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e,
+ 0xf1, 0x46, 0xbe, 0x00
+};
+/* clang-format on */
+
+const srtp_auth_test_case_t srtp_hmac_test_case_0 = {
+ sizeof(srtp_hmac_test_case_0_key), /* octets in key */
+ srtp_hmac_test_case_0_key, /* key */
+ sizeof(srtp_hmac_test_case_0_data), /* octets in data */
+ srtp_hmac_test_case_0_data, /* data */
+ sizeof(srtp_hmac_test_case_0_tag), /* octets in tag */
+ srtp_hmac_test_case_0_tag, /* tag */
+ NULL /* pointer to next testcase */
+};
diff --git a/crypto/include/stat.h b/crypto/hash/auth_test_cases.h
similarity index 73%
copy from crypto/include/stat.h
copy to crypto/hash/auth_test_cases.h
index 1894e04..9f37718 100644
--- a/crypto/include/stat.h
+++ b/crypto/hash/auth_test_cases.h
@@ -1,15 +1,6 @@
/*
- * stats.h
*
- * interface to statistical test functions
- *
- * David A. McGrew
- * Cisco Systems, Inc.
- */
-
-/*
- *
- * Copyright(c) 2001-2017, Cisco Systems, Inc.
+ * Copyright (c) 2013-2021, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,24 +34,15 @@
*
*/
-#ifndef STAT_H
-#define STAT_H
+#ifndef AUTH_TEST_CASES_H
+#define AUTH_TEST_CASES_H
-#include "datatypes.h" /* for uint8_t */
-#include "err.h" /* for srtp_err_status_t */
-
-#ifdef __cplusplus
-extern "C" {
+#ifdef HAVE_CONFIG_H
+#include <config.h>
#endif
-srtp_err_status_t stat_test_monobit(uint8_t *data);
+#include "auth.h"
-srtp_err_status_t stat_test_poker(uint8_t *data);
+extern const srtp_auth_test_case_t srtp_hmac_test_case_0;
-srtp_err_status_t stat_test_runs(uint8_t *data);
-
-#ifdef __cplusplus
-}
#endif
-
-#endif /* STAT_H */
diff --git a/crypto/hash/hmac_ossl.c b/crypto/hash/hmac_ossl.c
index 8146438..4bdfe53 100644
--- a/crypto/hash/hmac_ossl.c
+++ b/crypto/hash/hmac_ossl.c
@@ -49,23 +49,59 @@
#include "auth.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
+#include "auth_test_cases.h"
#include <openssl/evp.h>
+
+#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+#define SRTP_OSSL_USE_EVP_MAC
+/* before this version reinit of EVP_MAC_CTX was not supported so need to
+ * duplicate the CTX each time */
+#define SRTP_OSSL_MIN_REINIT_VERSION 0x30000030L
+#endif
+
+#ifndef SRTP_OSSL_USE_EVP_MAC
#include <openssl/hmac.h>
+#endif
#define SHA1_DIGEST_SIZE 20
-/* the debug module for authentiation */
+/* the debug module for authentication */
srtp_debug_module_t srtp_mod_hmac = {
0, /* debugging is off by default */
"hmac sha-1 openssl" /* printable name for module */
};
+/*
+ * There are three different behaviors of OpenSSL HMAC for different versions.
+ *
+ * 1. Pre-3.0 - Use HMAC API
+ * 2. 3.0.0 - 3.0.2 - EVP API is required, but doesn't support reinitialization,
+ * so we have to use EVP_MAC_CTX_dup
+ * 3. 3.0.3 and later - EVP API is required and supports reinitialization
+ *
+ * The distingtion between cases 2 & 3 needs to be made at runtime, because in a
+ * shared library context you might end up building against 3.0.3 and running
+ * against 3.0.2.
+ */
+
+typedef struct {
+#ifdef SRTP_OSSL_USE_EVP_MAC
+ EVP_MAC *mac;
+ EVP_MAC_CTX *ctx;
+ int use_dup;
+ EVP_MAC_CTX *ctx_dup;
+#else
+ HMAC_CTX *ctx;
+#endif
+} srtp_hmac_ossl_ctx_t;
+
static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a,
int key_len,
int out_len)
{
extern const srtp_auth_type_t srtp_hmac;
+ srtp_hmac_ossl_ctx_t *hmac;
debug_print(srtp_mod_hmac, "allocating auth func with key length %d",
key_len);
@@ -77,33 +113,49 @@
return srtp_err_status_bad_param;
}
-/* OpenSSL 1.1.0 made HMAC_CTX an opaque structure, which must be allocated
- using HMAC_CTX_new. But this function doesn't exist in OpenSSL 1.0.x. */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER
- {
- /* allocate memory for auth and HMAC_CTX structures */
- uint8_t *pointer;
- HMAC_CTX *new_hmac_ctx;
- pointer = (uint8_t *)srtp_crypto_alloc(sizeof(HMAC_CTX) +
- sizeof(srtp_auth_t));
- if (pointer == NULL) {
- return srtp_err_status_alloc_fail;
- }
- *a = (srtp_auth_t *)pointer;
- (*a)->state = pointer + sizeof(srtp_auth_t);
- new_hmac_ctx = (HMAC_CTX *)((*a)->state);
-
- HMAC_CTX_init(new_hmac_ctx);
- }
-
-#else
*a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t));
if (*a == NULL) {
return srtp_err_status_alloc_fail;
}
- (*a)->state = HMAC_CTX_new();
- if ((*a)->state == NULL) {
+ hmac =
+ (srtp_hmac_ossl_ctx_t *)srtp_crypto_alloc(sizeof(srtp_hmac_ossl_ctx_t));
+ if (hmac == NULL) {
+ srtp_crypto_free(*a);
+ *a = NULL;
+ return srtp_err_status_alloc_fail;
+ }
+
+#ifdef SRTP_OSSL_USE_EVP_MAC
+ hmac->mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ if (hmac->mac == NULL) {
+ srtp_crypto_free(hmac);
+ srtp_crypto_free(*a);
+ *a = NULL;
+ return srtp_err_status_alloc_fail;
+ }
+
+ hmac->ctx = EVP_MAC_CTX_new(hmac->mac);
+ if (hmac->ctx == NULL) {
+ EVP_MAC_free(hmac->mac);
+ srtp_crypto_free(hmac);
+ srtp_crypto_free(*a);
+ *a = NULL;
+ return srtp_err_status_alloc_fail;
+ }
+
+ hmac->use_dup =
+ OpenSSL_version_num() < SRTP_OSSL_MIN_REINIT_VERSION ? 1 : 0;
+
+ if (hmac->use_dup) {
+ debug_print0(srtp_mod_hmac, "using EVP_MAC_CTX_dup");
+ hmac->ctx_dup = hmac->ctx;
+ hmac->ctx = NULL;
+ }
+#else
+ hmac->ctx = HMAC_CTX_new();
+ if (hmac->ctx == NULL) {
+ srtp_crypto_free(hmac);
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
@@ -111,6 +163,7 @@
#endif
/* set pointers */
+ (*a)->state = hmac;
(*a)->type = &srtp_hmac;
(*a)->out_len = out_len;
(*a)->key_len = key_len;
@@ -121,22 +174,24 @@
static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a)
{
- HMAC_CTX *hmac_ctx;
+ srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)a->state;
- hmac_ctx = (HMAC_CTX *)a->state;
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER
- HMAC_CTX_cleanup(hmac_ctx);
-
- /* zeroize entire state*/
- octet_string_set_to_zero(a, sizeof(HMAC_CTX) + sizeof(srtp_auth_t));
-
+ if (hmac) {
+#ifdef SRTP_OSSL_USE_EVP_MAC
+ EVP_MAC_CTX_free(hmac->ctx);
+ EVP_MAC_CTX_free(hmac->ctx_dup);
+ EVP_MAC_free(hmac->mac);
#else
- HMAC_CTX_free(hmac_ctx);
+ HMAC_CTX_free(hmac->ctx);
+#endif
+ /* zeroize entire state*/
+ octet_string_set_to_zero(hmac, sizeof(srtp_hmac_ossl_ctx_t));
+
+ srtp_crypto_free(hmac);
+ }
/* zeroize entire state*/
octet_string_set_to_zero(a, sizeof(srtp_auth_t));
-#endif
/* free memory */
srtp_crypto_free(a);
@@ -146,11 +201,24 @@
static srtp_err_status_t srtp_hmac_start(void *statev)
{
- HMAC_CTX *state = (HMAC_CTX *)statev;
+ srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev;
- if (HMAC_Init_ex(state, NULL, 0, NULL, NULL) == 0)
+#ifdef SRTP_OSSL_USE_EVP_MAC
+ if (hmac->use_dup) {
+ EVP_MAC_CTX_free(hmac->ctx);
+ hmac->ctx = EVP_MAC_CTX_dup(hmac->ctx_dup);
+ if (hmac->ctx == NULL) {
+ return srtp_err_status_alloc_fail;
+ }
+ } else {
+ if (EVP_MAC_init(hmac->ctx, NULL, 0, NULL) == 0) {
+ return srtp_err_status_auth_fail;
+ }
+ }
+#else
+ if (HMAC_Init_ex(hmac->ctx, NULL, 0, NULL, NULL) == 0)
return srtp_err_status_auth_fail;
-
+#endif
return srtp_err_status_ok;
}
@@ -158,11 +226,22 @@
const uint8_t *key,
int key_len)
{
- HMAC_CTX *state = (HMAC_CTX *)statev;
+ srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev;
- if (HMAC_Init_ex(state, key, key_len, EVP_sha1(), NULL) == 0)
+#ifdef SRTP_OSSL_USE_EVP_MAC
+ OSSL_PARAM params[2];
+
+ params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0);
+ params[1] = OSSL_PARAM_construct_end();
+
+ if (EVP_MAC_init(hmac->use_dup ? hmac->ctx_dup : hmac->ctx, key, key_len,
+ params) == 0) {
return srtp_err_status_auth_fail;
-
+ }
+#else
+ if (HMAC_Init_ex(hmac->ctx, key, key_len, EVP_sha1(), NULL) == 0)
+ return srtp_err_status_auth_fail;
+#endif
return srtp_err_status_ok;
}
@@ -170,14 +249,19 @@
const uint8_t *message,
int msg_octets)
{
- HMAC_CTX *state = (HMAC_CTX *)statev;
+ srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
- if (HMAC_Update(state, message, msg_octets) == 0)
+#ifdef SRTP_OSSL_USE_EVP_MAC
+ if (EVP_MAC_update(hmac->ctx, message, msg_octets) == 0) {
return srtp_err_status_auth_fail;
-
+ }
+#else
+ if (HMAC_Update(hmac->ctx, message, msg_octets) == 0)
+ return srtp_err_status_auth_fail;
+#endif
return srtp_err_status_ok;
}
@@ -187,10 +271,17 @@
int tag_len,
uint8_t *result)
{
- HMAC_CTX *state = (HMAC_CTX *)statev;
+ srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev;
uint8_t hash_value[SHA1_DIGEST_SIZE];
int i;
+#ifdef SRTP_OSSL_USE_EVP_MAC
+ size_t len;
+#else
unsigned int len;
+#endif
+
+ debug_print(srtp_mod_hmac, "input: %s",
+ srtp_octet_string_hex_string(message, msg_octets));
/* check tag length, return error if we can't provide the value expected */
if (tag_len > SHA1_DIGEST_SIZE) {
@@ -198,13 +289,22 @@
}
/* hash message, copy output into H */
- if (HMAC_Update(state, message, msg_octets) == 0)
+#ifdef SRTP_OSSL_USE_EVP_MAC
+ if (EVP_MAC_update(hmac->ctx, message, msg_octets) == 0) {
+ return srtp_err_status_auth_fail;
+ }
+
+ if (EVP_MAC_final(hmac->ctx, hash_value, &len, sizeof hash_value) == 0) {
+ return srtp_err_status_auth_fail;
+ }
+#else
+ if (HMAC_Update(hmac->ctx, message, msg_octets) == 0)
return srtp_err_status_auth_fail;
- if (HMAC_Final(state, hash_value, &len) == 0)
+ if (HMAC_Final(hmac->ctx, hash_value, &len) == 0)
return srtp_err_status_auth_fail;
-
- if (len < tag_len)
+#endif
+ if (tag_len < 0 || len < (unsigned int)tag_len)
return srtp_err_status_auth_fail;
/* copy hash_value to *result */
@@ -218,41 +318,6 @@
return srtp_err_status_ok;
}
-/* begin test case 0 */
-/* clang-format off */
-static const uint8_t srtp_hmac_test_case_0_key[SHA1_DIGEST_SIZE] = {
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_hmac_test_case_0_data[8] = {
- 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */
-};
-/* clang-format on */
-
-/* clang-format off */
-static const uint8_t srtp_hmac_test_case_0_tag[SHA1_DIGEST_SIZE] = {
- 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
- 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e,
- 0xf1, 0x46, 0xbe, 0x00
-};
-/* clang-format on */
-
-static const srtp_auth_test_case_t srtp_hmac_test_case_0 = {
- sizeof(srtp_hmac_test_case_0_key), /* octets in key */
- srtp_hmac_test_case_0_key, /* key */
- sizeof(srtp_hmac_test_case_0_data), /* octets in data */
- srtp_hmac_test_case_0_data, /* data */
- sizeof(srtp_hmac_test_case_0_tag), /* octets in tag */
- srtp_hmac_test_case_0_tag, /* tag */
- NULL /* pointer to next testcase */
-};
-
-/* end test case 0 */
-
static const char srtp_hmac_description[] =
"hmac sha-1 authentication function";
diff --git a/crypto/hash/null_auth.c b/crypto/hash/null_auth.c
index 5194417..ae723c2 100644
--- a/crypto/hash/null_auth.c
+++ b/crypto/hash/null_auth.c
@@ -102,6 +102,10 @@
int key_len)
{
/* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */
+ (void)statev;
+ (void)key;
+ (void)key_len;
+
/* accept any length of key, and do nothing */
return srtp_err_status_ok;
@@ -114,6 +118,11 @@
uint8_t *result)
{
/* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */
+ (void)statev;
+ (void)message;
+ (void)msg_octets;
+ (void)tag_len;
+ (void)result;
return srtp_err_status_ok;
}
@@ -123,6 +132,9 @@
int msg_octets)
{
/* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */
+ (void)statev;
+ (void)message;
+ (void)msg_octets;
return srtp_err_status_ok;
}
@@ -130,6 +142,7 @@
static srtp_err_status_t srtp_null_auth_start(void *statev)
{
/* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */
+ (void)statev;
return srtp_err_status_ok;
}
diff --git a/crypto/include/aes_gcm.h b/crypto/include/aes_gcm.h
index 4d6031f..cd0dcee 100644
--- a/crypto/include/aes_gcm.h
+++ b/crypto/include/aes_gcm.h
@@ -64,8 +64,29 @@
#endif /* OPENSSL */
+#ifdef MBEDTLS
+#define MAX_AD_SIZE 2048
+#include <mbedtls/aes.h>
+#include <mbedtls/gcm.h>
+
+typedef struct {
+ int key_size;
+ int tag_len;
+ int aad_size;
+ int iv_len;
+ uint8_t iv[12];
+ uint8_t tag[16];
+ uint8_t aad[MAX_AD_SIZE];
+ mbedtls_gcm_context *ctx;
+ srtp_cipher_direction_t dir;
+} srtp_aes_gcm_ctx_t;
+
+#endif /* MBEDTLS */
+
#ifdef NSS
+#define NSS_PKCS11_2_0_COMPAT 1
+
#include <nss.h>
#include <pk11pub.h>
diff --git a/crypto/include/aes_icm_ext.h b/crypto/include/aes_icm_ext.h
index ad306dd..5b21c95 100644
--- a/crypto/include/aes_icm_ext.h
+++ b/crypto/include/aes_icm_ext.h
@@ -63,8 +63,24 @@
#endif /* OPENSSL */
+#ifdef MBEDTLS
+
+#include <mbedtls/aes.h>
+typedef struct {
+ v128_t counter; /* holds the counter value */
+ v128_t offset; /* initial offset value */
+ v128_t stream_block;
+ size_t nc_off;
+ int key_size;
+ mbedtls_aes_context *ctx;
+} srtp_aes_icm_ctx_t;
+
+#endif /* MBEDTLS */
+
#ifdef NSS
+#define NSS_PKCS11_2_0_COMPAT 1
+
#include <nss.h>
#include <pk11pub.h>
diff --git a/crypto/include/cipher.h b/crypto/include/cipher.h
index 4f14e35..43d453e 100644
--- a/crypto/include/cipher.h
+++ b/crypto/include/cipher.h
@@ -153,7 +153,7 @@
srtp_cipher_init_func_t init;
srtp_cipher_set_aad_func_t set_aad;
srtp_cipher_encrypt_func_t encrypt;
- srtp_cipher_encrypt_func_t decrypt;
+ srtp_cipher_decrypt_func_t decrypt;
srtp_cipher_set_iv_func_t set_iv;
srtp_cipher_get_tag_func_t get_tag;
const char *description;
diff --git a/crypto/include/cipher_types.h b/crypto/include/cipher_types.h
index 18f0328..28250d1 100644
--- a/crypto/include/cipher_types.h
+++ b/crypto/include/cipher_types.h
@@ -66,19 +66,15 @@
extern srtp_debug_module_t srtp_mod_auth;
extern srtp_debug_module_t srtp_mod_cipher;
-extern srtp_debug_module_t srtp_mod_stat;
extern srtp_debug_module_t srtp_mod_alloc;
/* debug modules for cipher types */
extern srtp_debug_module_t srtp_mod_aes_icm;
-#ifdef OPENSSL
-extern srtp_debug_module_t srtp_mod_aes_gcm;
-#endif
-#ifdef NSS
+
+#if defined(OPENSSL) || defined(MBEDTLS) || defined(NSS)
extern srtp_debug_module_t srtp_mod_aes_gcm;
#endif
/* debug modules for auth types */
extern srtp_debug_module_t srtp_mod_hmac;
-
#endif
diff --git a/crypto/include/datatypes.h b/crypto/include/datatypes.h
index 6a588d0..696defb 100644
--- a/crypto/include/datatypes.h
+++ b/crypto/include/datatypes.h
@@ -62,31 +62,14 @@
#error "Platform not recognized"
#endif
+#if defined(__SSE2__)
+#include <emmintrin.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
-/* if DATATYPES_USE_MACROS is defined, then little functions are macros */
-#define DATATYPES_USE_MACROS
-
-typedef union {
- uint8_t v8[2];
- uint16_t value;
-} v16_t;
-
-typedef union {
- uint8_t v8[4];
- uint16_t v16[2];
- uint32_t value;
-} v32_t;
-
-typedef union {
- uint8_t v8[8];
- uint16_t v16[4];
- uint32_t v32[2];
- uint64_t value;
-} v64_t;
-
typedef union {
uint8_t v8[16];
uint16_t v16[8];
@@ -94,26 +77,6 @@
uint64_t v64[2];
} v128_t;
-typedef union {
- uint8_t v8[32];
- uint16_t v16[16];
- uint32_t v32[8];
- uint64_t v64[4];
-} v256_t;
-
-/* some useful and simple math functions */
-
-#define pow_2(X) ((unsigned int)1 << (X)) /* 2^X */
-
-#define pow_minus_one(X) ((X) ? -1 : 1) /* (-1)^X */
-
-/*
- * octet_get_weight(x) returns the hamming weight (number of bits equal to
- * one) in the octet x
- */
-
-int octet_get_weight(uint8_t octet);
-
#define MAX_PRINT_STRING_LEN 1024
char *srtp_octet_string_hex_string(const void *str, int length);
@@ -126,59 +89,56 @@
void v128_left_shift(v128_t *x, int shift_index);
-void v128_right_shift(v128_t *x, int shift_index);
-
/*
* the following macros define the data manipulation functions
*
- * If DATATYPES_USE_MACROS is defined, then these macros are used
- * directly (and function call overhead is avoided). Otherwise,
- * the macros are used through the functions defined in datatypes.c
- * (and the compiler provides better warnings).
*/
-#define _v128_set_to_zero(x) \
+#if defined(__SSE2__)
+
+#define v128_set_to_zero(x) \
+ (_mm_storeu_si128((__m128i *)(x), _mm_setzero_si128()))
+
+#define v128_copy(x, y) \
+ (_mm_storeu_si128((__m128i *)(x), _mm_loadu_si128((const __m128i *)(y))))
+
+#define v128_xor(z, x, y) \
+ (_mm_storeu_si128((__m128i *)(z), \
+ _mm_xor_si128(_mm_loadu_si128((const __m128i *)(x)), \
+ _mm_loadu_si128((const __m128i *)(y)))))
+
+#define v128_xor_eq(z, x) \
+ (_mm_storeu_si128((__m128i *)(z), \
+ _mm_xor_si128(_mm_loadu_si128((const __m128i *)(x)), \
+ _mm_loadu_si128((const __m128i *)(z)))))
+
+#else /* defined(__SSE2__) */
+
+#define v128_set_to_zero(x) \
((x)->v32[0] = 0, (x)->v32[1] = 0, (x)->v32[2] = 0, (x)->v32[3] = 0)
-#define _v128_copy(x, y) \
+#define v128_copy(x, y) \
((x)->v32[0] = (y)->v32[0], (x)->v32[1] = (y)->v32[1], \
(x)->v32[2] = (y)->v32[2], (x)->v32[3] = (y)->v32[3])
-#define _v128_xor(z, x, y) \
+#define v128_xor(z, x, y) \
((z)->v32[0] = (x)->v32[0] ^ (y)->v32[0], \
(z)->v32[1] = (x)->v32[1] ^ (y)->v32[1], \
(z)->v32[2] = (x)->v32[2] ^ (y)->v32[2], \
(z)->v32[3] = (x)->v32[3] ^ (y)->v32[3])
-#define _v128_and(z, x, y) \
- ((z)->v32[0] = (x)->v32[0] & (y)->v32[0], \
- (z)->v32[1] = (x)->v32[1] & (y)->v32[1], \
- (z)->v32[2] = (x)->v32[2] & (y)->v32[2], \
- (z)->v32[3] = (x)->v32[3] & (y)->v32[3])
-
-#define _v128_or(z, x, y) \
- ((z)->v32[0] = (x)->v32[0] | (y)->v32[0], \
- (z)->v32[1] = (x)->v32[1] | (y)->v32[1], \
- (z)->v32[2] = (x)->v32[2] | (y)->v32[2], \
- (z)->v32[3] = (x)->v32[3] | (y)->v32[3])
-
-#define _v128_complement(x) \
- ((x)->v32[0] = ~(x)->v32[0], (x)->v32[1] = ~(x)->v32[1], \
- (x)->v32[2] = ~(x)->v32[2], (x)->v32[3] = ~(x)->v32[3])
-
/* ok for NO_64BIT_MATH if it can compare uint64_t's (even as structures) */
-#define _v128_is_eq(x, y) \
- (((x)->v64[0] == (y)->v64[0]) && ((x)->v64[1] == (y)->v64[1]))
-
#ifdef NO_64BIT_MATH
-#define _v128_xor_eq(z, x) \
+#define v128_xor_eq(z, x) \
((z)->v32[0] ^= (x)->v32[0], (z)->v32[1] ^= (x)->v32[1], \
(z)->v32[2] ^= (x)->v32[2], (z)->v32[3] ^= (x)->v32[3])
#else
-#define _v128_xor_eq(z, x) \
+#define v128_xor_eq(z, x) \
((z)->v64[0] ^= (x)->v64[0], (z)->v64[1] ^= (x)->v64[1])
#endif
+#endif /* defined(__SSE2__) */
+
/* NOTE! This assumes an odd ordering! */
/* This will not be compatible directly with math on some processors */
/* bit 0 is first 32-bit word, low order bit. in little-endian, that's
@@ -188,58 +148,14 @@
really care which bit is which. AES does care which bit is which, but
doesn't use the 128-bit get/set or 128-bit shifts */
-#define _v128_get_bit(x, bit) (((((x)->v32[(bit) >> 5]) >> ((bit)&31)) & 1))
+#define v128_get_bit(x, bit) (((((x)->v32[(bit) >> 5]) >> ((bit)&31)) & 1))
-#define _v128_set_bit(x, bit) \
+#define v128_set_bit(x, bit) \
((((x)->v32[(bit) >> 5]) |= ((uint32_t)1 << ((bit)&31))))
-#define _v128_clear_bit(x, bit) \
+#define v128_clear_bit(x, bit) \
((((x)->v32[(bit) >> 5]) &= ~((uint32_t)1 << ((bit)&31))))
-#define _v128_set_bit_to(x, bit, value) \
- ((value) ? _v128_set_bit(x, bit) : _v128_clear_bit(x, bit))
-
-#ifdef DATATYPES_USE_MACROS /* little functions are really macros */
-
-#define v128_set_to_zero(z) _v128_set_to_zero(z)
-#define v128_copy(z, x) _v128_copy(z, x)
-#define v128_xor(z, x, y) _v128_xor(z, x, y)
-#define v128_and(z, x, y) _v128_and(z, x, y)
-#define v128_or(z, x, y) _v128_or(z, x, y)
-#define v128_complement(x) _v128_complement(x)
-#define v128_is_eq(x, y) _v128_is_eq(x, y)
-#define v128_xor_eq(x, y) _v128_xor_eq(x, y)
-#define v128_get_bit(x, i) _v128_get_bit(x, i)
-#define v128_set_bit(x, i) _v128_set_bit(x, i)
-#define v128_clear_bit(x, i) _v128_clear_bit(x, i)
-#define v128_set_bit_to(x, i, y) _v128_set_bit_to(x, i, y)
-
-#else
-
-void v128_set_to_zero(v128_t *x);
-
-int v128_is_eq(const v128_t *x, const v128_t *y);
-
-void v128_copy(v128_t *x, const v128_t *y);
-
-void v128_xor(v128_t *z, v128_t *x, v128_t *y);
-
-void v128_and(v128_t *z, v128_t *x, v128_t *y);
-
-void v128_or(v128_t *z, v128_t *x, v128_t *y);
-
-void v128_complement(v128_t *x);
-
-int v128_get_bit(const v128_t *x, int i);
-
-void v128_set_bit(v128_t *x, int i);
-
-void v128_clear_bit(v128_t *x, int i);
-
-void v128_set_bit_to(v128_t *x, int i, int y);
-
-#endif /* DATATYPES_USE_MACROS */
-
/*
* srtp_octet_string_is_eq(a, b, len) returns 1 if the length len strings
* a and b are not equal. It returns 0 otherwise. The running time of the
@@ -247,7 +163,7 @@
* verifying authentication tags.
*/
-int srtp_octet_string_is_eq(uint8_t *a, uint8_t *b, int len);
+int srtp_octet_string_is_eq(const uint8_t *a, const uint8_t *b, int len);
/*
* A portable way to zero out memory as recommended by
@@ -276,15 +192,18 @@
#include <byteswap.h>
#define be32_to_cpu(x) bswap_32((x))
#define be64_to_cpu(x) bswap_64((x))
+#elif defined(__APPLE__)
+// Mac OS X / Darwin features
+#include <libkern/OSByteOrder.h>
+#define be32_to_cpu(x) OSSwapInt32(x)
+#define be64_to_cpu(x) OSSwapInt64(x)
#else /* WORDS_BIGENDIAN */
-#if defined(__GNUC__) && defined(HAVE_X86)
+#if defined(__GNUC__)
/* Fall back. */
static inline uint32_t be32_to_cpu(uint32_t v)
{
- /* optimized for x86. */
- asm("bswap %0" : "=r"(v) : "0"(v));
- return v;
+ return __builtin_bswap32(v);
}
#else /* HAVE_X86 */
#ifdef HAVE_NETINET_IN_H
@@ -297,7 +216,9 @@
static inline uint64_t be64_to_cpu(uint64_t v)
{
-#ifdef NO_64BIT_MATH
+#if defined(__GNUC__)
+ v = __builtin_bswap64(v);
+#elif defined(NO_64BIT_MATH)
/* use the make64 functions to do 64-bit math */
v = make64(htonl(low32(v)), htonl(high32(v)));
#else /* NO_64BIT_MATH */
@@ -331,35 +252,13 @@
uint32_t *word;
} bitvector_t;
-#define _bitvector_get_bit(v, bit_index) \
+#define bitvector_get_bit(v, bit_index) \
(((((v)->word[((bit_index) >> 5)]) >> ((bit_index)&31)) & 1))
-#define _bitvector_set_bit(v, bit_index) \
+#define bitvector_set_bit(v, bit_index) \
((((v)->word[((bit_index) >> 5)] |= ((uint32_t)1 << ((bit_index)&31)))))
-#define _bitvector_clear_bit(v, bit_index) \
- ((((v)->word[((bit_index) >> 5)] &= ~((uint32_t)1 << ((bit_index)&31)))))
-
-#define _bitvector_get_length(v) (((v)->length))
-
-#ifdef DATATYPES_USE_MACROS /* little functions are really macros */
-
-#define bitvector_get_bit(v, bit_index) _bitvector_get_bit(v, bit_index)
-#define bitvector_set_bit(v, bit_index) _bitvector_set_bit(v, bit_index)
-#define bitvector_clear_bit(v, bit_index) _bitvector_clear_bit(v, bit_index)
-#define bitvector_get_length(v) _bitvector_get_length(v)
-
-#else
-
-int bitvector_get_bit(const bitvector_t *v, int bit_index);
-
-void bitvector_set_bit(bitvector_t *v, int bit_index);
-
-void bitvector_clear_bit(bitvector_t *v, int bit_index);
-
-unsigned long bitvector_get_length(const bitvector_t *v);
-
-#endif
+#define bitvector_get_length(v) (((v)->length))
int bitvector_alloc(bitvector_t *v, unsigned long length);
@@ -369,8 +268,6 @@
void bitvector_left_shift(bitvector_t *x, int index);
-char *bitvector_bit_string(bitvector_t *x, char *buf, int len);
-
#ifdef __cplusplus
}
#endif
diff --git a/crypto/include/err.h b/crypto/include/err.h
index 326f5e9..6624d01 100644
--- a/crypto/include/err.h
+++ b/crypto/include/err.h
@@ -49,6 +49,17 @@
#include <stdarg.h>
#include "srtp.h"
+#if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
+#if __has_attribute(format)
+#define LIBSRTP_FORMAT_PRINTF(fmt, args) \
+ __attribute__((format(__printf__, fmt, args)))
+#else
+#define LIBSRTP_FORMAT_PRINTF(fmt, args)
+#endif
+#else
+#define LIBSRTP_FORMAT_PRINTF(fmt, args)
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -96,7 +107,8 @@
*
*/
-void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...);
+void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...)
+ LIBSRTP_FORMAT_PRINTF(2, 3);
/*
* debug_module_t defines a debug module
diff --git a/crypto/include/key.h b/crypto/include/key.h
index 3498114..4164722 100644
--- a/crypto/include/key.h
+++ b/crypto/include/key.h
@@ -66,8 +66,6 @@
srtp_err_status_t srtp_key_limit_clone(srtp_key_limit_t original,
srtp_key_limit_t *new_key);
-srtp_err_status_t srtp_key_limit_check(const srtp_key_limit_t key);
-
srtp_key_event_t srtp_key_limit_update(srtp_key_limit_t key);
typedef enum {
diff --git a/crypto/include/null_auth.h b/crypto/include/null_auth.h
index 490dd7b..0e57d67 100644
--- a/crypto/include/null_auth.h
+++ b/crypto/include/null_auth.h
@@ -55,17 +55,6 @@
char foo;
} srtp_null_auth_ctx_t;
-#if 0
-srtp_err_status_t srtp_null_auth_alloc(srtp_auth_t **a, int key_len, int out_len);
-
-srtp_err_status_t srtp_null_auth_dealloc(srtp_auth_t *a);
-
-srtp_err_status_t srtp_null_auth_init(srtp_null_auth_ctx_t *state, const uint8_t *key, int key_len);
-
-srtp_err_status_t srtp_null_auth_compute(srtp_null_auth_ctx_t *state, uint8_t *message, int msg_octets, int tag_len, uint8_t *result);
-
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/crypto/include/rdb.h b/crypto/include/rdb.h
index 98314c1..208dff3 100644
--- a/crypto/include/rdb.h
+++ b/crypto/include/rdb.h
@@ -64,8 +64,6 @@
v128_t bitmask;
} srtp_rdb_t;
-#define rdb_bits_in_bitmask (8 * sizeof(v128_t))
-
/*
* srtp_rdb_init
*
diff --git a/crypto/kernel/crypto_kernel.c b/crypto/kernel/crypto_kernel.c
index df6af7d..ef0f03f 100644
--- a/crypto/kernel/crypto_kernel.c
+++ b/crypto/kernel/crypto_kernel.c
@@ -60,7 +60,7 @@
/* crypto_kernel is a global variable, the only one of its datatype */
-srtp_crypto_kernel_t crypto_kernel = {
+static srtp_crypto_kernel_t crypto_kernel = {
srtp_crypto_kernel_state_insecure, /* start off in insecure state */
NULL, /* no cipher types yet */
NULL, /* no auth types yet */
@@ -69,7 +69,7 @@
#define MAX_RNG_TRIALS 25
-srtp_err_status_t srtp_crypto_kernel_init()
+srtp_err_status_t srtp_crypto_kernel_init(void)
{
srtp_err_status_t status;
@@ -101,10 +101,6 @@
if (status) {
return status;
}
- status = srtp_crypto_kernel_load_debug_module(&srtp_mod_stat);
- if (status) {
- return status;
- }
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_alloc);
if (status) {
return status;
@@ -172,7 +168,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_crypto_kernel_status()
+srtp_err_status_t srtp_crypto_kernel_status(void)
{
srtp_err_status_t status;
srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
@@ -213,7 +209,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_crypto_kernel_list_debug_modules()
+srtp_err_status_t srtp_crypto_kernel_list_debug_modules(void)
{
srtp_kernel_debug_module_t *dm = crypto_kernel.debug_module_list;
@@ -232,7 +228,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_crypto_kernel_shutdown()
+srtp_err_status_t srtp_crypto_kernel_shutdown(void)
{
/*
* free dynamic memory used in crypto_kernel at present
@@ -277,7 +273,8 @@
srtp_cipher_type_id_t id,
int replace)
{
- srtp_kernel_cipher_type_t *ctype, *new_ctype;
+ srtp_kernel_cipher_type_t *ctype;
+ srtp_kernel_cipher_type_t *new_ctype = NULL;
srtp_err_status_t status;
/* defensive coding */
@@ -354,7 +351,8 @@
srtp_auth_type_id_t id,
int replace)
{
- srtp_kernel_auth_type_t *atype, *new_atype;
+ srtp_kernel_auth_type_t *atype;
+ srtp_kernel_auth_type_t *new_atype = NULL;
srtp_err_status_t status;
/* defensive coding */
diff --git a/crypto/kernel/err.c b/crypto/kernel/err.c
index 9db5bfb..cfdf985 100644
--- a/crypto/kernel/err.c
+++ b/crypto/kernel/err.c
@@ -54,7 +54,7 @@
static FILE *srtp_err_file = NULL;
-srtp_err_status_t srtp_err_reporting_init()
+srtp_err_status_t srtp_err_reporting_init(void)
{
#ifdef ERR_REPORTING_STDOUT
srtp_err_file = stdout;
diff --git a/crypto/kernel/key.c b/crypto/kernel/key.c
index 0466195..5e6a188 100644
--- a/crypto/kernel/key.c
+++ b/crypto/kernel/key.c
@@ -77,14 +77,6 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_key_limit_check(const srtp_key_limit_t key)
-{
- if (key->state == srtp_key_state_expired) {
- return srtp_err_status_key_expired;
- }
- return srtp_err_status_ok;
-}
-
srtp_key_event_t srtp_key_limit_update(srtp_key_limit_t key)
{
#ifdef NO_64BIT_MATH
diff --git a/crypto/math/datatypes.c b/crypto/math/datatypes.c
index 1015888..52c7136 100644
--- a/crypto/math/datatypes.c
+++ b/crypto/math/datatypes.c
@@ -53,24 +53,15 @@
#include "datatypes.h"
-static const int8_t octet_weight[256] = {
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4,
- 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4,
- 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
- 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5,
- 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
- 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
-};
+#if defined(__SSE2__)
+#include <tmmintrin.h>
+#endif
-int octet_get_weight(uint8_t octet)
-{
- return (int)octet_weight[octet];
-}
+#if defined(_MSC_VER)
+#define ALIGNMENT(N) __declspec(align(N))
+#else
+#define ALIGNMENT(N) __attribute__((aligned(N)))
+#endif
/*
* bit_string is a buffer that is used to hold output strings, e.g.
@@ -81,10 +72,10 @@
/* include space for null terminator */
static char bit_string[MAX_PRINT_STRING_LEN + 1];
-uint8_t srtp_nibble_to_hex_char(uint8_t nibble)
+static uint8_t srtp_nibble_to_hex_char(uint8_t nibble)
{
- char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ static const char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
return buf[nibble & 0xF];
}
@@ -142,6 +133,9 @@
void v128_copy_octet_string(v128_t *x, const uint8_t s[16])
{
+#if defined(__SSE2__)
+ _mm_storeu_si128((__m128i *)(x), _mm_loadu_si128((const __m128i *)(s)));
+#else
#ifdef ALIGNMENT_32BIT_REQUIRED
if ((((uint32_t)&s[0]) & 0x3) != 0)
#endif
@@ -170,106 +164,67 @@
v128_copy(x, v);
}
#endif
+#endif /* defined(__SSE2__) */
}
-#ifndef DATATYPES_USE_MACROS /* little functions are not macros */
+#if defined(__SSSE3__)
-void v128_set_to_zero(v128_t *x)
+/* clang-format off */
+
+ALIGNMENT(16)
+static const uint8_t right_shift_masks[5][16] = {
+ { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u,
+ 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u },
+ { 0x80, 0x80, 0x80, 0x80, 0u, 1u, 2u, 3u,
+ 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u },
+ { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u },
+ { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0u, 1u, 2u, 3u },
+ /* needed for bitvector_left_shift */
+ { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }
+};
+
+ALIGNMENT(16)
+static const uint8_t left_shift_masks[4][16] = {
+ { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u,
+ 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u },
+ { 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u,
+ 12u, 13u, 14u, 15u, 0x80, 0x80, 0x80, 0x80 },
+ { 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
+ { 12u, 13u, 14u, 15u, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }
+};
+
+/* clang-format on */
+
+void v128_left_shift(v128_t *x, int shift)
{
- _v128_set_to_zero(x);
-}
-
-void v128_copy(v128_t *x, const v128_t *y)
-{
- _v128_copy(x, y);
-}
-
-void v128_xor(v128_t *z, v128_t *x, v128_t *y)
-{
- _v128_xor(z, x, y);
-}
-
-void v128_and(v128_t *z, v128_t *x, v128_t *y)
-{
- _v128_and(z, x, y);
-}
-
-void v128_or(v128_t *z, v128_t *x, v128_t *y)
-{
- _v128_or(z, x, y);
-}
-
-void v128_complement(v128_t *x)
-{
- _v128_complement(x);
-}
-
-int v128_is_eq(const v128_t *x, const v128_t *y)
-{
- return _v128_is_eq(x, y);
-}
-
-int v128_xor_eq(v128_t *x, const v128_t *y)
-{
- return _v128_xor_eq(x, y);
-}
-
-int v128_get_bit(const v128_t *x, int i)
-{
- return _v128_get_bit(x, i);
-}
-
-void v128_set_bit(v128_t *x, int i)
-{
- _v128_set_bit(x, i);
-}
-
-void v128_clear_bit(v128_t *x, int i)
-{
- _v128_clear_bit(x, i);
-}
-
-void v128_set_bit_to(v128_t *x, int i, int y)
-{
- _v128_set_bit_to(x, i, y);
-}
-
-#endif /* DATATYPES_USE_MACROS */
-
-void v128_right_shift(v128_t *x, int shift)
-{
- const int base_index = shift >> 5;
- const int bit_index = shift & 31;
- int i, from;
- uint32_t b;
-
if (shift > 127) {
v128_set_to_zero(x);
return;
}
- if (bit_index == 0) {
- /* copy each word from left size to right side */
- x->v32[4 - 1] = x->v32[4 - 1 - base_index];
- for (i = 4 - 1; i > base_index; i--)
- x->v32[i - 1] = x->v32[i - 1 - base_index];
+ const int base_index = shift >> 5;
+ const int bit_index = shift & 31;
- } else {
- /* set each word to the "or" of the two bit-shifted words */
- for (i = 4; i > base_index; i--) {
- from = i - 1 - base_index;
- b = x->v32[from] << bit_index;
- if (from > 0)
- b |= x->v32[from - 1] >> (32 - bit_index);
- x->v32[i - 1] = b;
- }
- }
+ __m128i mm = _mm_loadu_si128((const __m128i *)x);
+ __m128i mm_shift_right = _mm_cvtsi32_si128(bit_index);
+ __m128i mm_shift_left = _mm_cvtsi32_si128(32 - bit_index);
+ mm = _mm_shuffle_epi8(mm, ((const __m128i *)left_shift_masks)[base_index]);
- /* now wrap up the final portion */
- for (i = 0; i < base_index; i++)
- x->v32[i] = 0;
+ __m128i mm1 = _mm_srl_epi32(mm, mm_shift_right);
+ __m128i mm2 = _mm_sll_epi32(mm, mm_shift_left);
+ mm2 = _mm_srli_si128(mm2, 4);
+ mm1 = _mm_or_si128(mm1, mm2);
+
+ _mm_storeu_si128((__m128i *)x, mm1);
}
+#else /* defined(__SSSE3__) */
+
void v128_left_shift(v128_t *x, int shift)
{
int i;
@@ -296,27 +251,10 @@
x->v32[i] = 0;
}
+#endif /* defined(__SSSE3__) */
+
/* functions manipulating bitvector_t */
-#ifndef DATATYPES_USE_MACROS /* little functions are not macros */
-
-int bitvector_get_bit(const bitvector_t *v, int bit_index)
-{
- return _bitvector_get_bit(v, bit_index);
-}
-
-void bitvector_set_bit(bitvector_t *v, int bit_index)
-{
- _bitvector_set_bit(v, bit_index);
-}
-
-void bitvector_clear_bit(bitvector_t *v, int bit_index)
-{
- _bitvector_clear_bit(v, bit_index);
-}
-
-#endif /* DATATYPES_USE_MACROS */
-
int bitvector_alloc(bitvector_t *v, unsigned long length)
{
unsigned long l;
@@ -326,6 +264,7 @@
(length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1));
l = length / bits_per_word * bytes_per_word;
+ l = (l + 15ul) & ~15ul;
/* allocate memory, then set parameters */
if (l == 0) {
@@ -361,27 +300,73 @@
memset(x->word, 0, x->length >> 3);
}
-char *bitvector_bit_string(bitvector_t *x, char *buf, int len)
+#if defined(__SSSE3__)
+
+void bitvector_left_shift(bitvector_t *x, int shift)
{
- int j, i;
- uint32_t mask;
-
- for (j = i = 0; j < (int)(x->length >> 5) && i < len - 1; j++) {
- for (mask = 0x80000000; mask > 0; mask >>= 1) {
- if (x->word[j] & mask)
- buf[i] = '1';
- else
- buf[i] = '0';
- ++i;
- if (i >= len - 1)
- break;
- }
+ if ((uint32_t)shift >= x->length) {
+ bitvector_set_to_zero(x);
+ return;
}
- buf[i] = 0; /* null terminate string */
- return buf;
+ const int base_index = shift >> 5;
+ const int bit_index = shift & 31;
+ const int vec_length = (x->length + 127u) >> 7;
+ const __m128i *from = ((const __m128i *)x->word) + (base_index >> 2);
+ __m128i *to = (__m128i *)x->word;
+ __m128i *const end = to + vec_length;
+
+ __m128i mm_right_shift_mask =
+ ((const __m128i *)right_shift_masks)[4u - (base_index & 3u)];
+ __m128i mm_left_shift_mask =
+ ((const __m128i *)left_shift_masks)[base_index & 3u];
+ __m128i mm_shift_right = _mm_cvtsi32_si128(bit_index);
+ __m128i mm_shift_left = _mm_cvtsi32_si128(32 - bit_index);
+
+ __m128i mm_current = _mm_loadu_si128(from);
+ __m128i mm_current_r = _mm_srl_epi32(mm_current, mm_shift_right);
+ __m128i mm_current_l = _mm_sll_epi32(mm_current, mm_shift_left);
+
+ while ((end - from) >= 2) {
+ ++from;
+ __m128i mm_next = _mm_loadu_si128(from);
+
+ __m128i mm_next_r = _mm_srl_epi32(mm_next, mm_shift_right);
+ __m128i mm_next_l = _mm_sll_epi32(mm_next, mm_shift_left);
+ mm_current_l = _mm_alignr_epi8(mm_next_l, mm_current_l, 4);
+ mm_current = _mm_or_si128(mm_current_r, mm_current_l);
+
+ mm_current = _mm_shuffle_epi8(mm_current, mm_left_shift_mask);
+
+ __m128i mm_temp_next = _mm_srli_si128(mm_next_l, 4);
+ mm_temp_next = _mm_or_si128(mm_next_r, mm_temp_next);
+
+ mm_temp_next = _mm_shuffle_epi8(mm_temp_next, mm_right_shift_mask);
+ mm_current = _mm_or_si128(mm_temp_next, mm_current);
+
+ _mm_storeu_si128(to, mm_current);
+ ++to;
+
+ mm_current_r = mm_next_r;
+ mm_current_l = mm_next_l;
+ }
+
+ mm_current_l = _mm_srli_si128(mm_current_l, 4);
+ mm_current = _mm_or_si128(mm_current_r, mm_current_l);
+
+ mm_current = _mm_shuffle_epi8(mm_current, mm_left_shift_mask);
+
+ _mm_storeu_si128(to, mm_current);
+ ++to;
+
+ while (to < end) {
+ _mm_storeu_si128(to, _mm_setzero_si128());
+ ++to;
+ }
}
+#else /* defined(__SSSE3__) */
+
void bitvector_left_shift(bitvector_t *x, int shift)
{
int i;
@@ -410,16 +395,82 @@
x->word[i] = 0;
}
-int srtp_octet_string_is_eq(uint8_t *a, uint8_t *b, int len)
-{
- uint8_t *end = b + len;
- uint8_t accumulator = 0;
+#endif /* defined(__SSSE3__) */
+int srtp_octet_string_is_eq(const uint8_t *a, const uint8_t *b, int len)
+{
/*
* We use this somewhat obscure implementation to try to ensure the running
* time only depends on len, even accounting for compiler optimizations.
* The accumulator ends up zero iff the strings are equal.
*/
+ const uint8_t *end = b + len;
+ uint32_t accumulator = 0;
+
+#if defined(__SSE2__)
+ __m128i mm_accumulator1 = _mm_setzero_si128();
+ __m128i mm_accumulator2 = _mm_setzero_si128();
+ for (int i = 0, n = len >> 5; i < n; ++i, a += 32, b += 32) {
+ __m128i mm_a1 = _mm_loadu_si128((const __m128i *)a);
+ __m128i mm_b1 = _mm_loadu_si128((const __m128i *)b);
+ __m128i mm_a2 = _mm_loadu_si128((const __m128i *)(a + 16));
+ __m128i mm_b2 = _mm_loadu_si128((const __m128i *)(b + 16));
+ mm_a1 = _mm_xor_si128(mm_a1, mm_b1);
+ mm_a2 = _mm_xor_si128(mm_a2, mm_b2);
+ mm_accumulator1 = _mm_or_si128(mm_accumulator1, mm_a1);
+ mm_accumulator2 = _mm_or_si128(mm_accumulator2, mm_a2);
+ }
+
+ mm_accumulator1 = _mm_or_si128(mm_accumulator1, mm_accumulator2);
+
+ if ((end - b) >= 16) {
+ __m128i mm_a1 = _mm_loadu_si128((const __m128i *)a);
+ __m128i mm_b1 = _mm_loadu_si128((const __m128i *)b);
+ mm_a1 = _mm_xor_si128(mm_a1, mm_b1);
+ mm_accumulator1 = _mm_or_si128(mm_accumulator1, mm_a1);
+ a += 16;
+ b += 16;
+ }
+
+ if ((end - b) >= 8) {
+ __m128i mm_a1 = _mm_loadl_epi64((const __m128i *)a);
+ __m128i mm_b1 = _mm_loadl_epi64((const __m128i *)b);
+ mm_a1 = _mm_xor_si128(mm_a1, mm_b1);
+ mm_accumulator1 = _mm_or_si128(mm_accumulator1, mm_a1);
+ a += 8;
+ b += 8;
+ }
+
+ mm_accumulator1 = _mm_or_si128(
+ mm_accumulator1, _mm_unpackhi_epi64(mm_accumulator1, mm_accumulator1));
+ mm_accumulator1 =
+ _mm_or_si128(mm_accumulator1, _mm_srli_si128(mm_accumulator1, 4));
+ accumulator = _mm_cvtsi128_si32(mm_accumulator1);
+#else
+ uint32_t accumulator2 = 0;
+ for (int i = 0, n = len >> 3; i < n; ++i, a += 8, b += 8) {
+ uint32_t a_val1, b_val1;
+ uint32_t a_val2, b_val2;
+ memcpy(&a_val1, a, sizeof(a_val1));
+ memcpy(&b_val1, b, sizeof(b_val1));
+ memcpy(&a_val2, a + 4, sizeof(a_val2));
+ memcpy(&b_val2, b + 4, sizeof(b_val2));
+ accumulator |= a_val1 ^ b_val1;
+ accumulator2 |= a_val2 ^ b_val2;
+ }
+
+ accumulator |= accumulator2;
+
+ if ((end - b) >= 4) {
+ uint32_t a_val, b_val;
+ memcpy(&a_val, a, sizeof(a_val));
+ memcpy(&b_val, b, sizeof(b_val));
+ accumulator |= a_val ^ b_val;
+ a += 4;
+ b += 4;
+ }
+#endif
+
while (b < end)
accumulator |= (*a++ ^ *b++);
@@ -429,62 +480,21 @@
void srtp_cleanse(void *s, size_t len)
{
+#if defined(__GNUC__)
+ memset(s, 0, len);
+ __asm__ __volatile__("" : : "r"(s) : "memory");
+#else
volatile unsigned char *p = (volatile unsigned char *)s;
while (len--)
*p++ = 0;
+#endif
}
void octet_string_set_to_zero(void *s, size_t len)
{
-#if defined(OPENSSL) && !defined(OPENSSL_CLEANSE_BROKEN)
+#if defined(OPENSSL)
OPENSSL_cleanse(s, len);
#else
srtp_cleanse(s, len);
#endif
}
-
-#ifdef TESTAPP_SOURCE
-
-static const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static int base64_block_to_octet_triple(char *out, char *in)
-{
- unsigned char sextets[4] = { 0 };
- int j = 0;
- int i;
-
- for (i = 0; i < 4; i++) {
- char *p = strchr(b64chars, in[i]);
- if (p != NULL)
- sextets[i] = p - b64chars;
- else
- j++;
- }
-
- out[0] = (sextets[0] << 2) | (sextets[1] >> 4);
- if (j < 2)
- out[1] = (sextets[1] << 4) | (sextets[2] >> 2);
- if (j < 1)
- out[2] = (sextets[2] << 6) | sextets[3];
- return j;
-}
-
-int base64_string_to_octet_string(char *out, int *pad, char *in, int len)
-{
- int k = 0;
- int i = 0;
- int j = 0;
- if (len % 4 != 0)
- return 0;
-
- while (i < len && j == 0) {
- j = base64_block_to_octet_triple(out + k, in + i);
- k += 3;
- i += 4;
- }
- *pad = j;
- return i;
-}
-
-#endif
diff --git a/crypto/math/stat.c b/crypto/math/stat.c
deleted file mode 100644
index d300453..0000000
--- a/crypto/math/stat.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * stats.c
- *
- * statistical tests
- *
- * David A. McGrew
- * Cisco Systems, Inc.
- */
-
-/*
- *
- * Copyright (c) 2001-2017, Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the Cisco Systems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "stat.h"
-
-srtp_debug_module_t srtp_mod_stat = {
- 0, /* debugging is off by default */
- (char *)"stat test" /* printable module name */
-};
-
-/*
- * each test assumes that 20,000 bits (2500 octets) of data is
- * provided as input
- */
-
-#define STAT_TEST_DATA_LEN 2500
-
-srtp_err_status_t stat_test_monobit(uint8_t *data)
-{
- uint8_t *data_end = data + STAT_TEST_DATA_LEN;
- uint16_t ones_count;
-
- ones_count = 0;
- while (data < data_end) {
- ones_count += octet_get_weight(*data);
- data++;
- }
-
- debug_print(srtp_mod_stat, "bit count: %d", ones_count);
-
- if ((ones_count < 9725) || (ones_count > 10275))
- return srtp_err_status_algo_fail;
-
- return srtp_err_status_ok;
-}
-
-srtp_err_status_t stat_test_poker(uint8_t *data)
-{
- int i;
- uint8_t *data_end = data + STAT_TEST_DATA_LEN;
- double poker;
- uint16_t f[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- while (data < data_end) {
- f[*data & 0x0f]++; /* increment freq. count for low nibble */
- f[(*data) >> 4]++; /* increment freq. count for high nibble */
- data++;
- }
-
- poker = 0.0;
- for (i = 0; i < 16; i++)
- poker += (double)f[i] * f[i];
-
- poker *= (16.0 / 5000.0);
- poker -= 5000.0;
-
- debug_print(srtp_mod_stat, "poker test: %f\n", poker);
-
- if ((poker < 2.16) || (poker > 46.17))
- return srtp_err_status_algo_fail;
-
- return srtp_err_status_ok;
-}
-
-/*
- * runs[i] holds the number of runs of size (i-1)
- */
-
-srtp_err_status_t stat_test_runs(uint8_t *data)
-{
- uint8_t *data_end = data + STAT_TEST_DATA_LEN;
- uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 };
- uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
- uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
- uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
- int state = 0;
- uint16_t mask;
- int i;
-
- /*
- * the state variable holds the number of bits in the
- * current run (or gap, if negative)
- */
-
- while (data < data_end) {
- /* loop over the bits of this byte */
- for (mask = 1; mask < 256; mask <<= 1) {
- if (*data & mask) {
- /* next bit is a one */
- if (state > 0) {
- /* prefix is a run, so increment the run-count */
- state++;
-
- /* check for long runs */
- if (state > 25) {
- debug_print(srtp_mod_stat, ">25 runs: %d", state);
- return srtp_err_status_algo_fail;
- }
-
- } else if (state < 0) {
- /* prefix is a gap */
- if (state < -25) {
- debug_print(srtp_mod_stat, ">25 gaps: %d", state);
- return srtp_err_status_algo_fail; /* long-runs test
- failed */
- }
- if (state < -6) {
- state = -6; /* group together gaps > 5 */
- }
- gaps[-1 - state]++; /* increment gap count */
- state = 1; /* set state at one set bit */
- } else {
- /* state is zero; this happens only at initialization */
- state = 1;
- }
- } else {
- /* next bit is a zero */
- if (state > 0) {
- /* prefix is a run */
- if (state > 25) {
- debug_print(srtp_mod_stat, ">25 runs (2): %d", state);
- return srtp_err_status_algo_fail; /* long-runs test
- failed */
- }
- if (state > 6) {
- state = 6; /* group together runs > 5 */
- }
- runs[state - 1]++; /* increment run count */
- state = -1; /* set state at one zero bit */
- } else if (state < 0) {
- /* prefix is a gap, so increment gap-count (decrement state)
- */
- state--;
-
- /* check for long gaps */
- if (state < -25) {
- debug_print(srtp_mod_stat, ">25 gaps (2): %d", state);
- return srtp_err_status_algo_fail;
- }
-
- } else {
- /* state is zero; this happens only at initialization */
- state = -1;
- }
- }
- }
-
- /* move along to next octet */
- data++;
- }
-
- if (srtp_mod_stat.on) {
- debug_print0(srtp_mod_stat, "runs test");
- for (i = 0; i < 6; i++)
- debug_print(srtp_mod_stat, " runs[]: %d", runs[i]);
- for (i = 0; i < 6; i++)
- debug_print(srtp_mod_stat, " gaps[]: %d", gaps[i]);
- }
-
- /* check run and gap counts against the fixed limits */
- for (i = 0; i < 6; i++)
- if ((runs[i] < lo_value[i]) || (runs[i] > hi_value[i]) ||
- (gaps[i] < lo_value[i]) || (gaps[i] > hi_value[i]))
- return srtp_err_status_algo_fail;
-
- return srtp_err_status_ok;
-}
diff --git a/crypto/replay/rdb.c b/crypto/replay/rdb.c
index ab1c7b5..d8c2b38 100644
--- a/crypto/replay/rdb.c
+++ b/crypto/replay/rdb.c
@@ -49,6 +49,8 @@
#include "rdb.h"
+#define rdb_bits_in_bitmask (8 * sizeof(v128_t))
+
/*
* this implementation of a replay database works as follows:
*
diff --git a/crypto/replay/rdbx.c b/crypto/replay/rdbx.c
index 40cba01..e12005c 100644
--- a/crypto/replay/rdbx.c
+++ b/crypto/replay/rdbx.c
@@ -279,7 +279,7 @@
{
if (delta > 0) {
/* shift forward by delta */
- srtp_index_advance(&rdbx->index, delta);
+ srtp_index_advance(&rdbx->index, (srtp_sequence_number_t)delta);
bitvector_left_shift(&rdbx->bitmask, delta);
bitvector_set_bit(&rdbx->bitmask,
bitvector_get_length(&rdbx->bitmask) - 1);
@@ -306,13 +306,13 @@
srtp_xtd_seq_num_t *guess,
srtp_sequence_number_t s)
{
-/*
- * if the sequence number and rollover counter in the rdbx are
- * non-zero, then use the srtp_index_guess(...) function, otherwise, just
- * set the rollover counter to zero (since the srtp_index_guess(...)
- * function might incorrectly guess that the rollover counter is
- * 0xffffffff)
- */
+ /*
+ * if the sequence number and rollover counter in the rdbx are
+ * non-zero, then use the srtp_index_guess(...) function, otherwise, just
+ * set the rollover counter to zero (since the srtp_index_guess(...)
+ * function might incorrectly guess that the rollover counter is
+ * 0xffffffff)
+ */
#ifdef NO_64BIT_MATH
/* seq_num_median = 0x8000 */
diff --git a/crypto/test/cipher_driver.c b/crypto/test/cipher_driver.c
index 8219a06..641d0c7 100644
--- a/crypto/test/cipher_driver.c
+++ b/crypto/test/cipher_driver.c
@@ -51,12 +51,7 @@
#include "getopt_s.h"
#include "cipher.h"
#include "cipher_priv.h"
-#ifdef GCM
-#include "aes_icm_ext.h"
-#include "aes_gcm.h"
-#else
-#include "aes_icm.h"
-#endif
+#include "datatypes.h"
#define PRINT_DEBUG 0
@@ -394,7 +389,7 @@
/* make sure that len doesn't cause us to overreach the buffer */
if (current + len > end)
- len = end - current;
+ len = (unsigned)(end - current);
status = srtp_cipher_encrypt(c, current, &len);
if (status)
@@ -443,7 +438,7 @@
{
int i, j;
srtp_err_status_t status;
- uint8_t *key;
+ uint8_t *key = NULL;
srtp_cipher_t **cipher_array;
/* pad klen allocation, to handle aes_icm reading 16 bytes for the
14-byte salt */
@@ -458,11 +453,13 @@
/* set ca to location of cipher_array */
*ca = cipher_array;
- /* allocate key */
- key = srtp_crypto_alloc(klen_pad);
- if (key == NULL) {
- srtp_crypto_free(cipher_array);
- return srtp_err_status_alloc_fail;
+ /* allocate key , allow zero key for example null cipher */
+ if (klen_pad > 0) {
+ key = srtp_crypto_alloc(klen_pad);
+ if (key == NULL) {
+ srtp_crypto_free(cipher_array);
+ return srtp_err_status_alloc_fail;
+ }
}
/* allocate and initialize an array of ciphers */
diff --git a/crypto/test/datatypes_driver.c b/crypto/test/datatypes_driver.c
index 96379be..95a14c5 100644
--- a/crypto/test/datatypes_driver.c
+++ b/crypto/test/datatypes_driver.c
@@ -102,13 +102,6 @@
printf("----------------------------------------------\n");
v128_set_to_zero(&x);
- v128_set_bit(&x, 0);
- for (i = 0; i < 128; i++) {
- printf("%s\n", v128_bit_string(&x));
- v128_right_shift(&x, 1);
- }
- printf("----------------------------------------------\n");
- v128_set_to_zero(&x);
v128_set_bit(&x, 127);
for (i = 0; i < 128; i++) {
printf("%s\n", v128_bit_string(&x));
@@ -146,39 +139,12 @@
void byte_order(void)
{
- int i;
+ size_t i;
v128_t e;
-#if 0
- v16_t b;
- v32_t c;
- v64_t d;
-
- for (i=0; i < sizeof(b); i++)
- b.octet[i] = i;
- for (i=0; i < sizeof(c); i++)
- c.octet[i] = i;
- for (i=0; i < sizeof(d); i++)
- d.octet[i] = i;
-
- printf("v128_t:\t%s\n", v128_hex_string(&e));
- printf("v64_t:\t%s\n", v64_hex_string(&d));
- printf("v32_t:\t%s\n", v32_hex_string(c));
- printf("v16_t:\t%s\n", v16_hex_string(b));
-
- c.value = 0x01020304;
- printf("v32_t:\t%s\n", v32_hex_string(c));
- b.value = 0x0102;
- printf("v16_t:\t%s\n", v16_hex_string(b));
-
- printf("uint16_t ordering:\n");
-
- c.value = 0x00010002;
- printf("v32_t:\t%x%x\n", c.v16[0], c.v16[1]);
-#endif
printf("byte ordering of crypto/math datatypes:\n");
for (i = 0; i < sizeof(e); i++)
- e.v8[i] = i;
+ e.v8[i] = (uint8_t)i;
printf("v128_t: %s\n", v128_hex_string(&e));
}
@@ -189,12 +155,12 @@
char raw[10];
int len;
- len = hex_string_to_octet_string(raw, hex1, strlen(hex1));
+ len = hex_string_to_octet_string(raw, hex1, (int)strlen(hex1));
printf("computed length: %d\tstring: %s\n", len,
octet_string_hex_string(raw, len / 2));
printf("expected length: %u\tstring: %s\n", (unsigned)strlen(hex1), hex1);
- len = hex_string_to_octet_string(raw, hex2, strlen(hex2));
+ len = hex_string_to_octet_string(raw, hex2, (int)strlen(hex2));
printf("computed length: %d\tstring: %s\n", len,
octet_string_hex_string(raw, len / 2));
printf("expected length: %d\tstring: %s\n", 16, "0123456789abcdef");
diff --git a/crypto/test/kernel_driver.c b/crypto/test/kernel_driver.c
index d29405a..929a247 100644
--- a/crypto/test/kernel_driver.c
+++ b/crypto/test/kernel_driver.c
@@ -113,15 +113,3 @@
return 0;
}
-
-/*
- * crypto_kernel_cipher_test() is a test of the cipher interface
- * of the crypto_kernel
- */
-
-srtp_err_status_t crypto_kernel_cipher_test(void)
-{
- /* not implemented yet! */
-
- return srtp_err_status_ok;
-}
diff --git a/include/ekt.h b/include/ekt.h
deleted file mode 100644
index a289a53..0000000
--- a/include/ekt.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * ekt.h
- *
- * interface to Encrypted Key Transport for SRTP
- *
- * David McGrew
- * Cisco Systems, Inc.
- */
-/*
- *
- * Copyright (c) 2001-2017 Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the Cisco Systems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * EKT implementation strategy
- *
- * use stream_template approach
- *
- * in srtp_unprotect, when a new stream appears, check if template has
- * EKT defined, and if it does, then apply EKT processing
- *
- * question: will we want to allow key-sharing templates in addition
- * to EKT templates? could define a new ssrc_type_t that's associated
- * with an EKT, e.g. ssrc_any_ekt.
- *
- *
- */
-
-#ifndef SRTP_EKT_H
-#define SRTP_EKT_H
-
-// left in commented out as reminder to not include private headers
-//#include "srtp_priv.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SRTP_EKT_CIPHER_DEFAULT 1
-#define SRTP_EKT_CIPHER_AES_128_ECB 1
-#define SRTP_EKT_CIPHER_AES_192_KEY_WRAP 2
-#define SRTP_EKT_CIPHER_AES_256_KEY_WRAP 3
-
-typedef uint16_t srtp_ekt_spi_t;
-
-unsigned srtp_ekt_octets_after_base_tag(srtp_ekt_stream_t ekt);
-
-/*
- * an srtp_policy_t structure can contain a pointer to an
- * srtp_ekt_policy_t structure
- *
- * this structure holds all of the high level EKT information, and it
- * is passed into libsrtp to indicate what policy should be in effect
- */
-
-typedef struct srtp_ekt_policy_ctx_t {
- srtp_ekt_spi_t spi; /* security parameter index */
- uint8_t ekt_cipher_type;
- uint8_t *ekt_key;
- struct srtp_ekt_policy_ctx_t *next_ekt_policy;
-} srtp_ekt_policy_ctx_t;
-
-/*
- * an srtp_ekt_data_t structure holds the data corresponding to an ekt key,
- * spi, and so on
- */
-
-typedef struct srtp_ekt_data_t {
- srtp_ekt_spi_t spi;
- uint8_t ekt_cipher_type;
- srtp_aes_expanded_key_t ekt_enc_key;
- srtp_aes_expanded_key_t ekt_dec_key;
- struct ekt_data_t *next_ekt_data;
-} srtp_ekt_data_t;
-
-/*
- * an srtp_stream_ctx_t can contain an srtp_ekt_stream_ctx_t
- *
- * an srtp_ekt_stream_ctx_t structure holds all of the EKT information for
- * a specific SRTP stream
- */
-
-typedef struct srtp_ekt_stream_ctx_t {
- srtp_ekt_data_t *data;
- uint16_t isn; /* initial sequence number */
- uint8_t encrypted_master_key[SRTP_MAX_KEY_LEN];
-} srtp_ekt_stream_ctx_t;
-
-srtp_err_status_t srtp_ekt_alloc(srtp_ekt_stream_t *stream_data,
- srtp_ekt_policy_t policy);
-
-srtp_err_status_t srtp_ekt_stream_init(srtp_ekt_stream_t e,
- srtp_ekt_spi_t spi,
- void *ekt_key,
- unsigned ekt_cipher_type);
-
-srtp_err_status_t srtp_ekt_stream_init_from_policy(srtp_ekt_stream_t e,
- srtp_ekt_policy_t p);
-
-srtp_err_status_t srtp_stream_init_from_ekt(srtp_stream_t stream,
- const void *srtcp_hdr,
- unsigned pkt_octet_len);
-
-void srtp_ekt_write_data(srtp_ekt_stream_t ekt,
- uint8_t *base_tag,
- unsigned base_tag_len,
- int *packet_len,
- srtp_xtd_seq_num_t pkt_index);
-
-/*
- * We handle EKT by performing some additional steps before
- * authentication (copying the auth tag into a temporary location,
- * zeroizing the "base tag" field in the packet)
- *
- * With EKT, the tag_len parameter is actually the base tag
- * length
- */
-srtp_err_status_t srtp_ekt_tag_verification_preproces(uint8_t *pkt_tag,
- uint8_t *pkt_tag_copy,
- unsigned tag_len);
-
-srtp_err_status_t srtp_ekt_tag_verification_postproces(uint8_t *pkt_tag,
- uint8_t *pkt_tag_copy,
- unsigned tag_len);
-
-/*
- * @brief EKT pre-processing for srtcp tag generation
- *
- * This function does the pre-processing of the SRTCP authentication
- * tag format. When EKT is used, it consists of writing the Encrypted
- * Master Key, the SRTP ROC, the Initial Sequence Number, and SPI
- * fields. The Base Authentication Tag field is set to the all-zero
- * value
- *
- * When EKT is not used, this function is a no-op.
- *
- */
-srtp_err_status_t srtp_stream_srtcp_auth_tag_generation_preprocess(
- const srtp_stream_t *s,
- uint8_t *pkt_tag,
- unsigned pkt_octet_len);
-
-/* it's not clear that a tag_generation_postprocess function is needed */
-srtp_err_status_t srtcp_auth_tag_generation_postprocess(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* SRTP_EKT_H */
diff --git a/include/getopt_s.h b/include/getopt_s.h
deleted file mode 100644
index 53fb25b..0000000
--- a/include/getopt_s.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * getopt.h
- *
- * interface to a minimal implementation of the getopt() function,
- * written so that test applications that use that function can run on
- * non-POSIX platforms
- *
- */
-/*
- *
- * Copyright (c) 2001-2017 Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the Cisco Systems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef GETOPT_S_H
-#define GETOPT_S_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * getopt_s(), optarg_s, and optind_s are small, locally defined
- * versions of the POSIX standard getopt() interface.
- */
-
-int getopt_s(int argc, char *const argv[], const char *optstring);
-
-extern char *optarg_s; /* defined in getopt.c */
-
-extern int optind_s; /* defined in getopt.c */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GETOPT_S_H */
diff --git a/include/srtp.h b/include/srtp.h
index 572bad6..40b0c78 100644
--- a/include/srtp.h
+++ b/include/srtp.h
@@ -94,6 +94,23 @@
#define SRTP_MAX_TRAILER_LEN (SRTP_MAX_TAG_LEN + SRTP_MAX_MKI_LEN)
/**
+ * SRTP_SRCTP_INDEX_LEN is the size the SRTCP index which is
+ * 4 bytes
+ */
+#define SRTP_SRCTP_INDEX_LEN 4
+
+/**
+ * SRTP_MAX_SRTCP_TRAILER_LEN is the maximum length of the SRTCP trailer
+ * (index, authentication tag and MKI) supported by libSRTP. This value is
+ * the maximum number of octets that will be added to an RTCP packet by
+ * srtp_protect_rtcp().
+ *
+ * @brief the maximum number of octets added by srtp_protect().
+ */
+#define SRTP_MAX_SRTCP_TRAILER_LEN \
+ (SRTP_SRCTP_INDEX_LEN + SRTP_MAX_TAG_LEN + SRTP_MAX_MKI_LEN)
+
+/**
* SRTP_MAX_NUM_MASTER_KEYS is the maximum number of Master keys for
* MKI supported by libSRTP.
*
@@ -271,16 +288,6 @@
} srtp_ssrc_t;
/**
- * @brief points to an EKT policy
- */
-typedef struct srtp_ekt_policy_ctx_t *srtp_ekt_policy_t;
-
-/**
- * @brief points to EKT stream data
- */
-typedef struct srtp_ekt_stream_ctx_t *srtp_ekt_stream_t;
-
-/**
* @brief srtp_master_key_t represents a master key. There will
* be a Master Key Index and the Master Key associated with the
* Master Key Index. Need to also keep track of the Master Key
@@ -329,8 +336,8 @@
/**< this stream. */
srtp_master_key_t **keys; /** Array of Master Key structures */
unsigned long num_master_keys; /** Number of master keys */
- srtp_ekt_policy_t ekt; /**< Pointer to the EKT policy structure */
- /**< for this stream (if any) */
+ void *deprecated_ekt; /**< DEPRECATED: pointer to the EKT */
+ /**< policy structure for this stream */
unsigned long window_size; /**< The window size to use for replay */
/**< protection. */
int allow_repeat_tx; /**< Whether retransmissions of */
@@ -1168,9 +1175,7 @@
* @brief identifies a particular SRTP profile
*
* An srtp_profile_t enumeration is used to identify a particular SRTP
- * profile (that is, a set of algorithms and parameters). These profiles
- * are defined for DTLS-SRTP:
- * https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml
+ * profile (that is, a set of algorithms and parameters).
*/
typedef enum {
srtp_profile_reserved = 0,
@@ -1179,7 +1184,7 @@
srtp_profile_null_sha1_80 = 5,
srtp_profile_null_sha1_32 = 6,
srtp_profile_aead_aes_128_gcm = 7,
- srtp_profile_aead_aes_256_gcm = 8,
+ srtp_profile_aead_aes_256_gcm = 8
} srtp_profile_t;
/**
@@ -1301,7 +1306,7 @@
* packet, and assumes that the RTCP packet is aligned on a 32-bit
* boundary.
*
- * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4
+ * @warning This function assumes that it can write SRTP_MAX_SRTCP_TRAILER_LEN
* into the location in memory immediately following the RTCP packet.
* Callers MUST ensure that this much writable memory is available in
* the buffer that holds the RTCP packet.
@@ -1342,7 +1347,7 @@
* packet, and assumes that the RTCP packet is aligned on a 32-bit
* boundary.
*
- * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4
+ * @warning This function assumes that it can write SRTP_MAX_SRTCP_TRAILER_LEN
* into the location in memory immediately following the RTCP packet.
* Callers MUST ensure that this much writable memory is available in
* the buffer that holds the RTCP packet.
diff --git a/include/srtp_priv.h b/include/srtp_priv.h
index d449f2a..8e78489 100644
--- a/include/srtp_priv.h
+++ b/include/srtp_priv.h
@@ -55,7 +55,6 @@
#include "cipher.h"
#include "auth.h"
#include "aes.h"
-#include "key.h"
#include "crypto_kernel.h"
#ifdef __cplusplus
@@ -67,6 +66,7 @@
typedef struct srtp_stream_ctx_t_ srtp_stream_ctx_t;
typedef srtp_stream_ctx_t *srtp_stream_t;
+typedef struct srtp_stream_list_ctx_t_ *srtp_stream_list_t;
/*
* the following declarations are libSRTP internal functions
@@ -98,12 +98,6 @@
const unsigned int max_master_keys);
/*
- * srtp_stream_init(s, p) initializes the srtp_stream_t s to
- * use the policy at the location p
- */
-srtp_err_status_t srtp_stream_init(srtp_stream_t srtp, const srtp_policy_t *p);
-
-/*
* libsrtp internal datatypes
*/
typedef enum direction_t {
@@ -147,18 +141,24 @@
srtp_sec_serv_t rtcp_services;
direction_t direction;
int allow_repeat_tx;
- srtp_ekt_stream_t ekt;
int *enc_xtn_hdr;
int enc_xtn_hdr_count;
uint32_t pending_roc;
- struct srtp_stream_ctx_t_ *next; /* linked list of streams */
+ /*
+ The next and prev pointers are here to allow for a stream list to be
+ implemented as an intrusive doubly-linked list (the former being the
+ default). Other stream list implementations can ignore these fields or use
+ them for some other purpose specific to the stream list implementation.
+ */
+ struct srtp_stream_ctx_t_ *next;
+ struct srtp_stream_ctx_t_ *prev;
} strp_stream_ctx_t_;
/*
* an srtp_ctx_t holds a stream list and a service description
*/
typedef struct srtp_ctx_t_ {
- struct srtp_stream_ctx_t_ *stream_list; /* linked list of streams */
+ srtp_stream_list_t stream_list; /* linked list of streams */
struct srtp_stream_ctx_t_ *stream_template; /* act as template for other */
/* streams */
void *user_data; /* user custom data */
diff --git a/include/stream_list_priv.h b/include/stream_list_priv.h
new file mode 100644
index 0000000..b61af18
--- /dev/null
+++ b/include/stream_list_priv.h
@@ -0,0 +1,122 @@
+/*
+ * stream_list_priv.h
+ *
+ * list of SRTP streams, keyed by SSRC
+ *
+ * Alba Mendez
+ */
+/*
+ *
+ * Copyright (c) 2001-2017, Cisco Systems, Inc.
+ * Copyright (c) 2022, Dolby Laboratories, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef SRTP_STREAM_LIST_PRIV_H
+#define SRTP_STREAM_LIST_PRIV_H
+
+#include "srtp_priv.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * srtp_stream_list_t holds a list of srtp_stream_t, each identified
+ * by their SSRC.
+ *
+ * the API was extracted to allow downstreams to override its
+ * implementation by defining the `SRTP_NO_STREAM_LIST` preprocessor
+ * directive, which removes the default implementation of these
+ * functions. if this is done, the `next` & `prev` fields are free for
+ * the implementation to use.
+ *
+ * this is still an internal interface; there is no stability
+ * guarantee--downstreams should watch this file for changes in
+ * signatures or semantics.
+ */
+
+/**
+ * allocate and initialize a stream list instance
+ */
+srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr);
+
+/**
+ * deallocate a stream list instance
+ *
+ * the list must be empty or else an error is returned.
+ */
+srtp_err_status_t srtp_stream_list_dealloc(srtp_stream_list_t list);
+
+/**
+ * insert a stream into the list
+ *
+ * returns srtp_err_status_alloc_fail if insertion failed due to unavailable
+ * capacity in the list. if operation succeeds, srtp_err_status_ok is returned
+ *
+ * if another stream with the same SSRC already exists in the list,
+ * behavior is undefined. if the SSRC field is mutated while the
+ * stream is inserted, further operations have undefined behavior
+ */
+srtp_err_status_t srtp_stream_list_insert(srtp_stream_list_t list,
+ srtp_stream_t stream);
+
+/*
+ * look up the stream corresponding to the specified SSRC and return it.
+ * if no such SSRC is found, NULL is returned.
+ */
+srtp_stream_t srtp_stream_list_get(srtp_stream_list_t list, uint32_t ssrc);
+
+/**
+ * remove the stream from the list.
+ *
+ * The stream to be removed is referenced "by value", i.e., by the pointer to be
+ * removed from the list. This pointer is obtained using `srtp_stream_list_get`
+ * or as callback parameter in `srtp_stream_list_for_each`.
+ */
+void srtp_stream_list_remove(srtp_stream_list_t list, srtp_stream_t stream);
+
+/**
+ * iterate through all stored streams. while iterating, it is allowed to delete
+ * the current element; any other mutation to the list is undefined behavior.
+ * returning non-zero from callback aborts the iteration.
+ */
+void srtp_stream_list_for_each(srtp_stream_list_t list,
+ int (*callback)(srtp_stream_t, void *),
+ void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SRTP_STREAM_LIST_PRIV_H */
diff --git a/srtp/ekt.c b/srtp/ekt.c
deleted file mode 100644
index 24af93b..0000000
--- a/srtp/ekt.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * ekt.c
- *
- * Encrypted Key Transport for SRTP
- *
- * David McGrew
- * Cisco Systems, Inc.
- */
-/*
- *
- * Copyright (c) 2001-2017 Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the Cisco Systems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "srtp_priv.h"
-#include "err.h"
-#include "ekt.h"
-
-extern srtp_debug_module_t mod_srtp;
-
-/*
- * The EKT Authentication Tag format.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * : Base Authentication Tag :
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * : Encrypted Master Key :
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Rollover Counter |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Initial Sequence Number | Security Parameter Index |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- */
-
-#define EKT_OCTETS_AFTER_BASE_TAG 24
-#define EKT_OCTETS_AFTER_EMK 8
-#define EKT_OCTETS_AFTER_ROC 4
-#define EKT_SPI_LEN 2
-
-unsigned srtp_ekt_octets_after_base_tag(srtp_ekt_stream_t ekt)
-{
- /*
- * if the pointer ekt is NULL, then EKT is not in effect, so we
- * indicate this by returning zero
- */
- if (!ekt)
- return 0;
-
- switch (ekt->data->ekt_cipher_type) {
- case SRTP_EKT_CIPHER_AES_128_ECB:
- return 16 + EKT_OCTETS_AFTER_EMK;
- break;
- default:
- break;
- }
- return 0;
-}
-
-static inline srtp_ekt_spi_t srtcp_packet_get_ekt_spi(
- const uint8_t *packet_start,
- unsigned pkt_octet_len)
-{
- const uint8_t *spi_location;
-
- spi_location = packet_start + (pkt_octet_len - EKT_SPI_LEN);
-
- return *((const srtp_ekt_spi_t *)spi_location);
-}
-
-static inline uint32_t srtcp_packet_get_ekt_roc(const uint8_t *packet_start,
- unsigned pkt_octet_len)
-{
- const uint8_t *roc_location;
-
- roc_location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_ROC);
-
- return *((const uint32_t *)roc_location);
-}
-
-static inline const uint8_t *srtcp_packet_get_emk_location(
- const uint8_t *packet_start,
- unsigned pkt_octet_len)
-{
- const uint8_t *location;
-
- location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_BASE_TAG);
-
- return location;
-}
-
-srtp_err_status_t srtp_ekt_alloc(srtp_ekt_stream_t *stream_data,
- srtp_ekt_policy_t policy)
-{
- /*
- * if the policy pointer is NULL, then EKT is not in use
- * so we just set the EKT stream data pointer to NULL
- */
- if (!policy) {
- *stream_data = NULL;
- return srtp_err_status_ok;
- }
-
- /* TODO */
- *stream_data = NULL;
-
- return srtp_err_status_ok;
-}
-
-srtp_err_status_t srtp_ekt_stream_init_from_policy(
- srtp_ekt_stream_t stream_data,
- srtp_ekt_policy_t policy)
-{
- if (!stream_data)
- return srtp_err_status_ok;
-
- return srtp_err_status_ok;
-}
-
-void aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len)
-{
-#ifndef GCM
- // FIXME: need to get this working through the crypto module interface
- srtp_aes_expanded_key_t expanded_key;
-
- srtp_aes_expand_decryption_key(key, key_len, &expanded_key);
- srtp_aes_decrypt(ciphertext, &expanded_key);
-#endif
-}
-
-/*
- * The function srtp_stream_init_from_ekt() initializes a stream using
- * the EKT data from an SRTCP trailer.
- */
-
-srtp_err_status_t srtp_stream_init_from_ekt(srtp_stream_t stream,
- const void *srtcp_hdr,
- unsigned pkt_octet_len)
-{
- srtp_err_status_t err;
- const uint8_t *master_key;
- srtp_policy_t srtp_policy;
- uint32_t roc;
-
- /*
- * NOTE: at present, we only support a single ekt_policy at a time.
- */
- if (stream->ekt->data->spi !=
- srtcp_packet_get_ekt_spi(srtcp_hdr, pkt_octet_len))
- return srtp_err_status_no_ctx;
-
- if (stream->ekt->data->ekt_cipher_type != SRTP_EKT_CIPHER_AES_128_ECB)
- return srtp_err_status_bad_param;
-
- /* decrypt the Encrypted Master Key field */
- master_key = srtcp_packet_get_emk_location(srtcp_hdr, pkt_octet_len);
- /* FIX!? This decrypts the master key in-place, and never uses it */
- /* FIX!? It's also passing to ekt_dec_key (which is an aes_expanded_key_t)
- * to a function which expects a raw (unexpanded) key */
- aes_decrypt_with_raw_key((void *)master_key,
- &stream->ekt->data->ekt_dec_key, 16);
-
- /* set the SRTP ROC */
- roc = srtcp_packet_get_ekt_roc(srtcp_hdr, pkt_octet_len);
- err = srtp_rdbx_set_roc(&stream->rtp_rdbx, roc);
- if (err)
- return err;
-
- err = srtp_stream_init(stream, &srtp_policy);
- if (err)
- return err;
-
- return srtp_err_status_ok;
-}
-
-void srtp_ekt_write_data(srtp_ekt_stream_t ekt,
- uint8_t *base_tag,
- unsigned base_tag_len,
- int *packet_len,
- srtp_xtd_seq_num_t pkt_index)
-{
- uint32_t roc;
- uint16_t isn;
- unsigned emk_len;
- uint8_t *packet;
-
- /* if the pointer ekt is NULL, then EKT is not in effect */
- if (!ekt) {
- debug_print0(mod_srtp, "EKT not in use");
- return;
- }
-
- /* write zeros into the location of the base tag */
- octet_string_set_to_zero(base_tag, base_tag_len);
- packet = base_tag + base_tag_len;
-
- /* copy encrypted master key into packet */
- emk_len = srtp_ekt_octets_after_base_tag(ekt);
- memcpy(packet, ekt->encrypted_master_key, emk_len);
- debug_print(mod_srtp, "writing EKT EMK: %s,",
- srtp_octet_string_hex_string(packet, emk_len));
- packet += emk_len;
-
- /* copy ROC into packet */
- roc = (uint32_t)(pkt_index >> 16);
- *((uint32_t *)packet) = be32_to_cpu(roc);
- debug_print(mod_srtp, "writing EKT ROC: %s,",
- srtp_octet_string_hex_string(packet, sizeof(roc)));
- packet += sizeof(roc);
-
- /* copy ISN into packet */
- isn = (uint16_t)pkt_index;
- *((uint16_t *)packet) = htons(isn);
- debug_print(mod_srtp, "writing EKT ISN: %s,",
- srtp_octet_string_hex_string(packet, sizeof(isn)));
- packet += sizeof(isn);
-
- /* copy SPI into packet */
- *((uint16_t *)packet) = htons(ekt->data->spi);
- debug_print(mod_srtp, "writing EKT SPI: %s,",
- srtp_octet_string_hex_string(packet, sizeof(ekt->data->spi)));
-
- /* increase packet length appropriately */
- *packet_len += EKT_OCTETS_AFTER_EMK + emk_len;
-}
-
-/*
- * The function call srtcp_ekt_trailer(ekt, auth_len, auth_tag )
- *
- * If the pointer ekt is NULL, then the other inputs are unaffected.
- *
- * auth_tag is a pointer to the pointer to the location of the
- * authentication tag in the packet. If EKT is in effect, then the
- * auth_tag pointer is set to the location
- */
-
-void srtcp_ekt_trailer(srtp_ekt_stream_t ekt,
- unsigned *auth_len,
- void **auth_tag,
- void *tag_copy)
-{
- /*
- * if there is no EKT policy, then the other inputs are unaffected
- */
- if (!ekt)
- return;
-
- /* copy auth_tag into temporary location */
-}
diff --git a/srtp/srtp.c b/srtp/srtp.c
index 030cc83..82f4a83 100644
--- a/srtp/srtp.c
+++ b/srtp/srtp.c
@@ -46,9 +46,9 @@
#include "config.h"
#include "srtp_priv.h"
+#include "stream_list_priv.h"
#include "crypto_types.h"
#include "err.h"
-#include "ekt.h" /* for SRTP Encrypted Key Transport */
#include "alloc.h" /* for srtp_crypto_alloc() */
#ifdef GCM
@@ -74,43 +74,66 @@
};
#define octets_in_rtp_header 12
-#define uint32s_in_rtp_header 3
#define octets_in_rtcp_header 8
-#define uint32s_in_rtcp_header 2
-#define octets_in_rtp_extn_hdr 4
+#define octets_in_rtp_xtn_hdr 4
-static srtp_err_status_t srtp_validate_rtp_header(void *rtp_hdr,
- int *pkt_octet_len)
+static uint32_t srtp_get_rtp_hdr_len(const srtp_hdr_t *hdr)
{
- srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
- int rtp_header_len;
+ return octets_in_rtp_header + 4 * hdr->cc;
+}
- if (*pkt_octet_len < octets_in_rtp_header)
+/*
+ * Returns the location of the header extention cast too a srtp_hdr_xtnd_t
+ * struct. Will always return a value and assumes that the caller has already
+ * verified that a header extension is present by checking the x bit of
+ * srtp_hdr_t.
+ */
+static srtp_hdr_xtnd_t *srtp_get_rtp_xtn_hdr(srtp_hdr_t *hdr)
+{
+ uint32_t rtp_xtn_hdr_start = srtp_get_rtp_hdr_len(hdr);
+ return (srtp_hdr_xtnd_t *)((uint8_t *)hdr + rtp_xtn_hdr_start);
+}
+
+/*
+ * Returns the length of the extension header including the extension header
+ * header so will return a minium of 4. Assumes the srtp_hdr_xtnd_t is a valid
+ * pointer and that the caller has already verified that a header extension is
+ * valid by checking the x bit of the RTP header.
+ */
+static uint32_t srtp_get_rtp_xtn_hdr_len(const srtp_hdr_xtnd_t *xtn_hdr)
+{
+ return (ntohs(xtn_hdr->length) + 1) * 4;
+}
+
+static srtp_err_status_t srtp_validate_rtp_header(const void *rtp_hdr,
+ uint32_t pkt_octet_len)
+{
+ const srtp_hdr_t *hdr = (const srtp_hdr_t *)rtp_hdr;
+ uint32_t rtp_header_len;
+
+ if (pkt_octet_len < octets_in_rtp_header)
return srtp_err_status_bad_param;
/* Check RTP header length */
- rtp_header_len = octets_in_rtp_header + 4 * hdr->cc;
- if (hdr->x == 1)
- rtp_header_len += octets_in_rtp_extn_hdr;
-
- if (*pkt_octet_len < rtp_header_len)
+ rtp_header_len = srtp_get_rtp_hdr_len(hdr);
+ if (pkt_octet_len < rtp_header_len)
return srtp_err_status_bad_param;
- /* Verifing profile length. */
+ /* Verifying profile length. */
if (hdr->x == 1) {
- srtp_hdr_xtnd_t *xtn_hdr =
- (srtp_hdr_xtnd_t *)((uint32_t *)hdr + uint32s_in_rtp_header +
- hdr->cc);
- int profile_len = ntohs(xtn_hdr->length);
- rtp_header_len += profile_len * 4;
- /* profile length counts the number of 32-bit words */
- if (*pkt_octet_len < rtp_header_len)
+ if (pkt_octet_len < rtp_header_len + octets_in_rtp_xtn_hdr)
+ return srtp_err_status_bad_param;
+
+ rtp_header_len += srtp_get_rtp_xtn_hdr_len(
+ (const srtp_hdr_xtnd_t *)((const uint8_t *)hdr + rtp_header_len));
+ if (pkt_octet_len < rtp_header_len)
return srtp_err_status_bad_param;
}
+
return srtp_err_status_ok;
}
-const char *srtp_get_version_string()
+const char *srtp_get_version_string(void)
{
/*
* Simply return the autotools generated string
@@ -118,7 +141,7 @@
return SRTP_VER_STRING;
}
-unsigned int srtp_get_version()
+unsigned int srtp_get_version(void)
{
unsigned int major = 0, minor = 0, micro = 0;
unsigned int rv = 0;
@@ -149,8 +172,9 @@
return rv;
}
-srtp_err_status_t srtp_stream_dealloc(srtp_stream_ctx_t *stream,
- const srtp_stream_ctx_t *stream_template)
+static srtp_err_status_t srtp_stream_dealloc(
+ srtp_stream_ctx_t *stream,
+ const srtp_stream_ctx_t *stream_template)
{
srtp_err_status_t status;
unsigned int i = 0;
@@ -174,8 +198,8 @@
}
/*
- * deallocate cipher, if it is not the same as that in template
- */
+ * deallocate cipher, if it is not the same as that in template
+ */
if (template_session_keys &&
session_keys->rtp_cipher == template_session_keys->rtp_cipher) {
/* do nothing */
@@ -266,8 +290,6 @@
if (status)
return status;
- /* DAM - need to deallocate EKT here */
-
if (stream_template &&
stream->enc_xtn_hdr == stream_template->enc_xtn_hdr) {
/* do nothing */
@@ -281,14 +303,69 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
- const srtp_policy_t *p)
+/* try to insert stream in list or deallocate it */
+static srtp_err_status_t srtp_insert_or_dealloc_stream(srtp_stream_list_t list,
+ srtp_stream_t stream,
+ srtp_stream_t template)
+{
+ srtp_err_status_t status = srtp_stream_list_insert(list, stream);
+ /* on failure, ownership wasn't transferred and we need to deallocate */
+ if (status) {
+ srtp_stream_dealloc(stream, template);
+ }
+ return status;
+}
+
+struct remove_and_dealloc_streams_data {
+ srtp_err_status_t status;
+ srtp_stream_list_t list;
+ srtp_stream_t template;
+};
+
+static int remove_and_dealloc_streams_cb(srtp_stream_t stream, void *data)
+{
+ struct remove_and_dealloc_streams_data *d =
+ (struct remove_and_dealloc_streams_data *)data;
+ srtp_stream_list_remove(d->list, stream);
+ d->status = srtp_stream_dealloc(stream, d->template);
+ if (d->status) {
+ return 1;
+ }
+ return 0;
+}
+
+static srtp_err_status_t srtp_remove_and_dealloc_streams(
+ srtp_stream_list_t list,
+ srtp_stream_t template)
+{
+ struct remove_and_dealloc_streams_data data = { srtp_err_status_ok, list,
+ template };
+ srtp_stream_list_for_each(list, remove_and_dealloc_streams_cb, &data);
+ return data.status;
+}
+
+static srtp_err_status_t srtp_valid_policy(const srtp_policy_t *p)
+{
+ if (p != NULL && p->deprecated_ekt != NULL) {
+ return srtp_err_status_bad_param;
+ }
+
+ return srtp_err_status_ok;
+}
+
+static srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
+ const srtp_policy_t *p)
{
srtp_stream_ctx_t *str;
srtp_err_status_t stat;
unsigned int i = 0;
srtp_session_keys_t *session_keys = NULL;
+ stat = srtp_valid_policy(p);
+ if (stat != srtp_err_status_ok) {
+ return stat;
+ }
+
/*
* This function allocates the stream context, rtp and rtcp ciphers
* and auth functions, and key limit structure. If there is a
@@ -375,13 +452,6 @@
}
}
- /* allocate ekt data associated with stream */
- stat = srtp_ekt_alloc(&str->ekt, p->ekt);
- if (stat) {
- srtp_stream_dealloc(str, NULL);
- return stat;
- }
-
if (p->enc_xtn_hdr && p->enc_xtn_hdr_count > 0) {
srtp_cipher_type_id_t enc_xtn_hdr_cipher_type;
int enc_xtn_hdr_cipher_key_len;
@@ -448,9 +518,10 @@
* the SSRC
*/
-srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
- uint32_t ssrc,
- srtp_stream_ctx_t **str_ptr)
+static srtp_err_status_t srtp_stream_clone(
+ const srtp_stream_ctx_t *stream_template,
+ uint32_t ssrc,
+ srtp_stream_ctx_t **str_ptr)
{
srtp_err_status_t status;
srtp_stream_ctx_t *str;
@@ -541,15 +612,13 @@
str->rtp_services = stream_template->rtp_services;
str->rtcp_services = stream_template->rtcp_services;
- /* set pointer to EKT data associated with stream */
- str->ekt = stream_template->ekt;
-
/* copy information about extensions header encryption */
str->enc_xtn_hdr = stream_template->enc_xtn_hdr;
str->enc_xtn_hdr_count = stream_template->enc_xtn_hdr_count;
/* defensive coding */
str->next = NULL;
+ str->prev = NULL;
return srtp_err_status_ok;
}
@@ -756,26 +825,45 @@
int key_length)
{
switch (cipher->id) {
+ case SRTP_NULL_CIPHER:
+ return 0;
case SRTP_AES_ICM_128:
case SRTP_AES_ICM_192:
case SRTP_AES_ICM_256:
/* The legacy modes are derived from
* the configured key length on the policy */
return key_length - SRTP_SALT_LEN;
- break;
case SRTP_AES_GCM_128:
return key_length - SRTP_AEAD_SALT_LEN;
- break;
case SRTP_AES_GCM_256:
return key_length - SRTP_AEAD_SALT_LEN;
- break;
default:
return key_length;
- break;
}
}
-unsigned int srtp_validate_policy_master_keys(const srtp_policy_t *policy)
+/* Get the key length that the application should supply for the given cipher */
+static inline int full_key_length(const srtp_cipher_type_t *cipher)
+{
+ switch (cipher->id) {
+ case SRTP_NULL_CIPHER:
+ case SRTP_AES_ICM_128:
+ return SRTP_AES_ICM_128_KEY_LEN_WSALT;
+ case SRTP_AES_ICM_192:
+ return SRTP_AES_ICM_192_KEY_LEN_WSALT;
+ case SRTP_AES_ICM_256:
+ return SRTP_AES_ICM_256_KEY_LEN_WSALT;
+ case SRTP_AES_GCM_128:
+ return SRTP_AES_GCM_128_KEY_LEN_WSALT;
+ case SRTP_AES_GCM_256:
+ return SRTP_AES_GCM_256_KEY_LEN_WSALT;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int srtp_validate_policy_master_keys(
+ const srtp_policy_t *policy)
{
unsigned long i = 0;
@@ -869,6 +957,7 @@
srtp_err_status_t stat;
srtp_kdf_t kdf;
uint8_t tmp_key[MAX_SRTP_KEY_LEN];
+ int input_keylen, input_keylen_rtcp;
int kdf_keylen = 30, rtp_keylen, rtcp_keylen;
int rtp_base_key_len, rtp_salt_len;
int rtcp_base_key_len, rtcp_salt_len;
@@ -878,7 +967,7 @@
/* If RTP or RTCP have a key length > AES-128, assume matching kdf. */
/* TODO: kdf algorithm, master key length, and master salt length should
* be part of srtp_policy_t.
- */
+ */
session_keys = &srtp->session_keys[current_mki_index];
/* initialize key limit to maximum value */
@@ -905,12 +994,28 @@
session_keys->mki_size = master_key->mki_size;
+ input_keylen = full_key_length(session_keys->rtp_cipher->type);
+ input_keylen_rtcp = full_key_length(session_keys->rtcp_cipher->type);
+ if (input_keylen_rtcp > input_keylen) {
+ input_keylen = input_keylen_rtcp;
+ }
+
rtp_keylen = srtp_cipher_get_key_length(session_keys->rtp_cipher);
rtcp_keylen = srtp_cipher_get_key_length(session_keys->rtcp_cipher);
rtp_base_key_len =
base_key_length(session_keys->rtp_cipher->type, rtp_keylen);
rtp_salt_len = rtp_keylen - rtp_base_key_len;
+ /*
+ * We assume that the `key` buffer provided by the caller has a length
+ * equal to the greater of `rtp_keylen` and `rtcp_keylen`. Since we are
+ * about to read `input_keylen` bytes from it, we need to check that we will
+ * not overrun.
+ */
+ if ((rtp_keylen < input_keylen) && (rtcp_keylen < input_keylen)) {
+ return srtp_err_status_bad_param;
+ }
+
if (rtp_keylen > kdf_keylen) {
kdf_keylen = 46; /* AES-CTR mode is always used for KDF */
}
@@ -919,6 +1024,11 @@
kdf_keylen = 46; /* AES-CTR mode is always used for KDF */
}
+ if (input_keylen > kdf_keylen) {
+ kdf_keylen = 46; /* AES-CTR mode is always used for KDF */
+ }
+
+ debug_print(mod_srtp, "input key len: %d", input_keylen);
debug_print(mod_srtp, "srtp key len: %d", rtp_keylen);
debug_print(mod_srtp, "srtcp key len: %d", rtcp_keylen);
debug_print(mod_srtp, "base key len: %d", rtp_base_key_len);
@@ -931,7 +1041,7 @@
* the legacy CTR mode KDF, which uses a 112 bit master SALT.
*/
memset(tmp_key, 0x0, MAX_SRTP_KEY_LEN);
- memcpy(tmp_key, key, (rtp_base_key_len + rtp_salt_len));
+ memcpy(tmp_key, key, input_keylen);
/* initialize KDF state */
#if defined(OPENSSL) && defined(OPENSSL_KDF)
@@ -1213,11 +1323,16 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_stream_init(srtp_stream_ctx_t *srtp,
- const srtp_policy_t *p)
+static srtp_err_status_t srtp_stream_init(srtp_stream_ctx_t *srtp,
+ const srtp_policy_t *p)
{
srtp_err_status_t err;
+ err = srtp_valid_policy(p);
+ if (err != srtp_err_status_ok) {
+ return err;
+ }
+
debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)", p->ssrc.value);
/* initialize replay database */
@@ -1277,16 +1392,6 @@
return err;
}
- /*
- * if EKT is in use, then initialize the EKT data associated with
- * the stream
- */
- err = srtp_ekt_stream_init_from_policy(srtp->ekt, p->ekt);
- if (err) {
- srtp_rdbx_dealloc(&srtp->rtp_rdbx);
- return err;
- }
-
return srtp_err_status_ok;
}
@@ -1297,8 +1402,8 @@
void srtp_event_reporter(srtp_event_data_t *data)
{
- srtp_err_report(srtp_err_level_warning, "srtp: in stream 0x%x: ",
- data->ssrc);
+ srtp_err_report(srtp_err_level_warning,
+ "srtp: in stream 0x%x: ", data->ssrc);
switch (data->event) {
case event_ssrc_collision:
@@ -1382,7 +1487,7 @@
srtp_err_status_t status;
uint8_t keystream[257]; /* Maximum 2 bytes header + 255 bytes data. */
int keystream_pos;
- uint8_t *xtn_hdr_data = ((uint8_t *)xtn_hdr) + octets_in_rtp_extn_hdr;
+ uint8_t *xtn_hdr_data = ((uint8_t *)xtn_hdr) + octets_in_rtp_xtn_hdr;
uint8_t *xtn_hdr_end =
xtn_hdr_data + (ntohs(xtn_hdr->length) * sizeof(uint32_t));
@@ -1495,7 +1600,7 @@
static void srtp_calc_aead_iv(srtp_session_keys_t *session_keys,
v128_t *iv,
srtp_xtd_seq_num_t *seq,
- srtp_hdr_t *hdr)
+ const srtp_hdr_t *hdr)
{
v128_t in;
v128_t salt;
@@ -1534,11 +1639,11 @@
}
srtp_session_keys_t *srtp_get_session_keys(srtp_stream_ctx_t *stream,
- uint8_t *hdr,
- const unsigned int *pkt_octet_len,
+ const uint8_t *hdr,
+ unsigned int pkt_octet_len,
unsigned int *mki_size)
{
- unsigned int base_mki_start_location = *pkt_octet_len;
+ unsigned int base_mki_start_location = pkt_octet_len;
unsigned int mki_start_location = 0;
unsigned int tag_len = 0;
unsigned int i = 0;
@@ -1649,7 +1754,7 @@
return srtp_err_status_ok;
}
-static srtp_err_status_t srtp_get_est_pkt_index(srtp_hdr_t *hdr,
+static srtp_err_status_t srtp_get_est_pkt_index(const srtp_hdr_t *hdr,
srtp_stream_ctx_t *stream,
srtp_xtd_seq_num_t *est,
int *delta)
@@ -1687,7 +1792,7 @@
unsigned int use_mki)
{
srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
- uint32_t *enc_start; /* pointer to start of encrypted portion */
+ uint8_t *enc_start; /* pointer to start of encrypted portion */
int enc_octet_len = 0; /* number of octets in encrypted portion */
srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */
int delta; /* delta of local pkt idx and that in hdr */
@@ -1727,16 +1832,15 @@
* extension, if present; otherwise, it starts after the last csrc,
* if any are present
*/
- enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
+ enc_start = (uint8_t *)hdr + srtp_get_rtp_hdr_len(hdr);
if (hdr->x == 1) {
- xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
- enc_start += (ntohs(xtn_hdr->length) + 1);
+ xtn_hdr = srtp_get_rtp_xtn_hdr(hdr);
+ enc_start += srtp_get_rtp_xtn_hdr_len(xtn_hdr);
}
/* note: the passed size is without the auth tag */
- if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len))
+ if (!(enc_start <= (uint8_t *)hdr + *pkt_octet_len))
return srtp_err_status_parse_err;
- enc_octet_len =
- (int)(*pkt_octet_len - ((uint8_t *)enc_start - (uint8_t *)hdr));
+ enc_octet_len = (int)(*pkt_octet_len - (enc_start - (uint8_t *)hdr));
if (enc_octet_len < 0)
return srtp_err_status_parse_err;
@@ -1744,13 +1848,23 @@
* 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 */
- }
+ 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) {
+ 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);
}
@@ -1799,7 +1913,7 @@
/*
* Set the AAD over the RTP header
*/
- aad_len = (uint8_t *)enc_start - (uint8_t *)hdr;
+ aad_len = (uint32_t)(enc_start - (uint8_t *)hdr);
status =
srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t *)hdr, aad_len);
if (status) {
@@ -1807,7 +1921,7 @@
}
/* Encrypt the payload */
- status = srtp_cipher_encrypt(session_keys->rtp_cipher, (uint8_t *)enc_start,
+ status = srtp_cipher_encrypt(session_keys->rtp_cipher, enc_start,
(unsigned int *)&enc_octet_len);
if (status) {
return srtp_err_status_cipher_fail;
@@ -1816,9 +1930,8 @@
* If we're doing GCM, we need to get the tag
* and append that to the output
*/
- status =
- srtp_cipher_get_tag(session_keys->rtp_cipher,
- (uint8_t *)enc_start + enc_octet_len, &tag_len);
+ status = srtp_cipher_get_tag(session_keys->rtp_cipher,
+ enc_start + enc_octet_len, &tag_len);
if (status) {
return (srtp_err_status_cipher_fail);
}
@@ -1849,10 +1962,11 @@
void *srtp_hdr,
unsigned int *pkt_octet_len,
srtp_session_keys_t *session_keys,
- unsigned int mki_size)
+ unsigned int mki_size,
+ int advance_packet_index)
{
srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr;
- uint32_t *enc_start; /* pointer to start of encrypted portion */
+ uint8_t *enc_start; /* pointer to start of encrypted portion */
unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
v128_t iv;
srtp_err_status_t status;
@@ -1900,19 +2014,18 @@
* extension, if present; otherwise, it starts after the last csrc,
* if any are present
*/
- enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
+ enc_start = (uint8_t *)hdr + srtp_get_rtp_hdr_len(hdr);
if (hdr->x == 1) {
- xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
- enc_start += (ntohs(xtn_hdr->length) + 1);
+ xtn_hdr = srtp_get_rtp_xtn_hdr(hdr);
+ enc_start += srtp_get_rtp_xtn_hdr_len(xtn_hdr);
}
- if (!((uint8_t *)enc_start <=
- (uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size)))
+ if (!(enc_start <= (uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size)))
return srtp_err_status_parse_err;
/*
* We pass the tag down to the cipher when doing GCM mode
*/
enc_octet_len = (unsigned int)(*pkt_octet_len - mki_size -
- ((uint8_t *)enc_start - (uint8_t *)hdr));
+ (enc_start - (uint8_t *)hdr));
/*
* Sanity check the encrypted payload length against
@@ -1944,7 +2057,7 @@
/*
* Set the AAD for AES-GCM, which is the RTP header
*/
- aad_len = (uint8_t *)enc_start - (uint8_t *)hdr;
+ aad_len = (uint32_t)(enc_start - (uint8_t *)hdr);
status =
srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t *)hdr, aad_len);
if (status) {
@@ -2008,9 +2121,12 @@
return status;
}
- /* add new stream to the head of the stream_list */
- new_stream->next = ctx->stream_list;
- ctx->stream_list = new_stream;
+ /* add new stream to the list */
+ status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
+ ctx->stream_template);
+ if (status) {
+ return status;
+ }
/* set stream (the pointer used in this function) */
stream = new_stream;
@@ -2020,7 +2136,15 @@
* 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) {
+ uint32_t roc_to_set = (uint32_t)(est >> 16);
+ uint16_t seq_to_set = (uint16_t)(est & 0xFFFF);
+ srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, roc_to_set, seq_to_set);
+ 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;
@@ -2045,8 +2169,8 @@
unsigned int mki_index)
{
srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
- uint32_t *enc_start; /* pointer to start of encrypted portion */
- uint32_t *auth_start; /* pointer to start of auth. portion */
+ uint8_t *enc_start; /* pointer to start of encrypted portion */
+ uint8_t *auth_start; /* pointer to start of auth. portion */
int enc_octet_len = 0; /* number of octets in encrypted portion */
srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */
int delta; /* delta of local pkt idx and that in hdr */
@@ -2059,14 +2183,11 @@
unsigned int mki_size = 0;
srtp_session_keys_t *session_keys = NULL;
uint8_t *mki_location = NULL;
- int advance_packet_index = 0;
debug_print0(mod_srtp, "function srtp_protect");
- /* we assume the hdr is 32-bit aligned to start */
-
/* Verify RTP header */
- status = srtp_validate_rtp_header(rtp_hdr, pkt_octet_len);
+ status = srtp_validate_rtp_header(rtp_hdr, *pkt_octet_len);
if (status)
return status;
@@ -2092,9 +2213,12 @@
if (status)
return status;
- /* add new stream to the head of the stream_list */
- new_stream->next = ctx->stream_list;
- ctx->stream_list = new_stream;
+ /* add new stream to the list */
+ status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
+ ctx->stream_template);
+ if (status) {
+ return status;
+ }
/* set direction to outbound */
new_stream->direction = dir_srtp_sender;
@@ -2169,16 +2293,15 @@
* if we're not providing confidentiality, set enc_start to NULL
*/
if (stream->rtp_services & sec_serv_conf) {
- enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
+ enc_start = (uint8_t *)hdr + srtp_get_rtp_hdr_len(hdr);
if (hdr->x == 1) {
- xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
- enc_start += (ntohs(xtn_hdr->length) + 1);
+ xtn_hdr = srtp_get_rtp_xtn_hdr(hdr);
+ enc_start += srtp_get_rtp_xtn_hdr_len(xtn_hdr);
}
/* note: the passed size is without the auth tag */
- if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len))
+ if (!(enc_start <= (uint8_t *)hdr + *pkt_octet_len))
return srtp_err_status_parse_err;
- enc_octet_len =
- (int)(*pkt_octet_len - ((uint8_t *)enc_start - (uint8_t *)hdr));
+ enc_octet_len = (int)(*pkt_octet_len - (enc_start - (uint8_t *)hdr));
if (enc_octet_len < 0)
return srtp_err_status_parse_err;
} else {
@@ -2194,7 +2317,7 @@
* to indicate that no authentication is needed
*/
if (stream->rtp_services & sec_serv_auth) {
- auth_start = (uint32_t *)hdr;
+ auth_start = (uint8_t *)hdr;
auth_tag = (uint8_t *)hdr + *pkt_octet_len + mki_size;
} else {
auth_start = NULL;
@@ -2210,10 +2333,7 @@
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) {
+ if (status == srtp_err_status_pkt_idx_adv) {
srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, (uint32_t)(est >> 16),
(uint16_t)(est & 0xFFFF));
stream->pending_roc = 0;
@@ -2314,9 +2434,8 @@
/* if we're encrypting, exor keystream into the message */
if (enc_start) {
- status =
- srtp_cipher_encrypt(session_keys->rtp_cipher, (uint8_t *)enc_start,
- (unsigned int *)&enc_octet_len);
+ status = srtp_cipher_encrypt(session_keys->rtp_cipher, enc_start,
+ (unsigned int *)&enc_octet_len);
if (status)
return srtp_err_status_cipher_fail;
}
@@ -2332,7 +2451,7 @@
return status;
/* run auth func over packet */
- status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start,
+ status = srtp_auth_update(session_keys->rtp_auth, auth_start,
*pkt_octet_len);
if (status)
return status;
@@ -2373,8 +2492,8 @@
unsigned int use_mki)
{
srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr;
- uint32_t *enc_start; /* pointer to start of encrypted portion */
- uint32_t *auth_start; /* pointer to start of auth. portion */
+ uint8_t *enc_start; /* pointer to start of encrypted portion */
+ uint8_t *auth_start; /* pointer to start of auth. portion */
unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */
@@ -2393,10 +2512,8 @@
debug_print0(mod_srtp, "function srtp_unprotect");
- /* we assume the hdr is 32-bit aligned to start */
-
/* Verify RTP header */
- status = srtp_validate_rtp_header(srtp_hdr, pkt_octet_len);
+ status = srtp_validate_rtp_header(srtp_hdr, *pkt_octet_len);
if (status)
return status;
@@ -2465,9 +2582,9 @@
/* Determine if MKI is being used and what session keys should be used */
if (use_mki) {
- session_keys = srtp_get_session_keys(
- stream, (uint8_t *)hdr, (const unsigned int *)pkt_octet_len,
- &mki_size);
+ session_keys =
+ srtp_get_session_keys(stream, (const uint8_t *)hdr,
+ (unsigned int)*pkt_octet_len, &mki_size);
if (session_keys == NULL)
return srtp_err_status_bad_mki;
@@ -2483,7 +2600,7 @@
session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) {
return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr,
(unsigned int *)pkt_octet_len, session_keys,
- mki_size);
+ mki_size, advance_packet_index);
}
/* get tag length from stream */
@@ -2547,16 +2664,16 @@
* if we're not providing confidentiality, set enc_start to NULL
*/
if (stream->rtp_services & sec_serv_conf) {
- enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
+ enc_start = (uint8_t *)hdr + srtp_get_rtp_hdr_len(hdr);
if (hdr->x == 1) {
- xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
- enc_start += (ntohs(xtn_hdr->length) + 1);
+ xtn_hdr = srtp_get_rtp_xtn_hdr(hdr);
+ enc_start += srtp_get_rtp_xtn_hdr_len(xtn_hdr);
}
- if (!((uint8_t *)enc_start <=
+ if (!(enc_start <=
(uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size)))
return srtp_err_status_parse_err;
enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - mki_size -
- ((uint8_t *)enc_start - (uint8_t *)hdr));
+ (enc_start - (uint8_t *)hdr));
} else {
enc_start = NULL;
}
@@ -2567,7 +2684,7 @@
* to indicate that no authentication is needed
*/
if (stream->rtp_services & sec_serv_auth) {
- auth_start = (uint32_t *)hdr;
+ auth_start = (uint8_t *)hdr;
auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;
} else {
auth_start = NULL;
@@ -2602,7 +2719,7 @@
return status;
/* now compute auth function over packet */
- status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start,
+ status = srtp_auth_update(session_keys->rtp_auth, auth_start,
*pkt_octet_len - tag_len - mki_size);
if (status)
return status;
@@ -2650,8 +2767,8 @@
/* if we're decrypting, add keystream into ciphertext */
if (enc_start) {
- status = srtp_cipher_decrypt(session_keys->rtp_cipher,
- (uint8_t *)enc_start, &enc_octet_len);
+ status = srtp_cipher_decrypt(session_keys->rtp_cipher, enc_start,
+ &enc_octet_len);
if (status)
return srtp_err_status_cipher_fail;
}
@@ -2691,12 +2808,16 @@
*/
status =
srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream);
- if (status)
+ if (status) {
return status;
+ }
- /* add new stream to the head of the stream_list */
- new_stream->next = ctx->stream_list;
- ctx->stream_list = new_stream;
+ /* add new stream to the list */
+ status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
+ ctx->stream_template);
+ if (status) {
+ return status;
+ }
/* set stream (the pointer used in this function) */
stream = new_stream;
@@ -2723,7 +2844,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_init()
+srtp_err_status_t srtp_init(void)
{
srtp_err_status_t status;
@@ -2740,7 +2861,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_shutdown()
+srtp_err_status_t srtp_shutdown(void)
{
srtp_err_status_t status;
@@ -2754,51 +2875,13 @@
return srtp_err_status_ok;
}
-/*
- * The following code is under consideration for removal. See
- * SRTP_MAX_TRAILER_LEN
- */
-#if 0
-
-/*
- * srtp_get_trailer_length(&a) returns the number of octets that will
- * be added to an RTP packet by the SRTP processing. This value
- * is constant for a given srtp_stream_t (i.e. between initializations).
- */
-
-int
-srtp_get_trailer_length(const srtp_stream_t s) {
- return srtp_auth_get_tag_length(s->rtp_auth);
-}
-
-#endif
-
-/*
- * srtp_get_stream(ssrc) returns a pointer to the stream corresponding
- * to ssrc, or NULL if no stream exists for that ssrc
- *
- * this is an internal function
- */
-
srtp_stream_ctx_t *srtp_get_stream(srtp_t srtp, uint32_t ssrc)
{
- srtp_stream_ctx_t *stream;
-
- /* walk down list until ssrc is found */
- stream = srtp->stream_list;
- while (stream != NULL) {
- if (stream->ssrc == ssrc)
- return stream;
- stream = stream->next;
- }
-
- /* we haven't found our ssrc, so return a null */
- return NULL;
+ return srtp_stream_list_get(srtp->stream_list, ssrc);
}
srtp_err_status_t srtp_dealloc(srtp_t session)
{
- srtp_stream_ctx_t *stream;
srtp_err_status_t status;
/*
@@ -2807,21 +2890,25 @@
* memory and just return an error
*/
- /* walk list of streams, deallocating as we go */
- stream = session->stream_list;
- while (stream != NULL) {
- srtp_stream_t next = stream->next;
- status = srtp_stream_dealloc(stream, session->stream_template);
- if (status)
- return status;
- stream = next;
+ /* deallocate streams */
+ status = srtp_remove_and_dealloc_streams(session->stream_list,
+ session->stream_template);
+ if (status) {
+ return status;
}
/* deallocate stream template, if there is one */
if (session->stream_template != NULL) {
status = srtp_stream_dealloc(session->stream_template, NULL);
- if (status)
+ if (status) {
return status;
+ }
+ }
+
+ /* deallocate stream list */
+ status = srtp_stream_list_dealloc(session->stream_list);
+ if (status) {
+ return status;
}
/* deallocate session context */
@@ -2835,6 +2922,11 @@
srtp_err_status_t status;
srtp_stream_t tmp;
+ status = srtp_valid_policy(policy);
+ if (status != srtp_err_status_ok) {
+ return status;
+ }
+
/* sanity check arguments */
if ((session == NULL) || (policy == NULL) ||
(!srtp_validate_policy_master_keys(policy)))
@@ -2879,8 +2971,11 @@
session->stream_template->direction = dir_srtp_receiver;
break;
case (ssrc_specific):
- tmp->next = session->stream_list;
- session->stream_list = tmp;
+ status = srtp_insert_or_dealloc_stream(session->stream_list, tmp,
+ session->stream_template);
+ if (status) {
+ return status;
+ }
break;
case (ssrc_undefined):
default:
@@ -2897,6 +2992,11 @@
srtp_err_status_t stat;
srtp_ctx_t *ctx;
+ stat = srtp_valid_policy(policy);
+ if (stat != srtp_err_status_ok) {
+ return stat;
+ }
+
/* sanity check arguments */
if (session == NULL)
return srtp_err_status_bad_param;
@@ -2907,13 +3007,23 @@
return srtp_err_status_alloc_fail;
*session = ctx;
+ ctx->stream_template = NULL;
+ ctx->stream_list = NULL;
+ ctx->user_data = NULL;
+
+ /* allocate stream list */
+ stat = srtp_stream_list_alloc(&ctx->stream_list);
+ if (stat) {
+ /* clean up everything */
+ srtp_dealloc(*session);
+ *session = NULL;
+ return stat;
+ }
+
/*
* loop over elements in the policy list, allocating and
* initializing a stream for each element
*/
- ctx->stream_template = NULL;
- ctx->stream_list = NULL;
- ctx->user_data = NULL;
while (policy != NULL) {
stat = srtp_add_stream(ctx, policy);
if (stat) {
@@ -2932,28 +3042,20 @@
srtp_err_status_t srtp_remove_stream(srtp_t session, uint32_t ssrc)
{
- srtp_stream_ctx_t *stream, *last_stream;
+ srtp_stream_ctx_t *stream;
srtp_err_status_t status;
/* sanity check arguments */
if (session == NULL)
return srtp_err_status_bad_param;
- /* find stream in list; complain if not found */
- last_stream = stream = session->stream_list;
- while ((stream != NULL) && (ssrc != stream->ssrc)) {
- last_stream = stream;
- stream = stream->next;
- }
- if (stream == NULL)
+ /* find and remove stream from the list */
+ stream = srtp_stream_list_get(session->stream_list, ssrc);
+ if (stream == NULL) {
return srtp_err_status_no_ctx;
+ }
- /* remove stream from the list */
- if (last_stream == stream)
- /* stream was first in list */
- session->stream_list = stream->next;
- else
- last_stream->next = stream->next;
+ srtp_stream_list_remove(session->stream_list, stream);
/* deallocate the stream */
status = srtp_stream_dealloc(stream, session->stream_template);
@@ -2967,6 +3069,11 @@
{
srtp_err_status_t stat;
+ stat = srtp_valid_policy(policy);
+ if (stat != srtp_err_status_ok) {
+ return stat;
+ }
+
/* sanity check arguments */
if ((session == NULL) || (policy == NULL) ||
(!srtp_validate_policy_master_keys(policy))) {
@@ -2985,12 +3092,75 @@
return srtp_err_status_ok;
}
+struct update_template_stream_data {
+ srtp_err_status_t status;
+ srtp_t session;
+ srtp_stream_t new_stream_template;
+ srtp_stream_list_t new_stream_list;
+};
+
+static int update_template_stream_cb(srtp_stream_t stream, void *raw_data)
+{
+ struct update_template_stream_data *data =
+ (struct update_template_stream_data *)raw_data;
+ srtp_t session = data->session;
+ uint32_t ssrc = stream->ssrc;
+ srtp_xtd_seq_num_t old_index;
+ srtp_rdb_t old_rtcp_rdb;
+
+ /* old / non-template streams are copied unchanged */
+ if (stream->session_keys[0].rtp_auth !=
+ session->stream_template->session_keys[0].rtp_auth) {
+ srtp_stream_list_remove(session->stream_list, stream);
+ data->status = srtp_insert_or_dealloc_stream(
+ data->new_stream_list, stream, session->stream_template);
+ if (data->status) {
+ return 1;
+ }
+ return 0;
+ }
+
+ /* save old extendard seq */
+ old_index = stream->rtp_rdbx.index;
+ old_rtcp_rdb = stream->rtcp_rdb;
+
+ /* remove stream */
+ data->status = srtp_remove_stream(session, ssrc);
+ if (data->status) {
+ return 1;
+ }
+
+ /* allocate and initialize a new stream */
+ data->status = srtp_stream_clone(data->new_stream_template, ssrc, &stream);
+ if (data->status) {
+ return 1;
+ }
+
+ /* add new stream to the head of the new_stream_list */
+ data->status = srtp_insert_or_dealloc_stream(data->new_stream_list, stream,
+ data->new_stream_template);
+ if (data->status) {
+ return 1;
+ }
+
+ /* restore old extended seq */
+ stream->rtp_rdbx.index = old_index;
+ stream->rtcp_rdb = old_rtcp_rdb;
+
+ return 0;
+}
+
static srtp_err_status_t update_template_streams(srtp_t session,
const srtp_policy_t *policy)
{
srtp_err_status_t status;
srtp_stream_t new_stream_template;
- srtp_stream_t new_stream_list = NULL;
+ srtp_stream_list_t new_stream_list;
+
+ status = srtp_valid_policy(policy);
+ if (status != srtp_err_status_ok) {
+ return status;
+ }
if (session->stream_template == NULL) {
return srtp_err_status_bad_param;
@@ -3009,77 +3179,37 @@
return status;
}
- /* for all old templated streams */
- for (;;) {
- srtp_stream_t stream;
- uint32_t ssrc;
- srtp_xtd_seq_num_t old_index;
- srtp_rdb_t old_rtcp_rdb;
-
- stream = session->stream_list;
- while ((stream != NULL) &&
- (stream->session_keys[0].rtp_auth !=
- session->stream_template->session_keys[0].rtp_auth)) {
- stream = stream->next;
- }
- if (stream == NULL) {
- /* no more templated streams */
- break;
- }
-
- /* save old extendard seq */
- ssrc = stream->ssrc;
- old_index = stream->rtp_rdbx.index;
- old_rtcp_rdb = stream->rtcp_rdb;
-
- /* remove stream */
- status = srtp_remove_stream(session, ssrc);
- if (status) {
- /* free new allocations */
- while (new_stream_list != NULL) {
- srtp_stream_t next = new_stream_list->next;
- srtp_stream_dealloc(new_stream_list, new_stream_template);
- new_stream_list = next;
- }
- srtp_stream_dealloc(new_stream_template, NULL);
- return status;
- }
-
- /* allocate and initialize a new stream */
- status = srtp_stream_clone(new_stream_template, ssrc, &stream);
- if (status) {
- /* free new allocations */
- while (new_stream_list != NULL) {
- srtp_stream_t next = new_stream_list->next;
- srtp_stream_dealloc(new_stream_list, new_stream_template);
- new_stream_list = next;
- }
- srtp_stream_dealloc(new_stream_template, NULL);
- return status;
- }
-
- /* add new stream to the head of the new_stream_list */
- stream->next = new_stream_list;
- new_stream_list = stream;
-
- /* restore old extended seq */
- stream->rtp_rdbx.index = old_index;
- stream->rtcp_rdb = old_rtcp_rdb;
+ /* allocate new stream list */
+ status = srtp_stream_list_alloc(&new_stream_list);
+ if (status) {
+ srtp_crypto_free(new_stream_template);
+ return status;
}
- /* dealloc old template */
+
+ /* process streams */
+ struct update_template_stream_data data = { srtp_err_status_ok, session,
+ new_stream_template,
+ new_stream_list };
+ srtp_stream_list_for_each(session->stream_list, update_template_stream_cb,
+ &data);
+ if (data.status) {
+ /* free new allocations */
+ srtp_remove_and_dealloc_streams(new_stream_list, new_stream_template);
+ srtp_stream_list_dealloc(new_stream_list);
+ srtp_stream_dealloc(new_stream_template, NULL);
+ return data.status;
+ }
+
+ /* dealloc old list / template */
+ srtp_remove_and_dealloc_streams(session->stream_list,
+ session->stream_template);
+ srtp_stream_list_dealloc(session->stream_list);
srtp_stream_dealloc(session->stream_template, NULL);
- /* set new template */
+
+ /* set new list / template */
session->stream_template = new_stream_template;
- /* add new list */
- if (new_stream_list) {
- srtp_stream_t tail = new_stream_list;
- while (tail->next) {
- tail = tail->next;
- }
- tail->next = session->stream_list;
- session->stream_list = new_stream_list;
- }
- return status;
+ session->stream_list = new_stream_list;
+ return srtp_err_status_ok;
}
static srtp_err_status_t update_stream(srtp_t session,
@@ -3090,6 +3220,11 @@
srtp_rdb_t old_rtcp_rdb;
srtp_stream_t stream;
+ status = srtp_valid_policy(policy);
+ if (status != srtp_err_status_ok) {
+ return status;
+ }
+
stream = srtp_get_stream(session, htonl(policy->ssrc.value));
if (stream == NULL) {
return srtp_err_status_bad_param;
@@ -3126,6 +3261,11 @@
{
srtp_err_status_t status;
+ status = srtp_valid_policy(policy);
+ if (status != srtp_err_status_ok) {
+ return status;
+ }
+
/* sanity check arguments */
if ((session == NULL) || (policy == NULL) ||
(!srtp_validate_policy_master_keys(policy)))
@@ -3225,7 +3365,8 @@
*/
p->cipher_type = SRTP_NULL_CIPHER;
- p->cipher_key_len = 0;
+ p->cipher_key_len =
+ SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */
p->auth_type = SRTP_HMAC_SHA1;
p->auth_key_len = 20;
p->auth_tag_len = 10;
@@ -3239,7 +3380,8 @@
*/
p->cipher_type = SRTP_NULL_CIPHER;
- p->cipher_key_len = 0;
+ p->cipher_key_len =
+ SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */
p->auth_type = SRTP_NULL_AUTH;
p->auth_key_len = 0;
p->auth_tag_len = 0;
@@ -3446,7 +3588,7 @@
srtp_session_keys_t *session_keys,
v128_t *iv,
uint32_t seq_num,
- srtcp_hdr_t *hdr)
+ const srtcp_hdr_t *hdr)
{
v128_t in;
v128_t salt;
@@ -3488,7 +3630,6 @@
* AES-GCM mode with 128 or 256 bit keys.
*/
static srtp_err_status_t srtp_protect_rtcp_aead(
- srtp_t ctx,
srtp_stream_ctx_t *stream,
void *rtcp_hdr,
unsigned int *pkt_octet_len,
@@ -3496,8 +3637,8 @@
unsigned int use_mki)
{
srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
- uint32_t *enc_start; /* pointer to start of encrypted portion */
- uint32_t *trailer_p; /* pointer to start of trailer */
+ uint8_t *enc_start; /* pointer to start of encrypted portion */
+ uint8_t *trailer_p; /* pointer to start of trailer */
uint32_t trailer; /* trailer value */
unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
@@ -3515,13 +3656,13 @@
* set encryption start and encryption length - if we're not
* providing confidentiality, set enc_start to NULL
*/
- enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
+ enc_start = (uint8_t *)hdr + octets_in_rtcp_header;
enc_octet_len = *pkt_octet_len - octets_in_rtcp_header;
/* NOTE: hdr->length is not usable - it refers to only the first
* RTCP report in the compound packet!
*/
- trailer_p = (uint32_t *)((char *)enc_start + enc_octet_len + tag_len);
+ trailer_p = enc_start + enc_octet_len + tag_len;
if (stream->rtcp_services & sec_serv_conf) {
trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
@@ -3608,16 +3749,16 @@
/* if we're encrypting, exor keystream into the message */
if (enc_start) {
- status = srtp_cipher_encrypt(session_keys->rtcp_cipher,
- (uint8_t *)enc_start, &enc_octet_len);
+ status = srtp_cipher_encrypt(session_keys->rtcp_cipher, enc_start,
+ &enc_octet_len);
if (status) {
return srtp_err_status_cipher_fail;
}
/*
* Get the tag and append that to the output
*/
- status = srtp_cipher_get_tag(session_keys->rtcp_cipher,
- (uint8_t *)auth_tag, &tag_len);
+ status =
+ srtp_cipher_get_tag(session_keys->rtcp_cipher, auth_tag, &tag_len);
if (status) {
return (srtp_err_status_cipher_fail);
}
@@ -3635,8 +3776,8 @@
/*
* Get the tag and append that to the output
*/
- status = srtp_cipher_get_tag(session_keys->rtcp_cipher,
- (uint8_t *)auth_tag, &tag_len);
+ status =
+ srtp_cipher_get_tag(session_keys->rtcp_cipher, auth_tag, &tag_len);
if (status) {
return (srtp_err_status_cipher_fail);
}
@@ -3667,8 +3808,8 @@
unsigned int use_mki)
{
srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
- uint32_t *enc_start; /* pointer to start of encrypted portion */
- uint32_t *trailer_p; /* pointer to start of trailer */
+ uint8_t *enc_start; /* pointer to start of encrypted portion */
+ uint8_t *trailer_p; /* pointer to start of trailer */
uint32_t trailer; /* trailer value */
unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
@@ -3695,8 +3836,8 @@
*/
/* This should point trailer to the word past the end of the normal data. */
/* This would need to be modified for optional mikey data */
- trailer_p = (uint32_t *)((char *)hdr + *pkt_octet_len -
- sizeof(srtcp_trailer_t) - mki_size);
+ trailer_p =
+ (uint8_t *)hdr + *pkt_octet_len - sizeof(srtcp_trailer_t) - mki_size;
memcpy(&trailer, trailer_p, sizeof(trailer));
/*
@@ -3708,7 +3849,7 @@
sizeof(srtcp_trailer_t);
if (*((unsigned char *)trailer_p) & SRTCP_E_BYTE_BIT) {
- enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
+ enc_start = (uint8_t *)hdr + octets_in_rtcp_header;
} else {
enc_octet_len = 0;
enc_start = NULL; /* this indicates that there's no encryption */
@@ -3746,8 +3887,9 @@
* If payload encryption is enabled, then the AAD consist of
* the RTCP header and the seq# at the end of the packet
*/
- status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)hdr,
- octets_in_rtcp_header);
+ status =
+ srtp_cipher_set_aad(session_keys->rtcp_cipher, (const uint8_t *)hdr,
+ octets_in_rtcp_header);
if (status) {
return (srtp_err_status_cipher_fail);
}
@@ -3777,8 +3919,8 @@
/* if we're decrypting, exor keystream into the message */
if (enc_start) {
- status = srtp_cipher_decrypt(session_keys->rtcp_cipher,
- (uint8_t *)enc_start, &enc_octet_len);
+ status = srtp_cipher_decrypt(session_keys->rtcp_cipher, enc_start,
+ &enc_octet_len);
if (status) {
return status;
}
@@ -3787,8 +3929,8 @@
* Still need to run the cipher to check the tag
*/
tmp_len = tag_len;
- status = srtp_cipher_decrypt(session_keys->rtcp_cipher,
- (uint8_t *)auth_tag, &tmp_len);
+ status =
+ srtp_cipher_decrypt(session_keys->rtcp_cipher, auth_tag, &tmp_len);
if (status) {
return status;
}
@@ -3836,9 +3978,12 @@
return status;
}
- /* add new stream to the head of the stream_list */
- new_stream->next = ctx->stream_list;
- ctx->stream_list = new_stream;
+ /* add new stream to the list */
+ status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
+ ctx->stream_template);
+ if (status) {
+ return status;
+ }
/* set stream (the pointer used in this function) */
stream = new_stream;
@@ -3864,9 +4009,9 @@
unsigned int mki_index)
{
srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
- uint32_t *enc_start; /* pointer to start of encrypted portion */
- uint32_t *auth_start; /* pointer to start of auth. portion */
- uint32_t *trailer_p; /* pointer to start of trailer */
+ uint8_t *enc_start; /* pointer to start of encrypted portion */
+ uint8_t *auth_start; /* pointer to start of auth. portion */
+ uint8_t *trailer_p; /* pointer to start of trailer */
uint32_t trailer; /* trailer value */
unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
@@ -3878,8 +4023,6 @@
unsigned int mki_size = 0;
srtp_session_keys_t *session_keys = NULL;
- /* we assume the hdr is 32-bit aligned to start */
-
/* check the packet length - it must at least contain a full header */
if (*pkt_octet_len < octets_in_rtcp_header)
return srtp_err_status_bad_param;
@@ -3902,9 +4045,12 @@
if (status)
return status;
- /* add new stream to the head of the stream_list */
- new_stream->next = ctx->stream_list;
- ctx->stream_list = new_stream;
+ /* add new stream to the list */
+ status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
+ ctx->stream_template);
+ if (status) {
+ return status;
+ }
/* set stream (the pointer used in this function) */
stream = new_stream;
@@ -3940,7 +4086,7 @@
*/
if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 ||
session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) {
- return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr,
+ return srtp_protect_rtcp_aead(stream, rtcp_hdr,
(unsigned int *)pkt_octet_len,
session_keys, use_mki);
}
@@ -3952,7 +4098,7 @@
* set encryption start and encryption length - if we're not
* providing confidentiality, set enc_start to NULL
*/
- enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
+ enc_start = (uint8_t *)hdr + octets_in_rtcp_header;
enc_octet_len = *pkt_octet_len - octets_in_rtcp_header;
/* all of the packet, except the header, gets encrypted */
@@ -3960,7 +4106,7 @@
* NOTE: hdr->length is not usable - it refers to only the first RTCP report
* in the compound packet!
*/
- trailer_p = (uint32_t *)((char *)enc_start + enc_octet_len);
+ trailer_p = enc_start + enc_octet_len;
if (stream->rtcp_services & sec_serv_conf) {
trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
@@ -3980,14 +4126,10 @@
* (note that srtpc *always* provides authentication, unlike srtp)
*/
/* Note: This would need to change for optional mikey data */
- auth_start = (uint32_t *)hdr;
+ auth_start = (uint8_t *)hdr;
auth_tag =
(uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t) + mki_size;
- /* perform EKT processing if needed */
- srtp_ekt_write_data(stream->ekt, auth_tag, tag_len, pkt_octet_len,
- srtp_rdbx_get_packet_index(&stream->rtp_rdbx));
-
/*
* check sequence number for overruns, and copy it into the packet
* if its value isn't too big
@@ -4051,8 +4193,8 @@
/* if we're encrypting, exor keystream into the message */
if (enc_start) {
- status = srtp_cipher_encrypt(session_keys->rtcp_cipher,
- (uint8_t *)enc_start, &enc_octet_len);
+ status = srtp_cipher_encrypt(session_keys->rtcp_cipher, enc_start,
+ &enc_octet_len);
if (status)
return srtp_err_status_cipher_fail;
}
@@ -4067,7 +4209,7 @@
* result at auth_tag
*/
status =
- srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start,
+ srtp_auth_compute(session_keys->rtcp_auth, auth_start,
(*pkt_octet_len) + sizeof(srtcp_trailer_t), auth_tag);
debug_print(mod_srtp, "srtcp auth tag: %s",
srtp_octet_string_hex_string(auth_tag, tag_len));
@@ -4096,14 +4238,13 @@
unsigned int use_mki)
{
srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
- uint32_t *enc_start; /* pointer to start of encrypted portion */
- uint32_t *auth_start; /* pointer to start of auth. portion */
- uint32_t *trailer_p; /* pointer to start of trailer */
+ uint8_t *enc_start; /* pointer to start of encrypted portion */
+ uint8_t *auth_start; /* pointer to start of auth. portion */
+ uint8_t *trailer_p; /* pointer to start of trailer */
uint32_t trailer; /* trailer value */
unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */
uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
- uint8_t tag_copy[SRTP_MAX_TAG_LEN];
srtp_err_status_t status;
unsigned int auth_len;
int tag_len;
@@ -4115,8 +4256,6 @@
unsigned int mki_size = 0;
srtp_session_keys_t *session_keys = NULL;
- /* we assume the hdr is 32-bit aligned to start */
-
if (*pkt_octet_len < 0)
return srtp_err_status_bad_param;
@@ -4141,23 +4280,6 @@
if (ctx->stream_template != NULL) {
stream = ctx->stream_template;
- /*
- * check to see if stream_template has an EKT data structure, in
- * which case we initialize the template using the EKT policy
- * referenced by that data (which consists of decrypting the
- * master key from the EKT field)
- *
- * this function initializes a *provisional* stream, and this
- * stream should not be accepted until and unless the packet
- * passes its authentication check
- */
- if (stream->ekt != NULL) {
- status = srtp_stream_init_from_ekt(stream, srtcp_hdr,
- *pkt_octet_len);
- if (status)
- return status;
- }
-
debug_print(mod_srtp,
"srtcp using provisional stream (SSRC: 0x%08x)",
ntohl(hdr->ssrc));
@@ -4172,8 +4294,7 @@
*/
if (use_mki) {
session_keys = srtp_get_session_keys(
- stream, (uint8_t *)hdr, (const unsigned int *)pkt_octet_len,
- &mki_size);
+ stream, (uint8_t *)hdr, (unsigned int)*pkt_octet_len, &mki_size);
if (session_keys == NULL)
return srtp_err_status_bad_mki;
@@ -4217,17 +4338,16 @@
*/
/* This should point trailer to the word past the end of the normal data. */
/* This would need to be modified for optional mikey data */
- trailer_p = (uint32_t *)((char *)hdr + *pkt_octet_len -
- (tag_len + mki_size + sizeof(srtcp_trailer_t)));
+ trailer_p = (uint8_t *)hdr + *pkt_octet_len -
+ (tag_len + mki_size + sizeof(srtcp_trailer_t));
memcpy(&trailer, trailer_p, sizeof(trailer));
- e_bit_in_packet =
- (*((unsigned char *)trailer_p) & SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT;
+ e_bit_in_packet = (*(trailer_p)&SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT;
if (e_bit_in_packet != sec_serv_confidentiality) {
return srtp_err_status_cant_check;
}
if (sec_serv_confidentiality) {
- enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
+ enc_start = (uint8_t *)hdr + octets_in_rtcp_header;
} else {
enc_octet_len = 0;
enc_start = NULL; /* this indicates that there's no encryption */
@@ -4237,7 +4357,7 @@
* set the auth_start and auth_tag pointers to the proper locations
* (note that srtcp *always* uses authentication, unlike srtp)
*/
- auth_start = (uint32_t *)hdr;
+ auth_start = (uint8_t *)hdr;
/*
* The location of the auth tag in the packet needs to know MKI
@@ -4248,21 +4368,6 @@
auth_tag = (uint8_t *)hdr + auth_len + mki_size;
/*
- * if EKT is in use, then we make a copy of the tag from the packet,
- * and then zeroize the location of the base tag
- *
- * we first re-position the auth_tag pointer so that it points to
- * the base tag
- */
- if (stream->ekt) {
- auth_tag -= srtp_ekt_octets_after_base_tag(stream->ekt);
- memcpy(tag_copy, auth_tag, tag_len);
- octet_string_set_to_zero(auth_tag, tag_len);
- auth_tag = tag_copy;
- auth_len += tag_len;
- }
-
- /*
* check the sequence number for replays
*/
/* this is easier than dealing with bitfield access */
@@ -4307,8 +4412,8 @@
return status;
/* run auth func over packet, put result into tmp_tag */
- status = srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start,
- auth_len, tmp_tag);
+ status = srtp_auth_compute(session_keys->rtcp_auth, auth_start, auth_len,
+ tmp_tag);
debug_print(mod_srtp, "srtcp computed tag: %s",
srtp_octet_string_hex_string(tmp_tag, tag_len));
if (status)
@@ -4336,8 +4441,8 @@
/* if we're decrypting, exor keystream into the message */
if (enc_start) {
- status = srtp_cipher_decrypt(session_keys->rtcp_cipher,
- (uint8_t *)enc_start, &enc_octet_len);
+ status = srtp_cipher_decrypt(session_keys->rtcp_cipher, enc_start,
+ &enc_octet_len);
if (status)
return srtp_err_status_cipher_fail;
}
@@ -4349,12 +4454,6 @@
*pkt_octet_len -= mki_size;
/*
- * if EKT is in effect, subtract the EKT data out of the packet
- * length
- */
- *pkt_octet_len -= srtp_ekt_octets_after_base_tag(stream->ekt);
-
- /*
* verify that stream is for received traffic - this check will
* detect SSRC collisions, since a stream that appears in both
* srtp_protect() and srtp_unprotect() will fail this test in one of
@@ -4392,9 +4491,12 @@
if (status)
return status;
- /* add new stream to the head of the stream_list */
- new_stream->next = ctx->stream_list;
- ctx->stream_list = new_stream;
+ /* add new stream to the list */
+ status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
+ ctx->stream_template);
+ if (status) {
+ return status;
+ }
/* set stream (the pointer used in this function) */
stream = new_stream;
@@ -4420,10 +4522,6 @@
return ctx->user_data;
}
-/*
- * dtls keying for srtp
- */
-
srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp(
srtp_crypto_policy_t *policy,
srtp_profile_t profile)
@@ -4579,6 +4677,32 @@
return srtp_err_status_ok;
}
+struct get_protect_trailer_length_data {
+ uint32_t found_stream; /* whether at least one matching stream was found */
+ uint32_t length; /* maximum trailer length found so far */
+ uint32_t is_rtp;
+ uint32_t use_mki;
+ uint32_t mki_index;
+};
+
+static int get_protect_trailer_length_cb(srtp_stream_t stream, void *raw_data)
+{
+ struct get_protect_trailer_length_data *data =
+ (struct get_protect_trailer_length_data *)raw_data;
+ uint32_t temp_length;
+
+ if (stream_get_protect_trailer_length(stream, data->is_rtp, data->use_mki,
+ data->mki_index,
+ &temp_length) == srtp_err_status_ok) {
+ data->found_stream = 1;
+ if (temp_length > data->length) {
+ data->length = temp_length;
+ }
+ }
+
+ return 0;
+}
+
srtp_err_status_t get_protect_trailer_length(srtp_t session,
uint32_t is_rtp,
uint32_t use_mki,
@@ -4586,38 +4710,29 @@
uint32_t *length)
{
srtp_stream_ctx_t *stream;
+ struct get_protect_trailer_length_data data = { 0, 0, is_rtp, use_mki,
+ mki_index };
if (session == NULL) {
return srtp_err_status_bad_param;
}
- if (session->stream_template == NULL && session->stream_list == NULL) {
- return srtp_err_status_bad_param;
- }
-
- *length = 0;
-
stream = session->stream_template;
if (stream != NULL) {
+ data.found_stream = 1;
stream_get_protect_trailer_length(stream, is_rtp, use_mki, mki_index,
- length);
+ &data.length);
}
- stream = session->stream_list;
+ srtp_stream_list_for_each(session->stream_list,
+ get_protect_trailer_length_cb, &data);
- while (stream != NULL) {
- uint32_t temp_length;
- if (stream_get_protect_trailer_length(stream, is_rtp, use_mki,
- mki_index, &temp_length) ==
- srtp_err_status_ok) {
- if (temp_length > *length) {
- *length = temp_length;
- }
- }
- stream = stream->next;
+ if (!data.found_stream) {
+ return srtp_err_status_bad_param;
}
+ *length = data.length;
return srtp_err_status_ok;
}
@@ -4659,7 +4774,7 @@
static srtp_log_handler_func_t *srtp_log_handler = NULL;
static void *srtp_log_handler_data = NULL;
-void srtp_err_handler(srtp_err_reporting_level_t level, const char *msg)
+static void srtp_err_handler(srtp_err_reporting_level_t level, const char *msg)
{
if (srtp_log_handler) {
srtp_log_level_t log_level = srtp_log_level_error;
@@ -4731,3 +4846,92 @@
return srtp_err_status_ok;
}
+
+#ifndef SRTP_NO_STREAM_LIST
+
+/* in the default implementation, we have an intrusive doubly-linked list */
+typedef struct srtp_stream_list_ctx_t_ {
+ /* a stub stream that just holds pointers to the beginning and end of the
+ * list */
+ srtp_stream_ctx_t data;
+} srtp_stream_list_ctx_t_;
+
+srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr)
+{
+ srtp_stream_list_t list =
+ srtp_crypto_alloc(sizeof(srtp_stream_list_ctx_t_));
+ if (list == NULL) {
+ return srtp_err_status_alloc_fail;
+ }
+
+ list->data.next = NULL;
+ list->data.prev = NULL;
+
+ *list_ptr = list;
+ return srtp_err_status_ok;
+}
+
+srtp_err_status_t srtp_stream_list_dealloc(srtp_stream_list_t list)
+{
+ /* list must be empty */
+ if (list->data.next) {
+ return srtp_err_status_fail;
+ }
+ srtp_crypto_free(list);
+ return srtp_err_status_ok;
+}
+
+srtp_err_status_t srtp_stream_list_insert(srtp_stream_list_t list,
+ srtp_stream_t stream)
+{
+ /* insert at the head of the list */
+ stream->next = list->data.next;
+ if (stream->next != NULL) {
+ stream->next->prev = stream;
+ }
+ list->data.next = stream;
+ stream->prev = &(list->data);
+
+ return srtp_err_status_ok;
+}
+
+srtp_stream_t srtp_stream_list_get(srtp_stream_list_t list, uint32_t ssrc)
+{
+ /* walk down list until ssrc is found */
+ srtp_stream_t stream = list->data.next;
+ while (stream != NULL) {
+ if (stream->ssrc == ssrc) {
+ return stream;
+ }
+ stream = stream->next;
+ }
+
+ /* we haven't found our ssrc, so return a null */
+ return NULL;
+}
+
+void srtp_stream_list_remove(srtp_stream_list_t list,
+ srtp_stream_t stream_to_remove)
+{
+ (void)list;
+
+ stream_to_remove->prev->next = stream_to_remove->next;
+ if (stream_to_remove->next != NULL) {
+ stream_to_remove->next->prev = stream_to_remove->prev;
+ }
+}
+
+void srtp_stream_list_for_each(srtp_stream_list_t list,
+ int (*callback)(srtp_stream_t, void *),
+ void *data)
+{
+ srtp_stream_t stream = list->data.next;
+ while (stream != NULL) {
+ srtp_stream_t tmp = stream;
+ stream = stream->next;
+ if (callback(tmp, data))
+ break;
+ }
+}
+
+#endif
diff --git a/test/cutest.h b/test/cutest.h
index f46626d..94e1087 100644
--- a/test/cutest.h
+++ b/test/cutest.h
@@ -259,16 +259,15 @@
}
if (test_verbose_level__ >= verbose_level) {
- size_t n = 0;
va_list args;
printf(" ");
if (file != NULL)
- n += printf("%s:%d: Check ", file, line);
+ printf("%s:%d: Check ", file, line);
va_start(args, fmt);
- n += vprintf(fmt, args);
+ vprintf(fmt, args);
va_end(args);
printf("... ");
@@ -468,7 +467,8 @@
signame = "SIGTERM";
break;
default:
- sprintf(tmp, "signal %d", WTERMSIG(exit_code));
+ snprintf(tmp, sizeof(tmp), "signal %d",
+ WTERMSIG(exit_code));
signame = tmp;
break;
}
diff --git a/test/dtls_srtp_driver.c b/test/dtls_srtp_driver.c
deleted file mode 100644
index 4f4d0a3..0000000
--- a/test/dtls_srtp_driver.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * dtls_srtp_driver.c
- *
- * test driver for DTLS-SRTP functions
- *
- * David McGrew
- * Cisco Systems, Inc.
- */
-/*
- *
- * Copyright (c) 2001-2017 Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the Cisco Systems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <stdio.h> /* for printf() */
-#include "getopt_s.h" /* for local getopt() */
-#include "srtp_priv.h"
-
-srtp_err_status_t test_dtls_srtp(void);
-
-srtp_hdr_t *srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc);
-
-void usage(char *prog_name)
-{
- printf("usage: %s [ -t ][ -c ][ -v ][-d <debug_module> ]* [ -l ]\n"
- " -d <mod> turn on debugging module <mod>\n"
- " -l list debugging modules\n",
- prog_name);
- exit(1);
-}
-
-int main(int argc, char *argv[])
-{
- unsigned do_list_mods = 0;
- int q;
- srtp_err_status_t err;
-
- printf("dtls_srtp_driver\n");
-
- /* initialize srtp library */
- err = srtp_init();
- if (err) {
- printf("error: srtp init failed with error code %d\n", err);
- exit(1);
- }
-
- /* process input arguments */
- while (1) {
- q = getopt_s(argc, argv, "ld:");
- if (q == -1)
- break;
- switch (q) {
- case 'l':
- do_list_mods = 1;
- break;
- case 'd':
- err = srtp_crypto_kernel_set_debug_module(optarg_s, 1);
- if (err) {
- printf("error: set debug module (%s) failed\n", optarg_s);
- exit(1);
- }
- break;
- default:
- usage(argv[0]);
- }
- }
-
- if (do_list_mods) {
- err = srtp_crypto_kernel_list_debug_modules();
- if (err) {
- printf("error: list of debug modules failed\n");
- exit(1);
- }
- }
-
- printf("testing dtls_srtp...");
- err = test_dtls_srtp();
- if (err) {
- printf("\nerror (code %d)\n", err);
- exit(1);
- }
- printf("passed\n");
-
- /* shut down srtp library */
- err = srtp_shutdown();
- if (err) {
- printf("error: srtp shutdown failed with error code %d\n", err);
- exit(1);
- }
-
- return 0;
-}
-
-srtp_err_status_t test_dtls_srtp(void)
-{
- srtp_hdr_t *test_packet;
- int test_packet_len = 80;
- srtp_t s;
- srtp_policy_t policy;
- uint8_t key[SRTP_MAX_KEY_LEN];
- uint8_t salt[SRTP_MAX_KEY_LEN];
- unsigned int key_len, salt_len;
- srtp_profile_t profile;
- srtp_err_status_t err;
-
- memset(&policy, 0x0, sizeof(srtp_policy_t));
-
- /* create a 'null' SRTP session */
- err = srtp_create(&s, NULL);
- if (err)
- return err;
-
- /*
- * verify that packet-processing functions behave properly - we
- * expect that these functions will return srtp_err_status_no_ctx
- */
- test_packet = srtp_create_test_packet(80, 0xa5a5a5a5);
- if (test_packet == NULL)
- return srtp_err_status_alloc_fail;
-
- err = srtp_protect(s, test_packet, &test_packet_len);
- if (err != srtp_err_status_no_ctx) {
- printf("wrong return value from srtp_protect() (got code %d)\n", err);
- return srtp_err_status_fail;
- }
-
- err = srtp_unprotect(s, test_packet, &test_packet_len);
- if (err != srtp_err_status_no_ctx) {
- printf("wrong return value from srtp_unprotect() (got code %d)\n", err);
- return srtp_err_status_fail;
- }
-
- err = srtp_protect_rtcp(s, test_packet, &test_packet_len);
- if (err != srtp_err_status_no_ctx) {
- printf("wrong return value from srtp_protect_rtcp() (got code %d)\n",
- err);
- return srtp_err_status_fail;
- }
-
- err = srtp_unprotect_rtcp(s, test_packet, &test_packet_len);
- if (err != srtp_err_status_no_ctx) {
- printf("wrong return value from srtp_unprotect_rtcp() (got code %d)\n",
- err);
- return srtp_err_status_fail;
- }
-
- /*
- * set keys to known values for testing
- */
- profile = srtp_profile_aes128_cm_sha1_80;
- key_len = srtp_profile_get_master_key_length(profile);
- salt_len = srtp_profile_get_master_salt_length(profile);
- memset(key, 0xff, key_len);
- memset(salt, 0xee, salt_len);
- srtp_append_salt_to_key(key, key_len, salt, salt_len);
- policy.key = key;
-
- /* initialize SRTP policy from profile */
- err = srtp_crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile);
- if (err)
- return err;
- err = srtp_crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile);
- if (err)
- return err;
- policy.ssrc.type = ssrc_any_inbound;
- policy.ekt = NULL;
- policy.window_size = 128;
- policy.allow_repeat_tx = 0;
- policy.next = NULL;
-
- err = srtp_add_stream(s, &policy);
- if (err)
- return err;
-
- err = srtp_dealloc(s);
- if (err)
- return err;
-
- free(test_packet);
-
- return srtp_err_status_ok;
-}
-
-/*
- * srtp_create_test_packet(len, ssrc) returns a pointer to a
- * (malloced) example RTP packet whose data field has the length given
- * by pkt_octet_len and the SSRC value ssrc. The total length of the
- * packet is twelve octets longer, since the header is at the
- * beginning. There is room at the end of the packet for a trailer,
- * and the four octets following the packet are filled with 0xff
- * values to enable testing for overwrites.
- *
- * note that the location of the test packet can (and should) be
- * deallocated with the free() call once it is no longer needed.
- */
-
-srtp_hdr_t *srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc)
-{
- int i;
- uint8_t *buffer;
- srtp_hdr_t *hdr;
- int bytes_in_hdr = 12;
-
- /* allocate memory for test packet */
- hdr = malloc(pkt_octet_len + bytes_in_hdr + SRTP_MAX_TRAILER_LEN + 4);
- if (!hdr)
- return NULL;
-
- hdr->version = 2; /* RTP version two */
- hdr->p = 0; /* no padding needed */
- hdr->x = 0; /* no header extension */
- hdr->cc = 0; /* no CSRCs */
- hdr->m = 0; /* marker bit */
- hdr->pt = 0xf; /* payload type */
- hdr->seq = htons(0x1234); /* sequence number */
- hdr->ts = htonl(0xdecafbad); /* timestamp */
- hdr->ssrc = htonl(ssrc); /* synch. source */
-
- buffer = (uint8_t *)hdr;
- buffer += bytes_in_hdr;
-
- /* set RTP data to 0xab */
- for (i = 0; i < pkt_octet_len; i++)
- *buffer++ = 0xab;
-
- /* set post-data value to 0xffff to enable overrun checking */
- for (i = 0; i < SRTP_MAX_TRAILER_LEN + 4; i++)
- *buffer++ = 0xff;
-
- return hdr;
-}
diff --git a/test/rdbx_driver.c b/test/rdbx_driver.c
index df434a0..2cb676f 100644
--- a/test/rdbx_driver.c
+++ b/test/rdbx_driver.c
@@ -130,13 +130,6 @@
return 0;
}
-void print_rdbx(srtp_rdbx_t *rdbx)
-{
- char buf[2048];
- printf("rdbx: {%llu, %s}\n", (unsigned long long)(rdbx->index),
- bitvector_bit_string(&rdbx->bitmask, buf, sizeof(buf)));
-}
-
/*
* rdbx_check_add(rdbx, idx) checks a known-to-be-good idx against
* rdbx, then adds it. if a failure is detected (i.e., the check
@@ -150,7 +143,7 @@
int delta;
srtp_xtd_seq_num_t est;
- delta = srtp_index_guess(&rdbx->index, &est, idx);
+ delta = srtp_index_guess(&rdbx->index, &est, (srtp_sequence_number_t)idx);
if (srtp_rdbx_check(rdbx, delta) != srtp_err_status_ok) {
printf("replay_check failed at index %u\n", idx);
@@ -183,7 +176,7 @@
srtp_xtd_seq_num_t est;
srtp_err_status_t status;
- delta = srtp_index_guess(&rdbx->index, &est, idx);
+ delta = srtp_index_guess(&rdbx->index, &est, (srtp_sequence_number_t)idx);
status = srtp_rdbx_check(rdbx, delta);
if (status == srtp_err_status_ok) {
@@ -201,7 +194,7 @@
srtp_xtd_seq_num_t est;
srtp_err_status_t rstat;
- delta = srtp_index_guess(&rdbx->index, &est, idx);
+ delta = srtp_index_guess(&rdbx->index, &est, (srtp_sequence_number_t)idx);
rstat = srtp_rdbx_check(rdbx, delta);
if ((rstat != srtp_err_status_ok) &&
@@ -340,7 +333,7 @@
failures = 0;
timer = clock();
for (i = 0; (int)i < num_trials; i++) {
- delta = srtp_index_guess(&rdbx.index, &est, i);
+ delta = srtp_index_guess(&rdbx.index, &est, (srtp_sequence_number_t)i);
if (srtp_rdbx_check(&rdbx, delta) != srtp_err_status_ok)
++failures;
diff --git a/test/replay_driver.c b/test/replay_driver.c
index e0808b6..45aec02 100644
--- a/test/replay_driver.c
+++ b/test/replay_driver.c
@@ -82,12 +82,6 @@
return 0;
}
-void print_rdb(srtp_rdb_t *rdb)
-{
- printf("rdb: {%u, %s}\n", rdb->window_start,
- v128_bit_string(&rdb->bitmask));
-}
-
srtp_err_status_t rdb_check_add(srtp_rdb_t *rdb, uint32_t idx)
{
if (srtp_rdb_check(rdb, idx) != srtp_err_status_ok) {
@@ -138,7 +132,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t test_rdb_db()
+srtp_err_status_t test_rdb_db(void)
{
srtp_rdb_t rdb;
uint32_t idx, ircvd;
@@ -257,7 +251,6 @@
uint32_t i;
srtp_rdb_t rdb;
clock_t timer;
- int failures = 0; /* count number of failures */
if (srtp_rdb_init(&rdb) != srtp_err_status_ok) {
printf("rdb_init failed\n");
@@ -266,18 +259,12 @@
timer = clock();
for (i = 0; i < REPLAY_NUM_TRIALS; i += 3) {
- if (srtp_rdb_check(&rdb, i + 2) != srtp_err_status_ok)
- ++failures;
- if (srtp_rdb_add_index(&rdb, i + 2) != srtp_err_status_ok)
- ++failures;
- if (srtp_rdb_check(&rdb, i + 1) != srtp_err_status_ok)
- ++failures;
- if (srtp_rdb_add_index(&rdb, i + 1) != srtp_err_status_ok)
- ++failures;
- if (srtp_rdb_check(&rdb, i) != srtp_err_status_ok)
- ++failures;
- if (srtp_rdb_add_index(&rdb, i) != srtp_err_status_ok)
- ++failures;
+ srtp_rdb_check(&rdb, i + 2);
+ srtp_rdb_add_index(&rdb, i + 2);
+ srtp_rdb_check(&rdb, i + 1);
+ srtp_rdb_add_index(&rdb, i + 1);
+ srtp_rdb_check(&rdb, i);
+ srtp_rdb_add_index(&rdb, i);
}
timer = clock() - timer;
diff --git a/test/roc_driver.c b/test/roc_driver.c
index 4398620..11d1bbb 100644
--- a/test/roc_driver.c
+++ b/test/roc_driver.c
@@ -145,7 +145,7 @@
/* now update local srtp_xtd_seq_num_t as necessary */
if (delta > 0)
- srtp_index_advance(&local, delta);
+ srtp_index_advance(&local, (srtp_sequence_number_t)delta);
if (ref != est) {
#if ROC_VERBOSE
diff --git a/test/rtp.c b/test/rtp.c
index 70248ee..fac0311 100644
--- a/test/rtp.c
+++ b/test/rtp.c
@@ -131,10 +131,9 @@
if (stat) {
fprintf(stderr, "error: srtp unprotection failed with code %d%s\n",
stat,
- stat == srtp_err_status_replay_fail
- ? " (replay check failed)"
- : stat == srtp_err_status_auth_fail ? " (auth check failed)"
- : "");
+ stat == srtp_err_status_replay_fail ? " (replay check failed)"
+ : stat == srtp_err_status_auth_fail ? " (auth check failed)"
+ : "");
return -1;
}
strncpy(msg, receiver->message.body, octets_recvd);
diff --git a/test/rtp.h b/test/rtp.h
index 37921a6..50df88b 100644
--- a/test/rtp.h
+++ b/test/rtp.h
@@ -123,14 +123,14 @@
struct sockaddr_in name, /* socket name */
srtp_sec_serv_t security_services, /* sec. servs. to be used */
unsigned char *input_key /* master key/salt in hex */
- );
+);
int srtp_receiver_init(
rtp_receiver_t rtp_ctx, /* structure to be init'ed */
struct sockaddr_in name, /* socket name */
srtp_sec_serv_t security_services, /* sec. servs. to be used */
unsigned char *input_key /* master key/salt in hex */
- );
+);
int rtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy);
diff --git a/test/rtpw.c b/test/rtpw.c
index 0d37e7b..906f126 100644
--- a/test/rtpw.c
+++ b/test/rtpw.c
@@ -285,7 +285,17 @@
port = atoi(argv[optind_s++]);
/* set address */
-#ifdef HAVE_INET_ATON
+#ifdef HAVE_INET_PTON
+ if (0 == inet_pton(AF_INET, address, &rcvr_addr)) {
+ fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0],
+ address);
+ exit(1);
+ }
+ if (rcvr_addr.s_addr == INADDR_NONE) {
+ fprintf(stderr, "%s: address error", argv[0]);
+ exit(1);
+ }
+#elif HAVE_INET_ATON
if (0 == inet_aton(address, &rcvr_addr)) {
fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0],
address);
@@ -444,7 +454,6 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = ssrc;
policy.key = (uint8_t *)key;
- policy.ekt = NULL;
policy.next = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
@@ -474,14 +483,16 @@
}
/* check that hex string is the right length */
if (len < expected_len) {
- fprintf(stderr, "error: too few digits in key/salt "
- "(should be %d digits, found %d)\n",
+ fprintf(stderr,
+ "error: too few digits in key/salt "
+ "(should be %d digits, found %d)\n",
expected_len, len);
exit(1);
}
if ((int)strlen(input_key) > policy.rtp.cipher_key_len * 2) {
- fprintf(stderr, "error: too many digits in key/salt "
- "(should be %d hexadecimal digits, found %u)\n",
+ fprintf(stderr,
+ "error: too many digits in key/salt "
+ "(should be %d hexadecimal digits, found %u)\n",
policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key));
exit(1);
}
@@ -506,7 +517,6 @@
policy.ssrc.value = ssrc;
policy.window_size = 0;
policy.allow_repeat_tx = 0;
- policy.ekt = NULL;
policy.next = NULL;
}
diff --git a/test/rtpw_test.sh b/test/rtpw_test.sh
index 8fcb35f..d6d0474 100755
--- a/test/rtpw_test.sh
+++ b/test/rtpw_test.sh
@@ -66,13 +66,13 @@
ARGS="-b $key -a -e 128"
-# First, we run "killall" to get rid of all existing rtpw processes.
+# First, we run "pkill" to get rid of all existing rtpw processes.
# This step also enables this script to clean up after itself; if this
# script is interrupted after the rtpw processes are started but before
# they are killed, those processes will linger. Re-running the script
# will get rid of them.
-killall rtpw 2>/dev/null
+pkill -x rtpw 2>/dev/null
if test -n $MESON_EXE_WRAPPER || test -x $RTPW; then
diff --git a/test/rtpw_test_gcm.sh b/test/rtpw_test_gcm.sh
index 1722f44..e0cf9c1 100755
--- a/test/rtpw_test_gcm.sh
+++ b/test/rtpw_test_gcm.sh
@@ -62,13 +62,13 @@
DEST_PORT=9999
DURATION=3
-# First, we run "killall" to get rid of all existing rtpw processes.
+# First, we run "pkill" to get rid of all existing rtpw processes.
# This step also enables this script to clean up after itself; if this
# script is interrupted after the rtpw processes are started but before
# they are killed, those processes will linger. Re-running the script
# will get rid of them.
-killall rtpw 2>/dev/null
+pkill -x rtpw 2>/dev/null
if test -n $MESON_EXE_WRAPPER || test -x $RTPW; then
diff --git a/test/srtp_driver.c b/test/srtp_driver.c
index 1335540..7307e16 100644
--- a/test/srtp_driver.c
+++ b/test/srtp_driver.c
@@ -49,6 +49,7 @@
#include "getopt_s.h" /* for local getopt() */
#include "srtp_priv.h"
+#include "stream_list_priv.h"
#include "util.h"
#ifdef HAVE_NETINET_IN_H
@@ -61,6 +62,8 @@
srtp_err_status_t srtp_validate(void);
+srtp_err_status_t srtp_validate_null(void);
+
#ifdef GCM
srtp_err_status_t srtp_validate_gcm(void);
#endif
@@ -91,6 +94,8 @@
srtp_err_status_t srtp_test_protect_rtcp_trailer_length(void);
+srtp_err_status_t srtp_test_out_of_order_after_rollover(void);
+
srtp_err_status_t srtp_test_get_roc(void);
srtp_err_status_t srtp_test_set_receiver_roc(void);
@@ -117,15 +122,19 @@
srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy);
char *srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len);
+char *srtp_rtcp_packet_to_string(srtcp_hdr_t *hdr, int pkt_octet_len);
double mips_estimate(int num_trials, int *ignore);
+srtp_err_status_t srtp_stream_list_test(void);
+
#define TEST_MKI_ID_SIZE 4
extern uint8_t test_key[46];
extern uint8_t test_key_2[46];
extern uint8_t test_mki_id[TEST_MKI_ID_SIZE];
extern uint8_t test_mki_id_2[TEST_MKI_ID_SIZE];
+extern uint8_t test_key_gcm[28];
// clang-format off
srtp_master_key_t master_key_1 = {
@@ -148,21 +157,24 @@
void usage(char *prog_name)
{
- printf("usage: %s [ -t ][ -c ][ -v ][ -o ][-d <debug_module> ]* [ -l ]\n"
- " -t run timing test\n"
- " -r run rejection timing test\n"
- " -c run codec timing test\n"
- " -v run validation tests\n"
- " -o output logging to stdout\n"
- " -d <mod> turn on debugging module <mod>\n"
- " -l list debugging modules\n",
- prog_name);
+ printf(
+ "usage: %s [ -t ][ -c ][ -v ][ -s ][ -o ][-d <debug_module> ]* [ -l ]\n"
+ " -t run timing test\n"
+ " -r run rejection timing test\n"
+ " -c run codec timing test\n"
+ " -v run validation tests\n"
+ " -s run stream list tests only\n"
+ " -o output logging to stdout\n"
+ " -d <mod> turn on debugging module <mod>\n"
+ " -l list debugging modules\n",
+ prog_name);
exit(1);
}
void log_handler(srtp_log_level_t level, const char *msg, void *data)
{
char level_char = '?';
+ (void)data;
switch (level) {
case srtp_log_level_error:
level_char = 'e';
@@ -181,11 +193,12 @@
}
/*
- * The policy_array is a null-terminated array of policy structs. it
- * is declared at the end of this file
+ * The policy_array and invalid_policy_array are null-terminated arrays of
+ * policy structs. They is declared at the end of this file.
*/
extern const srtp_policy_t *policy_array[];
+extern const srtp_policy_t *invalid_policy_array[];
/* the wildcard_policy is declared below; it has a wildcard ssrc */
@@ -210,18 +223,20 @@
unsigned do_rejection_test = 0;
unsigned do_codec_timing = 0;
unsigned do_validation = 0;
+ unsigned do_stream_list = 0;
unsigned do_list_mods = 0;
unsigned do_log_stdout = 0;
srtp_err_status_t status;
+ const size_t hdr_size = 12;
/*
* verify that the compiler has interpreted the header data
* structure srtp_hdr_t correctly
*/
- if (sizeof(srtp_hdr_t) != 12) {
+ if (sizeof(srtp_hdr_t) != hdr_size) {
printf("error: srtp_hdr_t has incorrect size"
- "(size is %ld bytes, expected 12)\n",
- (long)sizeof(srtp_hdr_t));
+ "(size is %ld bytes, expected %ld)\n",
+ (long)sizeof(srtp_hdr_t), (long)hdr_size);
exit(1);
}
@@ -243,7 +258,7 @@
/* process input arguments */
while (1) {
- q = getopt_s(argc, argv, "trcvold:");
+ q = getopt_s(argc, argv, "trcvsold:");
if (q == -1) {
break;
}
@@ -259,6 +274,10 @@
break;
case 'v':
do_validation = 1;
+ do_stream_list = 1;
+ break;
+ case 's':
+ do_stream_list = 1;
break;
case 'o':
do_log_stdout = 1;
@@ -279,7 +298,7 @@
}
if (!do_validation && !do_timing_test && !do_codec_timing &&
- !do_list_mods && !do_rejection_test) {
+ !do_list_mods && !do_rejection_test && !do_stream_list) {
usage(argv[0]);
}
@@ -302,6 +321,7 @@
if (do_validation) {
const srtp_policy_t **policy = policy_array;
srtp_policy_t *big_policy;
+ srtp_t srtp_sender;
/* loop over policy array, testing srtp and srtcp for each policy */
while (*policy != NULL) {
@@ -364,6 +384,21 @@
policy++;
}
+ /* loop over invalid policy array, testing that an SRTP context cannot
+ * be created with the policy */
+ policy = invalid_policy_array;
+ while (*policy != NULL) {
+ printf("testing srtp_create fails with invalid policy\n");
+ if (srtp_create(&srtp_sender, *policy) != srtp_err_status_ok) {
+ printf("passed\n\n");
+ } else {
+ printf("failed\n");
+ exit(1);
+ }
+
+ policy++;
+ }
+
/* create a big policy list and run tests on it */
status = srtp_create_big_policy(&big_policy);
if (status) {
@@ -422,6 +457,15 @@
exit(1);
}
+ printf("testing srtp_protect and srtp_unprotect against "
+ "reference packet using null cipher and HMAC\n");
+ if (srtp_validate_null() == srtp_err_status_ok) {
+ printf("passed\n\n");
+ } else {
+ printf("failed\n");
+ exit(1);
+ }
+
#ifdef GCM
printf("testing srtp_protect and srtp_unprotect against "
"reference packet using GCM\n");
@@ -531,6 +575,14 @@
exit(1);
}
+ printf("testing srtp_test_out_of_order_after_rollover()...");
+ if (srtp_test_out_of_order_after_rollover() == srtp_err_status_ok) {
+ printf("passed\n");
+ } else {
+ printf("failed\n");
+ exit(1);
+ }
+
printf("testing srtp_test_get_roc()...");
if (srtp_test_get_roc() == srtp_err_status_ok) {
printf("passed\n");
@@ -556,6 +608,16 @@
}
}
+ if (do_stream_list) {
+ printf("testing srtp_stream_list...");
+ if (srtp_stream_list_test() == srtp_err_status_ok) {
+ printf("passed\n");
+ } else {
+ printf("failed\n");
+ exit(1);
+ }
+ }
+
if (do_timing_test) {
const srtp_policy_t **policy = policy_array;
@@ -589,7 +651,7 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xdecafbad;
policy.key = test_key;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
@@ -690,6 +752,47 @@
return hdr;
}
+srtcp_hdr_t *srtp_create_rtcp_test_packet(int pkt_octet_len,
+ uint32_t ssrc,
+ int *pkt_len)
+{
+ int i;
+ uint8_t *buffer;
+ srtcp_hdr_t *hdr;
+ int bytes_in_hdr = 8;
+
+ /* allocate memory for test packet */
+ hdr = (srtcp_hdr_t *)malloc(pkt_octet_len + bytes_in_hdr +
+ SRTP_MAX_SRTCP_TRAILER_LEN + 4);
+ if (!hdr) {
+ return NULL;
+ }
+
+ hdr->version = 2; /* RTP version two */
+ hdr->p = 0; /* no padding needed */
+ hdr->rc = 0; /* no reports */
+ hdr->pt = 0xc8; /* sender report (200) */
+ hdr->len = ((bytes_in_hdr + pkt_octet_len) % 4) - 1;
+ hdr->ssrc = htonl(ssrc); /* synch. source */
+
+ buffer = (uint8_t *)hdr;
+ buffer += bytes_in_hdr;
+
+ /* set data to 0xab */
+ for (i = 0; i < pkt_octet_len; i++) {
+ *buffer++ = 0xab;
+ }
+
+ /* set post-data value to 0xffff to enable overrun checking */
+ for (i = 0; i < SRTP_MAX_SRTCP_TRAILER_LEN + 4; i++) {
+ *buffer++ = 0xff;
+ }
+
+ *pkt_len = bytes_in_hdr + pkt_octet_len;
+
+ return hdr;
+}
+
static srtp_hdr_t *srtp_create_test_packet_extended(int pkt_octet_len,
uint32_t ssrc,
uint16_t seq,
@@ -928,12 +1031,10 @@
void err_check(srtp_err_status_t s)
{
- if (s == srtp_err_status_ok) {
- return;
- } else {
+ if (s != srtp_err_status_ok) {
fprintf(stderr, "error: unexpected srtp failure (code %d)\n", s);
+ exit(1);
}
- exit(1);
}
srtp_err_status_t srtp_test_call_protect(srtp_t srtp_sender,
@@ -949,7 +1050,7 @@
}
srtp_err_status_t srtp_test_call_protect_rtcp(srtp_t srtp_sender,
- srtp_hdr_t *hdr,
+ srtcp_hdr_t *hdr,
int *len,
int mki_index)
{
@@ -973,7 +1074,7 @@
}
srtp_err_status_t srtp_test_call_unprotect_rtcp(srtp_t srtp_sender,
- srtp_hdr_t *hdr,
+ srtcp_hdr_t *hdr,
int *len,
int use_mki)
{
@@ -1082,8 +1183,9 @@
pkt_end = (uint8_t *)hdr + msg_len + tag_length;
for (i = 0; i < 4; i++) {
if (pkt_end[i] != 0xff) {
- fprintf(stdout, "overwrite in srtp_protect() function "
- "(expected %x, found %x in trailing octet %d)\n",
+ fprintf(stdout,
+ "overwrite in srtp_protect() function "
+ "(expected %x, found %x in trailing octet %d)\n",
0xff, ((uint8_t *)hdr)[i], i);
free(hdr);
free(hdr2);
@@ -1179,7 +1281,7 @@
free(hdr);
free(hdr2);
free(rcvr_policy);
- return status;
+ return srtp_err_status_algo_fail;
} else {
printf("passed\n");
}
@@ -1198,11 +1300,12 @@
/* unprotect, and check for authentication failure */
status = srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki);
if (status != srtp_err_status_auth_fail) {
+ printf("failed with error code %d\n", status);
printf("failed\n");
free(hdr);
free(hdr2);
free(rcvr_policy);
- return status;
+ return srtp_err_status_algo_fail;
} else {
printf("passed\n");
}
@@ -1223,7 +1326,7 @@
srtp_t srtcp_sender;
srtp_t srtcp_rcvr;
srtp_err_status_t status = srtp_err_status_ok;
- srtp_hdr_t *hdr, *hdr2;
+ srtcp_hdr_t *hdr, *hdr2;
uint8_t hdr_enc[64];
uint8_t *pkt_end;
int msg_len_octets, msg_len_enc, msg_len;
@@ -1252,21 +1355,21 @@
ssrc = policy->ssrc.value;
}
msg_len_octets = 28;
- hdr = srtp_create_test_packet(msg_len_octets, ssrc, &len);
+ hdr = srtp_create_rtcp_test_packet(msg_len_octets, ssrc, &len);
/* save message len */
msg_len = len;
if (hdr == NULL) {
return srtp_err_status_alloc_fail;
}
- hdr2 = srtp_create_test_packet(msg_len_octets, ssrc, &len2);
+ hdr2 = srtp_create_rtcp_test_packet(msg_len_octets, ssrc, &len2);
if (hdr2 == NULL) {
free(hdr);
return srtp_err_status_alloc_fail;
}
debug_print(mod_driver, "before protection:\n%s",
- srtp_packet_to_string(hdr, len));
+ srtp_rtcp_packet_to_string(hdr, len));
#if PRINT_REFERENCE_PACKET
debug_print(mod_driver, "reference packet before protection:\n%s",
@@ -1275,7 +1378,7 @@
err_check(srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index));
debug_print(mod_driver, "after protection:\n%s",
- srtp_packet_to_string(hdr, len));
+ srtp_rtcp_packet_to_string(hdr, len));
#if PRINT_REFERENCE_PACKET
debug_print(mod_driver, "after protection:\n%s",
octet_string_hex_string((uint8_t *)hdr, len));
@@ -1286,7 +1389,7 @@
msg_len_enc = len;
/*
- * check for overrun of the srtp_protect() function
+ * check for overrun of the srtp_protect_rtcp() function
*
* The packet is followed by a value of 0xfffff; if the value of the
* data following the packet is different, then we know that the
@@ -1297,8 +1400,9 @@
pkt_end = (uint8_t *)hdr + msg_len + tag_length;
for (i = 0; i < 4; i++) {
if (pkt_end[i] != 0xff) {
- fprintf(stdout, "overwrite in srtp_protect_rtcp() function "
- "(expected %x, found %x in trailing octet %d)\n",
+ fprintf(stdout,
+ "overwrite in srtp_protect_rtcp() function "
+ "(expected %x, found %x in trailing octet %d)\n",
0xff, ((uint8_t *)hdr)[i], i);
free(hdr);
free(hdr2);
@@ -1355,9 +1459,9 @@
err_check(srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki));
debug_print(mod_driver, "after unprotection:\n%s",
- srtp_packet_to_string(hdr, len));
+ srtp_rtcp_packet_to_string(hdr, len));
- /* verify that the unprotected packet matches the origial one */
+ /* verify that the unprotected packet matches the original one */
for (i = 0; i < len; i++) {
if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
fprintf(stdout, "mismatch at octet %d\n", i);
@@ -1387,16 +1491,13 @@
free(hdr);
free(hdr2);
free(rcvr_policy);
- return status;
+ return srtp_err_status_algo_fail;
} else {
printf("passed\n");
}
printf("testing for false positives in auth check...");
- /* increment sequence number in header */
- hdr->seq++;
-
/* apply protection */
err_check(
srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index));
@@ -1407,11 +1508,12 @@
/* unprotect, and check for authentication failure */
status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki);
if (status != srtp_err_status_auth_fail) {
+ printf("failed with error code %d\n", status);
printf("failed\n");
free(hdr);
free(hdr2);
free(rcvr_policy);
- return status;
+ return srtp_err_status_algo_fail;
} else {
printf("passed\n");
}
@@ -1426,13 +1528,75 @@
return srtp_err_status_ok;
}
+struct srtp_session_print_stream_data {
+ // set by callback to indicate failure
+ srtp_err_status_t status;
+ // indicates if it is the template stream or a regular stream
+ int is_template;
+};
+
+int srtp_session_print_stream(srtp_stream_t stream, void *raw_data)
+{
+ static const char *serv_descr[4] = { "none", "confidentiality",
+ "authentication",
+ "confidentiality and authentication" };
+ static const char *direction[3] = { "unknown", "outbound", "inbound" };
+
+ struct srtp_session_print_stream_data *data =
+ (struct srtp_session_print_stream_data *)raw_data;
+ srtp_session_keys_t *session_keys = &stream->session_keys[0];
+ char ssrc_text[32];
+
+ if (!data->is_template && stream->rtp_services > sec_serv_conf_and_auth) {
+ data->status = srtp_err_status_bad_param;
+ return 1;
+ }
+
+ if (data->is_template) {
+ snprintf(ssrc_text, sizeof(ssrc_text), "any %s",
+ direction[stream->direction]);
+ } else {
+ snprintf(ssrc_text, sizeof(ssrc_text), "0x%08x", stream->ssrc);
+ }
+
+ printf("# SSRC: %s\r\n"
+ "# rtp cipher: %s\r\n"
+ "# rtp auth: %s\r\n"
+ "# rtp services: %s\r\n"
+ "# rtcp cipher: %s\r\n"
+ "# rtcp auth: %s\r\n"
+ "# rtcp services: %s\r\n"
+ "# window size: %lu\r\n"
+ "# tx rtx allowed:%s\r\n",
+ ssrc_text, session_keys->rtp_cipher->type->description,
+ session_keys->rtp_auth->type->description,
+ serv_descr[stream->rtp_services],
+ session_keys->rtcp_cipher->type->description,
+ session_keys->rtcp_auth->type->description,
+ serv_descr[stream->rtcp_services],
+ srtp_rdbx_get_window_size(&stream->rtp_rdbx),
+ stream->allow_repeat_tx ? "true" : "false");
+
+ printf("# Encrypted extension headers: ");
+ if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) {
+ int *enc_xtn_hdr = stream->enc_xtn_hdr;
+ int count = stream->enc_xtn_hdr_count;
+ while (count > 0) {
+ printf("%d ", *enc_xtn_hdr);
+ enc_xtn_hdr++;
+ count--;
+ }
+ printf("\n");
+ } else {
+ printf("none\n");
+ }
+
+ return 0;
+}
+
srtp_err_status_t srtp_session_print_policy(srtp_t srtp)
{
- char *serv_descr[4] = { "none", "confidentiality", "authentication",
- "confidentiality and authentication" };
- char *direction[3] = { "unknown", "outbound", "inbound" };
- srtp_stream_t stream;
- srtp_session_keys_t *session_keys = NULL;
+ struct srtp_session_print_stream_data data = { srtp_err_status_ok, 0 };
/* sanity checking */
if (srtp == NULL) {
@@ -1441,86 +1605,16 @@
/* if there's a template stream, print it out */
if (srtp->stream_template != NULL) {
- stream = srtp->stream_template;
- session_keys = &stream->session_keys[0];
- printf("# SSRC: any %s\r\n"
- "# rtp cipher: %s\r\n"
- "# rtp auth: %s\r\n"
- "# rtp services: %s\r\n"
- "# rtcp cipher: %s\r\n"
- "# rtcp auth: %s\r\n"
- "# rtcp services: %s\r\n"
- "# window size: %lu\r\n"
- "# tx rtx allowed:%s\r\n",
- direction[stream->direction],
- session_keys->rtp_cipher->type->description,
- session_keys->rtp_auth->type->description,
- serv_descr[stream->rtp_services],
- session_keys->rtcp_cipher->type->description,
- session_keys->rtcp_auth->type->description,
- serv_descr[stream->rtcp_services],
- srtp_rdbx_get_window_size(&stream->rtp_rdbx),
- stream->allow_repeat_tx ? "true" : "false");
-
- printf("# Encrypted extension headers: ");
- if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) {
- int *enc_xtn_hdr = stream->enc_xtn_hdr;
- int count = stream->enc_xtn_hdr_count;
- while (count > 0) {
- printf("%d ", *enc_xtn_hdr);
- enc_xtn_hdr++;
- count--;
- }
- printf("\n");
- } else {
- printf("none\n");
- }
+ data.is_template = 1;
+ srtp_session_print_stream(srtp->stream_template, &data);
}
/* loop over streams in session, printing the policy of each */
- stream = srtp->stream_list;
- while (stream != NULL) {
- if (stream->rtp_services > sec_serv_conf_and_auth) {
- return srtp_err_status_bad_param;
- }
- session_keys = &stream->session_keys[0];
+ data.is_template = 0;
+ srtp_stream_list_for_each(srtp->stream_list, srtp_session_print_stream,
+ &data);
- printf("# SSRC: 0x%08x\r\n"
- "# rtp cipher: %s\r\n"
- "# rtp auth: %s\r\n"
- "# rtp services: %s\r\n"
- "# rtcp cipher: %s\r\n"
- "# rtcp auth: %s\r\n"
- "# rtcp services: %s\r\n"
- "# window size: %lu\r\n"
- "# tx rtx allowed:%s\r\n",
- stream->ssrc, session_keys->rtp_cipher->type->description,
- session_keys->rtp_auth->type->description,
- serv_descr[stream->rtp_services],
- session_keys->rtcp_cipher->type->description,
- session_keys->rtcp_auth->type->description,
- serv_descr[stream->rtcp_services],
- srtp_rdbx_get_window_size(&stream->rtp_rdbx),
- stream->allow_repeat_tx ? "true" : "false");
-
- printf("# Encrypted extension headers: ");
- if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) {
- int *enc_xtn_hdr = stream->enc_xtn_hdr;
- int count = stream->enc_xtn_hdr_count;
- while (count > 0) {
- printf("%d ", *enc_xtn_hdr);
- enc_xtn_hdr++;
- count--;
- }
- printf("\n");
- } else {
- printf("none\n");
- }
-
- /* advance to next stream in the list */
- stream = stream->next;
- }
- return srtp_err_status_ok;
+ return data.status;
}
srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy)
@@ -1568,21 +1662,50 @@
}
/* write packet into string */
- sprintf(packet_string, "(s)rtp packet: {\n"
- " version:\t%d\n"
- " p:\t\t%d\n"
- " x:\t\t%d\n"
- " cc:\t\t%d\n"
- " m:\t\t%d\n"
- " pt:\t\t%x\n"
- " seq:\t\t%x\n"
- " ts:\t\t%x\n"
- " ssrc:\t%x\n"
- " data:\t%s\n"
- "} (%d octets in total)\n",
- hdr->version, hdr->p, hdr->x, hdr->cc, hdr->m, hdr->pt, hdr->seq,
- hdr->ts, hdr->ssrc, octet_string_hex_string(data, hex_len),
- pkt_octet_len);
+ snprintf(packet_string, sizeof(packet_string),
+ "(s)rtp packet: {\n"
+ " version:\t%d\n"
+ " p:\t\t%d\n"
+ " x:\t\t%d\n"
+ " cc:\t\t%d\n"
+ " m:\t\t%d\n"
+ " pt:\t\t%x\n"
+ " seq:\t\t%x\n"
+ " ts:\t\t%x\n"
+ " ssrc:\t%x\n"
+ " data:\t%s\n"
+ "} (%d octets in total)\n",
+ hdr->version, hdr->p, hdr->x, hdr->cc, hdr->m, hdr->pt, hdr->seq,
+ hdr->ts, hdr->ssrc, octet_string_hex_string(data, hex_len),
+ pkt_octet_len);
+
+ return packet_string;
+}
+
+char *srtp_rtcp_packet_to_string(srtcp_hdr_t *hdr, int pkt_octet_len)
+{
+ int octets_in_rtcp_header = 8;
+ uint8_t *data = ((uint8_t *)hdr) + octets_in_rtcp_header;
+ int hex_len = pkt_octet_len - octets_in_rtcp_header;
+
+ /* sanity checking */
+ if ((hdr == NULL) || (pkt_octet_len > MTU)) {
+ return NULL;
+ }
+
+ /* write packet into string */
+ snprintf(packet_string, sizeof(packet_string),
+ "(s)rtcp packet: {\n"
+ " version:\t%d\n"
+ " p:\t\t%d\n"
+ " rc:\t\t%d\n"
+ " pt:\t\t%x\n"
+ " len:\t\t%x\n"
+ " ssrc:\t%x\n"
+ " data:\t%s\n"
+ "} (%d octets in total)\n",
+ hdr->version, hdr->p, hdr->rc, hdr->pt, hdr->len, hdr->ssrc,
+ octet_string_hex_string(data, hex_len), pkt_octet_len);
return packet_string;
}
@@ -1624,7 +1747,7 @@
* These packets were made with the default SRTP policy.
*/
-srtp_err_status_t srtp_validate()
+srtp_err_status_t srtp_validate(void)
{
// clang-format off
uint8_t srtp_plaintext_ref[28] = {
@@ -1683,7 +1806,167 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = test_key;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
+ policy.window_size = 128;
+ policy.allow_repeat_tx = 0;
+ policy.next = NULL;
+
+ status = srtp_create(&srtp_snd, &policy);
+ if (status) {
+ return status;
+ }
+
+ /*
+ * protect plaintext, then compare with ciphertext
+ */
+ len = 28;
+ status = srtp_protect(srtp_snd, srtp_plaintext, &len);
+ if (status || (len != 38)) {
+ return srtp_err_status_fail;
+ }
+
+ debug_print(mod_driver, "ciphertext:\n %s",
+ octet_string_hex_string(srtp_plaintext, len));
+ debug_print(mod_driver, "ciphertext reference:\n %s",
+ octet_string_hex_string(srtp_ciphertext, len));
+
+ if (srtp_octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) {
+ return srtp_err_status_fail;
+ }
+
+ /*
+ * protect plaintext rtcp, then compare with srtcp ciphertext
+ */
+ len = 24;
+ status = srtp_protect_rtcp(srtp_snd, rtcp_plaintext, &len);
+ if (status || (len != 38)) {
+ return srtp_err_status_fail;
+ }
+
+ debug_print(mod_driver, "srtcp ciphertext:\n %s",
+ octet_string_hex_string(rtcp_plaintext, len));
+ debug_print(mod_driver, "srtcp ciphertext reference:\n %s",
+ octet_string_hex_string(srtcp_ciphertext, len));
+
+ if (srtp_octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) {
+ 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, srtp_ciphertext, &len);
+ if (status || (len != 28)) {
+ return status;
+ }
+
+ if (srtp_octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) {
+ return srtp_err_status_fail;
+ }
+
+ /*
+ * unprotect srtcp ciphertext, then compare with rtcp plaintext
+ */
+ len = 38;
+ status = srtp_unprotect_rtcp(srtp_recv, srtcp_ciphertext, &len);
+ if (status || (len != 24)) {
+ return status;
+ }
+
+ if (srtp_octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) {
+ return srtp_err_status_fail;
+ }
+
+ status = srtp_dealloc(srtp_snd);
+ if (status) {
+ return status;
+ }
+
+ status = srtp_dealloc(srtp_recv);
+ if (status) {
+ return status;
+ }
+
+ return srtp_err_status_ok;
+}
+
+/*
+ * srtp_validate_null() verifies the correctness of libsrtp by comparing
+ * some computed packets against some pre-computed reference values.
+ * These packets were made with a policy that applies null encryption
+ * and HMAC authentication.
+ */
+
+srtp_err_status_t srtp_validate_null(void)
+{
+ // clang-format off
+ uint8_t srtp_plaintext_ref[28] = {
+ 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
+ 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab
+ };
+ uint8_t srtp_plaintext[38] = {
+ 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
+ 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ uint8_t srtp_ciphertext[38] = {
+ 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
+ 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xa1, 0x36, 0x27,
+ 0x0b, 0x67, 0x91, 0x34, 0xce, 0x9b
+ };
+ uint8_t rtcp_plaintext_ref[24] = {
+ 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ };
+ uint8_t rtcp_plaintext[38] = {
+ 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ uint8_t srtcp_ciphertext[38] = {
+ 0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x88, 0xc7, 0xfd,
+ 0xfd, 0x37, 0xeb, 0xce, 0x61, 0x5d,
+ };
+ // clang-format on
+
+ srtp_t srtp_snd, srtp_recv;
+ srtp_err_status_t status;
+ int len;
+ srtp_policy_t policy;
+
+ /*
+ * 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_null_cipher_hmac_sha1_80(&policy.rtp);
+ srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtcp);
+ policy.ssrc.type = ssrc_specific;
+ policy.ssrc.value = 0xcafebabe;
+ policy.key = test_key;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
@@ -1782,15 +2065,9 @@
* srtp_validate_gcm() verifies the correctness of libsrtp by comparing
* an computed packet against the known ciphertext for the plaintext.
*/
-srtp_err_status_t srtp_validate_gcm()
+srtp_err_status_t srtp_validate_gcm(void)
{
// clang-format off
- unsigned char test_key_gcm[28] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xab
- };
uint8_t rtp_plaintext_ref[28] = {
0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
@@ -1851,7 +2128,7 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = test_key_gcm;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
@@ -1929,6 +2206,12 @@
return status;
}
+ debug_print(mod_driver, "srtcp plain:\n %s",
+ octet_string_hex_string(srtcp_ciphertext, len));
+ debug_print(mod_driver, "srtcp plain reference:\n %s",
+ octet_string_hex_string(rtcp_plaintext_ref,
+ sizeof(rtcp_plaintext_ref)));
+
if (srtp_octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) {
return srtp_err_status_fail;
}
@@ -1950,7 +2233,7 @@
/*
* Test vectors taken from RFC 6904, Appendix A
*/
-srtp_err_status_t srtp_validate_encrypted_extensions_headers()
+srtp_err_status_t srtp_validate_encrypted_extensions_headers(void)
{
// clang-format off
unsigned char test_key_ext_headers[30] = {
@@ -2008,7 +2291,7 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = test_key_ext_headers;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.enc_xtn_hdr = headers;
@@ -2073,7 +2356,7 @@
/*
* Headers of test vectors taken from RFC 6904, Appendix A
*/
-srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm()
+srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void)
{
// clang-format off
unsigned char test_key_ext_headers[30] = {
@@ -2129,7 +2412,7 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = test_key_ext_headers;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.enc_xtn_hdr = headers;
@@ -2196,7 +2479,7 @@
* These packets were made with the AES-CM-256/HMAC-SHA-1-80 policy.
*/
-srtp_err_status_t srtp_validate_aes_256()
+srtp_err_status_t srtp_validate_aes_256(void)
{
// clang-format off
unsigned char aes_256_test_key[46] = {
@@ -2245,7 +2528,7 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = aes_256_test_key;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
@@ -2311,7 +2594,8 @@
srtp_err_status_t srtp_create_big_policy(srtp_policy_t **list)
{
extern const srtp_policy_t *policy_array[];
- srtp_policy_t *p, *tmp;
+ srtp_policy_t *p = NULL;
+ srtp_policy_t *tmp;
int i = 0;
uint32_t ssrc = 0;
@@ -2354,7 +2638,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_test_empty_payload()
+srtp_err_status_t srtp_test_empty_payload(void)
{
srtp_t srtp_snd, srtp_recv;
srtp_err_status_t status;
@@ -2372,7 +2656,7 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = test_key;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
@@ -2430,7 +2714,7 @@
}
#ifdef GCM
-srtp_err_status_t srtp_test_empty_payload_gcm()
+srtp_err_status_t srtp_test_empty_payload_gcm(void)
{
srtp_t srtp_snd, srtp_recv;
srtp_err_status_t status;
@@ -2448,7 +2732,7 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = test_key;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
@@ -2506,7 +2790,7 @@
}
#endif // GCM
-srtp_err_status_t srtp_test_remove_stream()
+srtp_err_status_t srtp_test_remove_stream(void)
{
srtp_err_status_t status;
srtp_policy_t *policy_list, policy;
@@ -2573,7 +2857,7 @@
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = test_key;
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
@@ -2619,7 +2903,7 @@
* atempts to prove that srtp_update does not reset the ROC.
*/
-srtp_err_status_t srtp_test_update()
+srtp_err_status_t srtp_test_update(void)
{
srtp_err_status_t status;
uint32_t ssrc = 0x12121212;
@@ -2632,20 +2916,20 @@
memset(&policy, 0, sizeof(policy));
srtp_crypto_policy_set_rtp_default(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
- policy.ssrc.type = ssrc_any_outbound;
policy.key = test_key;
/* create a send and recive ctx with defualt profile and test_key */
- status = srtp_create(&srtp_recv, &policy);
+ policy.ssrc.type = ssrc_any_outbound;
+ status = srtp_create(&srtp_snd, &policy);
if (status)
return status;
policy.ssrc.type = ssrc_any_inbound;
- status = srtp_create(&srtp_snd, &policy);
+ status = srtp_create(&srtp_recv, &policy);
if (status)
return status;
@@ -2791,12 +3075,15 @@
#ifdef GCM
srtp_policy_t policy_aes_gcm;
srtp_policy_t policy_aes_gcm_mki;
+#else
+ (void)srtp_send_aes_gcm;
+ (void)srtp_send_aes_gcm_mki;
#endif // GCM
memset(&policy, 0, sizeof(policy));
srtp_crypto_policy_set_rtp_default(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
- policy.ekt = NULL;
+ policy.deprecated_ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
@@ -2806,7 +3093,7 @@
memset(&policy_mki, 0, sizeof(policy_mki));
srtp_crypto_policy_set_rtp_default(&policy_mki.rtp);
srtp_crypto_policy_set_rtcp_default(&policy_mki.rtcp);
- policy_mki.ekt = NULL;
+ policy_mki.deprecated_ekt = NULL;
policy_mki.window_size = 128;
policy_mki.allow_repeat_tx = 0;
policy_mki.next = NULL;
@@ -2819,7 +3106,7 @@
memset(&policy_aes_gcm, 0, sizeof(policy_aes_gcm));
srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtp);
srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtcp);
- policy_aes_gcm.ekt = NULL;
+ policy_aes_gcm.deprecated_ekt = NULL;
policy_aes_gcm.window_size = 128;
policy_aes_gcm.allow_repeat_tx = 0;
policy_aes_gcm.next = NULL;
@@ -2829,7 +3116,7 @@
memset(&policy_aes_gcm_mki, 0, sizeof(policy_aes_gcm_mki));
srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtp);
srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtcp);
- policy_aes_gcm_mki.ekt = NULL;
+ policy_aes_gcm_mki.deprecated_ekt = NULL;
policy_aes_gcm_mki.window_size = 128;
policy_aes_gcm_mki.allow_repeat_tx = 0;
policy_aes_gcm_mki.next = NULL;
@@ -2861,7 +3148,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_test_protect_trailer_length()
+srtp_err_status_t srtp_test_protect_trailer_length(void)
{
srtp_t srtp_send;
srtp_t srtp_send_mki;
@@ -2918,7 +3205,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_test_protect_rtcp_trailer_length()
+srtp_err_status_t srtp_test_protect_rtcp_trailer_length(void)
{
srtp_t srtp_send;
srtp_t srtp_send_mki;
@@ -2976,7 +3263,225 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_test_get_roc()
+srtp_err_status_t srtp_test_out_of_order_after_rollover(void)
+{
+ srtp_err_status_t status;
+
+ srtp_policy_t sender_policy;
+ srtp_t sender_session;
+
+ srtp_policy_t receiver_policy;
+ srtp_t receiver_session;
+
+ const uint32_t num_pkts = 5;
+ srtp_hdr_t *pkts[5];
+ int pkt_len_octets[5];
+
+ uint32_t i;
+ uint32_t stream_roc;
+
+ /* Create 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;
+
+ status = srtp_create(&sender_session, &sender_policy);
+ if (status) {
+ return status;
+ }
+
+ /* 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;
+
+ status = srtp_create(&receiver_session, &receiver_policy);
+ if (status) {
+ return status;
+ }
+
+ /* Create and protect packets to get to get roc == 1 */
+ pkts[0] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value,
+ 65534, 0, &pkt_len_octets[0]);
+ status = srtp_protect(sender_session, pkts[0], &pkt_len_octets[0]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 0) {
+ return srtp_err_status_fail;
+ }
+
+ pkts[1] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value,
+ 65535, 1, &pkt_len_octets[1]);
+ status = srtp_protect(sender_session, pkts[1], &pkt_len_octets[1]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 0) {
+ return srtp_err_status_fail;
+ }
+
+ pkts[2] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value, 0,
+ 2, &pkt_len_octets[2]);
+ status = srtp_protect(sender_session, pkts[2], &pkt_len_octets[2]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 1) {
+ return srtp_err_status_fail;
+ }
+
+ pkts[3] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value, 1,
+ 3, &pkt_len_octets[3]);
+ status = srtp_protect(sender_session, pkts[3], &pkt_len_octets[3]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 1) {
+ return srtp_err_status_fail;
+ }
+
+ pkts[4] = srtp_create_test_packet_extended(64, sender_policy.ssrc.value, 2,
+ 4, &pkt_len_octets[4]);
+ status = srtp_protect(sender_session, pkts[4], &pkt_len_octets[4]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(sender_session, sender_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 1) {
+ return srtp_err_status_fail;
+ }
+
+ /* Unprotect packets in this seq order 65534, 0, 2, 1, 65535 which is
+ * equivalent to index 0, 2, 4, 3, 1*/
+ status = srtp_unprotect(receiver_session, pkts[0], &pkt_len_octets[0]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 0) {
+ return srtp_err_status_fail;
+ }
+
+ status = srtp_unprotect(receiver_session, pkts[2], &pkt_len_octets[2]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 1) {
+ return srtp_err_status_fail;
+ }
+
+ status = srtp_unprotect(receiver_session, pkts[4], &pkt_len_octets[4]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 1) {
+ return srtp_err_status_fail;
+ }
+
+ status = srtp_unprotect(receiver_session, pkts[3], &pkt_len_octets[3]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 1) {
+ return srtp_err_status_fail;
+ }
+
+ status = srtp_unprotect(receiver_session, pkts[1], &pkt_len_octets[1]);
+ if (status) {
+ return status;
+ }
+ status = srtp_get_stream_roc(receiver_session, receiver_policy.ssrc.value,
+ &stream_roc);
+ if (status) {
+ return status;
+ }
+ if (stream_roc != 1) {
+ return srtp_err_status_fail;
+ }
+
+ /* Cleanup */
+ status = srtp_dealloc(sender_session);
+ if (status) {
+ return status;
+ }
+
+ status = srtp_dealloc(receiver_session);
+ if (status) {
+ return status;
+ }
+
+ for (i = 0; i < num_pkts; i++) {
+ free(pkts[i]);
+ }
+
+ return srtp_err_status_ok;
+}
+
+srtp_err_status_t srtp_test_get_roc(void)
{
srtp_err_status_t status;
srtp_policy_t policy;
@@ -3060,6 +3565,7 @@
uint32_t i;
uint32_t ts;
uint16_t seq;
+ uint16_t stride;
int msg_len_octets = 32;
int protected_msg_len_octets_1;
@@ -3067,11 +3573,17 @@
/* Create 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.key = test_key;
sender_policy.window_size = 128;
status = srtp_create(&sender_session, &sender_policy);
@@ -3080,9 +3592,11 @@
}
/* Create and protect packets */
+ i = 0;
seq = 0;
ts = 0;
- for (i = 0; i < packets; i++) {
+ stride = 0x4000;
+ while (i < packets) {
srtp_hdr_t *tmp_pkt;
int tmp_len;
@@ -3094,7 +3608,12 @@
return status;
}
- seq++;
+ while (stride > (packets - i) && stride > 1) {
+ stride >>= 1;
+ }
+
+ i += stride;
+ seq += stride;
ts++;
}
@@ -3120,11 +3639,17 @@
/* 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.key = test_key;
receiver_policy.window_size = 128;
status = srtp_create(&receiver_session, &receiver_policy);
@@ -3206,11 +3731,17 @@
/* Create 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.key = test_key;
sender_policy.window_size = 128;
status = srtp_create(&sender_session, &sender_policy);
@@ -3237,11 +3768,17 @@
/* 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.key = test_key;
receiver_policy.window_size = 128;
status = srtp_create(&receiver_session, &receiver_policy);
@@ -3286,7 +3823,7 @@
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_test_set_receiver_roc()
+srtp_err_status_t srtp_test_set_receiver_roc(void)
{
int packets;
uint32_t roc;
@@ -3342,10 +3879,15 @@
return status;
}
+ status = test_set_receiver_roc(packets + 65535, roc);
+ if (status) {
+ return status;
+ }
+
return srtp_err_status_ok;
}
-srtp_err_status_t srtp_test_set_sender_roc()
+srtp_err_status_t srtp_test_set_sender_roc(void)
{
uint32_t roc;
uint16_t seq;
@@ -3408,6 +3950,13 @@
0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
};
+unsigned char test_key_gcm[28] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab
+};
+
unsigned char test_mki_id[TEST_MKI_ID_SIZE] = {
0xe1, 0xf9, 0x7a, 0x0d
};
@@ -3480,20 +4029,20 @@
const srtp_policy_t hmac_only_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{
- SRTP_NULL_CIPHER, /* cipher type */
- 0, /* cipher key length in octets */
- SRTP_HMAC_SHA1, /* authentication func type */
- 20, /* auth key length in octets */
- 4, /* auth tag length in octets */
- sec_serv_auth /* security services flag */
+ SRTP_NULL_CIPHER, /* cipher type */
+ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */
+ SRTP_HMAC_SHA1, /* authentication func type */
+ 20, /* auth key length in octets */
+ 4, /* auth tag length in octets */
+ sec_serv_auth /* security services flag */
},
{
- SRTP_NULL_CIPHER, /* cipher type */
- 0, /* cipher key length in octets */
- SRTP_HMAC_SHA1, /* authentication func type */
- 20, /* auth key length in octets */
- 4, /* auth tag length in octets */
- sec_serv_auth /* security services flag */
+ SRTP_NULL_CIPHER, /* cipher type */
+ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */
+ SRTP_HMAC_SHA1, /* authentication func type */
+ 20, /* auth key length in octets */
+ 4, /* auth tag length in octets */
+ sec_serv_auth /* security services flag */
},
NULL,
(srtp_master_key_t **)test_keys,
@@ -3635,20 +4184,20 @@
const srtp_policy_t null_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{
- SRTP_NULL_CIPHER, /* cipher type */
- 0, /* cipher key length in octets */
- SRTP_NULL_AUTH, /* authentication func type */
- 0, /* auth key length in octets */
- 0, /* auth tag length in octets */
- sec_serv_none /* security services flag */
+ SRTP_NULL_CIPHER, /* cipher type */
+ SRTP_AES_GCM_256_KEY_LEN_WSALT, /* cipher key length in octets */
+ SRTP_NULL_AUTH, /* authentication func type */
+ 0, /* auth key length in octets */
+ 0, /* auth tag length in octets */
+ sec_serv_none /* security services flag */
},
{
- SRTP_NULL_CIPHER, /* cipher type */
- 0, /* cipher key length in octets */
- SRTP_NULL_AUTH, /* authentication func type */
- 0, /* auth key length in octets */
- 0, /* auth tag length in octets */
- sec_serv_none /* security services flag */
+ SRTP_NULL_CIPHER, /* cipher type */
+ SRTP_AES_GCM_256_KEY_LEN_WSALT, /* cipher key length in octets */
+ SRTP_NULL_AUTH, /* authentication func type */
+ 0, /* auth key length in octets */
+ 0, /* auth tag length in octets */
+ sec_serv_none /* security services flag */
},
NULL,
(srtp_master_key_t **)test_keys,
@@ -3730,23 +4279,7 @@
NULL
};
-// clang-format off
-uint8_t ekt_test_key[16] = {
- 0x77, 0x26, 0x9d, 0xac, 0x16, 0xa3, 0x28, 0xca,
- 0x8e, 0xc9, 0x68, 0x4b, 0xcc, 0xc4, 0xd2, 0x1b
-};
-// clang-format on
-
-#include "ekt.h"
-
-// clang-format off
-srtp_ekt_policy_ctx_t ekt_test_policy = {
- 0xa5a5, /* SPI */
- SRTP_EKT_CIPHER_AES_128_ECB,
- ekt_test_key,
- NULL
-};
-// clang-format on
+char ekt_test_policy = 'x';
const srtp_policy_t hmac_only_with_ekt_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
@@ -3769,7 +4302,7 @@
NULL,
(srtp_master_key_t **)test_keys,
2, /* indicates the number of Master keys */
- &ekt_test_policy, /* indicates that EKT is not in use */
+ &ekt_test_policy, /* requests deprecated EKT functionality */
128, /* replay window size */
0, /* retransmission not allowed */
NULL, /* no encrypted extension headers */
@@ -3800,6 +4333,12 @@
#endif
&null_policy,
&aes_256_hmac_policy,
+ NULL
+};
+// clang-format on
+
+// clang-format off
+const srtp_policy_t *invalid_policy_array[] = {
&hmac_only_with_ekt_policy,
NULL
};
@@ -3835,3 +4374,240 @@
0, /* list of encrypted extension headers is empty */
NULL
};
+
+static srtp_stream_t stream_list_test_create_stream(uint32_t ssrc)
+{
+ srtp_stream_t stream = malloc(sizeof(srtp_stream_ctx_t));
+ stream->ssrc = ssrc;
+ return stream;
+}
+
+static void stream_list_test_free_stream(srtp_stream_t stream)
+{
+ free(stream);
+}
+
+int stream_list_test_count_cb(srtp_stream_t stream, void *data)
+{
+ int *count = (int *)data;
+ (*count)++;
+ (void)stream;
+ return 0;
+}
+
+struct remove_one_data {
+ uint32_t ssrc;
+ srtp_stream_list_t list;
+};
+
+int stream_list_test_remove_one_cb(srtp_stream_t stream, void *data)
+{
+ struct remove_one_data *d = (struct remove_one_data *)data;
+ if (stream->ssrc == d->ssrc) {
+ srtp_stream_list_remove(d->list, stream);
+ stream_list_test_free_stream(stream);
+ return 1;
+ }
+ return 0;
+}
+
+int stream_list_test_remove_all_cb(srtp_stream_t stream, void *data)
+{
+ srtp_stream_list_t *list = (srtp_stream_list_t *)data;
+ srtp_stream_list_remove(*list, stream);
+ stream_list_test_free_stream(stream);
+ return 0;
+}
+
+srtp_err_status_t srtp_stream_list_test(void)
+{
+ srtp_stream_list_t list;
+
+ if (srtp_stream_list_alloc(&list)) {
+ return srtp_err_status_fail;
+ }
+
+ /* add 4 streams*/
+ if (srtp_stream_list_insert(list, stream_list_test_create_stream(1))) {
+ return srtp_err_status_fail;
+ }
+ if (srtp_stream_list_insert(list, stream_list_test_create_stream(2))) {
+ return srtp_err_status_fail;
+ }
+ if (srtp_stream_list_insert(list, stream_list_test_create_stream(3))) {
+ return srtp_err_status_fail;
+ }
+ if (srtp_stream_list_insert(list, stream_list_test_create_stream(4))) {
+ return srtp_err_status_fail;
+ }
+
+ /* find */
+ if (srtp_stream_list_get(list, 3) == NULL) {
+ return srtp_err_status_fail;
+ }
+ if (srtp_stream_list_get(list, 1) == NULL) {
+ return srtp_err_status_fail;
+ }
+ if (srtp_stream_list_get(list, 2) == NULL) {
+ return srtp_err_status_fail;
+ }
+ if (srtp_stream_list_get(list, 4) == NULL) {
+ return srtp_err_status_fail;
+ }
+
+ /* find not in list */
+ if (srtp_stream_list_get(list, 5)) {
+ return srtp_err_status_fail;
+ }
+
+ /* for each */
+ int count = 0;
+ srtp_stream_list_for_each(list, stream_list_test_count_cb, &count);
+ if (count != 4) {
+ return srtp_err_status_fail;
+ }
+
+ /* remove */
+ srtp_stream_t stream = srtp_stream_list_get(list, 3);
+ if (stream == NULL) {
+ return srtp_err_status_fail;
+ }
+ srtp_stream_list_remove(list, stream);
+ stream_list_test_free_stream(stream);
+
+ /* find after remove */
+ if (srtp_stream_list_get(list, 3)) {
+ return srtp_err_status_fail;
+ }
+
+ /* recount */
+ count = 0;
+ srtp_stream_list_for_each(list, stream_list_test_count_cb, &count);
+ if (count != 3) {
+ return srtp_err_status_fail;
+ }
+
+ /* remove one in for each */
+ struct remove_one_data data = { 2, list };
+ srtp_stream_list_for_each(list, stream_list_test_remove_one_cb, &data);
+
+ /* find after remove */
+ if (srtp_stream_list_get(list, 2)) {
+ return srtp_err_status_fail;
+ }
+
+ /* recount */
+ count = 0;
+ srtp_stream_list_for_each(list, stream_list_test_count_cb, &count);
+ if (count != 2) {
+ return srtp_err_status_fail;
+ }
+
+ /* destroy non empty list */
+ if (srtp_stream_list_dealloc(list) == srtp_err_status_ok) {
+ return srtp_err_status_fail;
+ }
+
+ /* remove all in for each */
+ srtp_stream_list_for_each(list, stream_list_test_remove_all_cb, &list);
+
+ /* recount */
+ count = 0;
+ srtp_stream_list_for_each(list, stream_list_test_count_cb, &count);
+ if (count != 0) {
+ return srtp_err_status_fail;
+ }
+
+ /* destroy empty list */
+ if (srtp_stream_list_dealloc(list)) {
+ return srtp_err_status_fail;
+ }
+
+ return srtp_err_status_ok;
+}
+
+#ifdef SRTP_USE_TEST_STREAM_LIST
+
+/*
+ * A srtp_stream_list_ctx_t implementation using a single linked list
+ * that does not use the internal next / prev fields.
+ */
+
+struct test_list_node {
+ srtp_stream_t stream;
+ struct test_list_node *next;
+};
+struct srtp_stream_list_ctx_t_ {
+ struct test_list_node *head;
+};
+
+srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr)
+{
+ struct srtp_stream_list_ctx_t_ *l =
+ malloc(sizeof(struct srtp_stream_list_ctx_t_));
+ l->head = NULL;
+ *list_ptr = l;
+ return srtp_err_status_ok;
+}
+
+srtp_err_status_t srtp_stream_list_dealloc(srtp_stream_list_t list)
+{
+ struct test_list_node *node = list->head;
+ if (node) {
+ return srtp_err_status_fail;
+ }
+ free(list);
+
+ return srtp_err_status_ok;
+}
+
+srtp_err_status_t srtp_stream_list_insert(srtp_stream_list_t list,
+ srtp_stream_t stream)
+{
+ struct test_list_node *node = malloc(sizeof(struct test_list_node));
+ node->stream = stream;
+ node->next = list->head;
+ list->head = node;
+
+ return srtp_err_status_ok;
+}
+
+srtp_stream_t srtp_stream_list_get(srtp_stream_list_t list, uint32_t ssrc)
+{
+ struct test_list_node *node = list->head;
+ while (node != NULL) {
+ if (node->stream->ssrc == ssrc)
+ return node->stream;
+ node = node->next;
+ }
+ return NULL;
+}
+
+void srtp_stream_list_remove(srtp_stream_list_t list, srtp_stream_t stream)
+{
+ struct test_list_node **node = &(list->head);
+ while ((*node) != NULL) {
+ if ((*node)->stream->ssrc == stream->ssrc) {
+ struct test_list_node *tmp = (*node);
+ (*node) = tmp->next;
+ free(tmp);
+ return;
+ }
+ node = &(*node)->next;
+ }
+}
+
+void srtp_stream_list_for_each(srtp_stream_list_t list,
+ int (*callback)(srtp_stream_t, void *),
+ void *data)
+{
+ struct test_list_node *node = list->head;
+ while (node != NULL) {
+ struct test_list_node *tmp = node;
+ node = node->next;
+ if (callback(tmp->stream, data))
+ break;
+ }
+}
+
+#endif
diff --git a/test/test_srtp.c b/test/test_srtp.c
index 0cea1f3..e739239 100644
--- a/test/test_srtp.c
+++ b/test/test_srtp.c
@@ -78,13 +78,13 @@
srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param },
{ "srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number()",
srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number },
- { NULL } /* End of tests */ };
+ { 0 } /* End of tests */ };
/*
* Implementation.
*/
-void srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output()
+void srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output(void)
{
// Preconditions
srtp_session_keys_t session_keys;
@@ -94,8 +94,7 @@
// Postconditions
srtp_err_status_t status;
- const v128_t zero_vector;
- memset((v128_t *)&zero_vector, 0, sizeof(v128_t));
+ const v128_t zero_vector = { 0 };
// Given
memset(&session_keys, 0, sizeof(srtp_session_keys_t));
@@ -112,7 +111,7 @@
TEST_CHECK(memcmp(&zero_vector, &init_vector, sizeof(v128_t)) == 0);
}
-void srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param()
+void srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param(void)
{
// Preconditions
srtp_session_keys_t session_keys;
@@ -144,7 +143,7 @@
* Ensure that for each valid sequence number where the most significant bit is
* high that we get an expected and unique IV.
*/
-void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number()
+void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number(void)
{
#define SAMPLE_COUNT (3)
// Preconditions
diff --git a/crypto/replay/ut_sim.c b/test/ut_sim.c
similarity index 98%
rename from crypto/replay/ut_sim.c
rename to test/ut_sim.c
index 2825b68..98d9ab2 100644
--- a/crypto/replay/ut_sim.c
+++ b/test/ut_sim.c
@@ -54,6 +54,8 @@
int ut_compar(const void *a, const void *b)
{
uint8_t r;
+ (void)a;
+ (void)b;
srtp_cipher_rand_for_tests(&r, sizeof(r));
return r > (UINT8_MAX / 2) ? -1 : 1;
}
diff --git a/include/ut_sim.h b/test/ut_sim.h
similarity index 100%
rename from include/ut_sim.h
rename to test/ut_sim.h
diff --git a/test/util.c b/test/util.c
index c0f7614..ac2d9a2 100644
--- a/test/util.c
+++ b/test/util.c
@@ -101,8 +101,6 @@
default:
return -1; /* this flags an error */
}
- /* NOTREACHED */
- return -1; /* this keeps compilers from complaining */
}
uint8_t nibble_to_hex_char(uint8_t nibble)
@@ -129,7 +127,7 @@
if (tmp == -1) {
return hex_len;
}
- x = (tmp << 4);
+ x = (uint8_t)(tmp << 4);
hex_len++;
tmp = hex_char_to_nibble(hex[1]);
if (tmp == -1) {
@@ -176,7 +174,7 @@
for (i = 0; i < 4; i++) {
char *p = strchr(b64chars, in[i]);
if (p != NULL) {
- sextets[i] = p - b64chars;
+ sextets[i] = (unsigned char)(p - b64chars);
} else {
j++;
}