Support OpenSSL3 with "no-deprecated" build option (#3603)

This commit is contained in:
Riza Sulistyo 2023-07-05 10:39:01 +07:00 committed by GitHub
parent 8e69c977c7
commit 914ce755a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 9351 additions and 7410 deletions

View File

@ -5951,6 +5951,13 @@ then :
fi
ac_fn_c_check_header_compile "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default"
if test "x$ac_cv_header_inttypes_h" = xyes
then :
printf "%s\n" "#define PJ_HAS_INTTYPES_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_ioctl_h" = xyes
then :
@ -9214,6 +9221,47 @@ printf "%s\n" "$ac_cv_lib_crypto_ERR_load_BIO_strings" >&6; }
if test "x$ac_cv_lib_crypto_ERR_load_BIO_strings" = xyes
then :
libcrypto_present=1 && LIBS="-lcrypto $LIBS"
else $as_nop
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ERR_get_error in -lcrypto" >&5
printf %s "checking for ERR_get_error in -lcrypto... " >&6; }
if test ${ac_cv_lib_crypto_ERR_get_error+y}
then :
printf %s "(cached) " >&6
else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcrypto $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
char ERR_get_error ();
int
main (void)
{
return ERR_get_error ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_crypto_ERR_get_error=yes
else $as_nop
ac_cv_lib_crypto_ERR_get_error=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_ERR_get_error" >&5
printf "%s\n" "$ac_cv_lib_crypto_ERR_get_error" >&6; }
if test "x$ac_cv_lib_crypto_ERR_get_error" = xyes
then :
libcrypto_present=1 && LIBS="-lcrypto $LIBS"
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SSL_CTX_new in -lssl" >&5

View File

@ -260,6 +260,7 @@ AC_CHECK_HEADER(stdio.h,[AC_DEFINE(PJ_HAS_STDIO_H,1)])
AC_CHECK_HEADER(stdint.h,[AC_DEFINE(PJ_HAS_STDINT_H,1)])
AC_CHECK_HEADER(stdlib.h,[AC_DEFINE(PJ_HAS_STDLIB_H,1)])
AC_CHECK_HEADER(string.h,[AC_DEFINE(PJ_HAS_STRING_H,1)])
AC_CHECK_HEADER(inttypes.h,[AC_DEFINE(PJ_HAS_INTTYPES_H,1)])
AC_CHECK_HEADER(sys/ioctl.h,[AC_DEFINE(PJ_HAS_SYS_IOCTL_H,1)])
AC_CHECK_HEADER(sys/select.h,[AC_DEFINE(PJ_HAS_SYS_SELECT_H,1)])
AC_CHECK_HEADER(sys/socket.h,[AC_DEFINE(PJ_HAS_SYS_SOCKET_H,1)])
@ -1958,7 +1959,7 @@ AC_ARG_ENABLE(ssl,
AC_SUBST(libssl_present)
AC_SUBST(libcrypto_present)
AC_CHECK_HEADER(openssl/ssl.h,[openssl_h_present=1])
AC_CHECK_LIB(crypto,ERR_load_BIO_strings,[libcrypto_present=1 && LIBS="-lcrypto $LIBS"])
AC_CHECK_LIB(crypto,ERR_load_BIO_strings,[libcrypto_present=1 && LIBS="-lcrypto $LIBS"], [AC_CHECK_LIB(crypto,ERR_get_error,[libcrypto_present=1 && LIBS="-lcrypto $LIBS"])])
AC_CHECK_LIB(ssl,SSL_CTX_new,[libssl_present=1 && LIBS="-lssl $LIBS"])
if test "x$openssl_h_present" = "x1" -a "x$libssl_present" = "x1" -a "x$libcrypto_present" = "x1"; then
AC_MSG_RESULT([OpenSSL library found, SSL support enabled])

View File

@ -60,6 +60,7 @@
#undef PJ_HAS_NETINET_TCP_H
#undef PJ_HAS_NET_IF_H
#undef PJ_HAS_IFADDRS_H
#undef PJ_HAS_INTTYPES_H
#undef PJ_HAS_SEMAPHORE_H
#undef PJ_HAS_SETJMP_H
#undef PJ_HAS_STDARG_H

View File

@ -36,6 +36,7 @@
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 0 /* Must be zero, otherwise errno_test() fails. */
#define PJ_HAS_INTTYPES_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 0

View File

@ -38,6 +38,7 @@
#define PJ_HAS_ASSERT_H 1
#define PJ_HAS_CTYPE_H 1
#define PJ_HAS_ERRNO_H 0 /* Must be zero, otherwise errno_test() fails. */
#define PJ_HAS_INTTYPES_H 1
#define PJ_HAS_LINUX_SOCKET_H 0
#define PJ_HAS_MALLOC_H 1
#define PJ_HAS_NETDB_H 0

View File

@ -163,9 +163,21 @@ static void update_certs_info(pj_ssl_sock_t* ssock,
# define OPENSSL_NO_SSL2 /* seems to be removed in 1.1.0 */
# define M_ASN1_STRING_data(x) ASN1_STRING_get0_data(x)
# define M_ASN1_STRING_length(x) ASN1_STRING_length(x)
# if defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT >= 0x10100000L
# if defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT >= 0x10100000L || \
defined(OPENSSL_NO_DEPRECATED)
# define X509_get_notBefore(x) X509_get0_notBefore(x)
# define X509_get_notAfter(x) X509_get0_notAfter(x)
# if OPENSSL_VERSION_NUMBER >= 0x30000000L
# if defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT >= 0x30000000L || \
defined(OPENSSL_NO_DEPRECATED)
# define SSL_get_peer_certificate(x) SSL_get1_peer_certificate(x)
# endif
# endif
# endif
#elif !USING_LIBRESSL
# define SSL_CIPHER_get_id(c) (c)->id
@ -173,7 +185,6 @@ static void update_certs_info(pj_ssl_sock_t* ssock,
# define X509_STORE_CTX_get0_cert(ctx) ((ctx)->cert)
#endif
#ifdef _MSC_VER
# if OPENSSL_VERSION_NUMBER >= 0x10100000L
# pragma comment(lib, "libcrypto")

View File

@ -98,8 +98,14 @@
#endif
#else /* Bundled SRTP */
# include <srtp_config.h>
# include <srtp.h>
# include <crypto_kernel.h>
#define srtp_aes_gcm_256_openssl srtp_aes_gcm_256
#define srtp_aes_gcm_128_openssl srtp_aes_gcm_128
#endif
#define THIS_FILE "transport_srtp.c"

View File

@ -15,4 +15,4 @@ speex: SVN -r12832
gsm: gsm-1.0.12
ilbc: from RFC
resample: lib-resample, I think version 1.7
srtp libsrtp-1.5.4
srtp libsrtp-2.5.0

View File

@ -61,7 +61,7 @@ else
CIPHERS_SRC = crypto/cipher/aes_icm_ossl.o crypto/cipher/aes_gcm_ossl.o
HASHES_SRC = crypto/hash/hmac_ossl.o
RNG_SRC = # crypto/rng/rand_source_ossl.o
SRTP_OTHER_CFLAGS = -DOPENSSL
SRTP_OTHER_CFLAGS = -DOPENSSL -DGCM
endif

View File

@ -28,15 +28,14 @@ export _LDFLAGS := $(CC_LDFLAGS) $(OS_LDFLAGS) $(M_LDFLAGS) $(HOST_LDFLAGS) \
$(APP_LDFLAGS) $(LDFLAGS)
# libcrypt.a (the crypto engine)
ciphers = crypto/cipher/cipher.o crypto/cipher/null_cipher.o \
ciphers = crypto/cipher/cipher.o crypto/cipher/null_cipher.o crypto/cipher/cipher_test_cases.o \
$(CIPHERS_SRC)
hashes = crypto/hash/null_auth.o crypto/hash/auth.o $(HASHES_SRC)
hashes = crypto/hash/null_auth.o crypto/hash/auth.o crypto/hash/auth_test_cases.o $(HASHES_SRC)
replay = crypto/replay/rdb.o crypto/replay/rdbx.o \
crypto/replay/ut_sim.o
replay = crypto/replay/rdb.o crypto/replay/rdbx.o
math = crypto/math/datatypes.o crypto/math/stat.o
math = crypto/math/datatypes.o
ust = crypto/ust/ust.o
@ -47,7 +46,7 @@ err = pjlib/srtp_err.o
kernel = crypto/kernel/crypto_kernel.o crypto/kernel/alloc.o \
crypto/kernel/key.o $(rng) $(err) # $(ust)
srtpobj = srtp/srtp.o srtp/ekt.o
srtpobj = srtp/srtp.o
cryptobj = $(ciphers) $(hashes) $(math) $(stat) $(kernel) $(replay)

View File

@ -706,8 +706,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Dynamic|ARM'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\srtp\crypto\cipher\cipher.c" />
<ClCompile Include="..\..\srtp\crypto\cipher\cipher_test_cases.c" />
<ClCompile Include="..\..\srtp\crypto\cipher\null_cipher.c" />
<ClCompile Include="..\..\srtp\crypto\hash\auth.c" />
<ClCompile Include="..\..\srtp\crypto\hash\auth_test_cases.c" />
<ClCompile Include="..\..\srtp\crypto\hash\hmac.c" />
<ClCompile Include="..\..\srtp\crypto\hash\hmac_ossl.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release-Static|Win32'">true</ExcludedFromBuild>
@ -744,12 +746,10 @@
</ClCompile>
<ClCompile Include="..\..\srtp\crypto\kernel\key.c" />
<ClCompile Include="..\..\srtp\crypto\math\datatypes.c" />
<ClCompile Include="..\..\srtp\crypto\math\stat.c" />
<ClCompile Include="..\..\srtp\crypto\replay\rdb.c" />
<ClCompile Include="..\..\srtp\crypto\replay\rdbx.c" />
<ClCompile Include="..\..\srtp\pjlib\srtp_err.c" />
<ClCompile Include="..\..\srtp\srtp\srtp.c" />
<ClCompile Include="..\..\srtp\srtp\ekt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\srtp\crypto\include\aes.h" />

View File

@ -74,18 +74,12 @@
<ClCompile Include="..\..\srtp\crypto\math\datatypes.c">
<Filter>crypto\math</Filter>
</ClCompile>
<ClCompile Include="..\..\srtp\crypto\math\stat.c">
<Filter>crypto\math</Filter>
</ClCompile>
<ClCompile Include="..\..\srtp\crypto\replay\rdb.c">
<Filter>crypto\replay</Filter>
</ClCompile>
<ClCompile Include="..\..\srtp\crypto\replay\rdbx.c">
<Filter>crypto\replay</Filter>
</ClCompile>
<ClCompile Include="..\..\srtp\srtp\ekt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\srtp\crypto\cipher\aes_icm_ossl.c">
<Filter>crypto\cipher</Filter>
</ClCompile>
@ -95,6 +89,12 @@
<ClCompile Include="..\..\srtp\crypto\hash\hmac_ossl.c">
<Filter>crypto\hash</Filter>
</ClCompile>
<ClCompile Include="..\..\srtp\crypto\cipher\cipher_test_cases.c">
<Filter>crypto\cipher</Filter>
</ClCompile>
<ClCompile Include="..\..\srtp\crypto\hash\auth_test_cases.c">
<Filter>crypto\hash</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\srtp\include\srtp.h">

View File

@ -43,6 +43,11 @@
# define HAVE_ARPA_INET_H 1
#endif
/* Define to 1 if you have the <inttypes.h> header file. */
#if defined(PJ_HAS_INTTYPES_H) && PJ_HAS_INTTYPES_H!=0
# define HAVE_INTTYPES_H 1
#endif
/* Define to 1 if you have the <byteswap.h> header file. */
/* #undef HAVE_BYTESWAP_H */

View File

@ -1,5 +1,191 @@
Changelog
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
Major changes
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.
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.
PR #463 - problem on srtp_aes_icm_openssl_encrypt.
PR #471 - Allow the pcap file to be read from a physical file.
PR #457 - Fix docs crypto_policy_* -> srtp_crypto_policy_* .
PR #452 - crypto/cipher: Reset the EVP_CIPHER_CTX structure before each test.
PR #444 - Extend rtp_ecoder to support RTCP and multiplexed SSRC's.
PR #443 - rtp_decoder avoid crash when no packets found.
PR #429 - Rand for test only.
PR #421 - Fix GCM IV logging.
PR #415 - Fixes unaligned trailer access.
PR #414 - Detect and handle broken "OPENSSL_cleanse".
2.2.0
Major changes
All code has been reformatted to be consistent. A .clang-format file and format.sh script has been added that can be use to verify and enforce consistent formatting. An automated check on code formatting is now part of travis build.
Other changes
PR #409 - Compatibilty with LibreSSL
PR #406 - Fix unprotect when pktlen < (2*mki_size + tag_len)
PR #405 - Prevent potential double free
PR #404 - Add back extern to global variables
PR #403 - Set gcm IV directly with EVP_CipherInit_ex
PR #401 - Fix memory access issue in srtp_get_session_keys()
PR #398 - Fix memory access fixes when invalid profiles where used
PR #391 - Return NULL when allocating memory of size zero
PR #390 - Bitvector of length zero is not valid
PR #385 - Treat warnings as errors on travis builds
PR #388 - Moved externs from crypto_kernel into its own header
PR #379 - Fixed several compiler warnings from Firefox builds
PR #377 - Removed variable init code in rdbx which never gets used
PR #381 - Added error in case the platform is not detected
PR #376 - Add coverity scan to travis builds
PR #374 - Add a big endian build on travis
PR #373 - Fixed buffer size issue in test/srtp_driver.c
PR #372 - Make rtp_decoder compile on MinGW
PR #367 - Rename configure.in to configure.ac
PR #365 - Replace calls to free() with srtp_crypto_free()
PR #364 - Add valgrind to travis and fix leaks in tests
PR #363 - Change smtp_crypto_alloc to initialize memory to zero
PR #354 - Fix potential leak if cloning of stream fails
PR #340 - Fix potential leak in srtp_add_stream()
PR #323 - Fix running test in out of source builds
Issue #316 - Remove VERSION file
2.1.0
Compatibility changes
@ -164,4 +350,4 @@ Other changes
PR #302 - Fix warning regarding unused variable
PR #303 - Makefile.in: Add gnu as match for shared lib suffix
PR #303 - Makefile.in: Add gnu as match for shared lib suffix

View File

@ -1,3 +1,9 @@
[![CMake Build](https://github.com/cisco/libsrtp/actions/workflows/cmake.yml/badge.svg)](https://github.com/cisco/libsrtp/actions/workflows/cmake.yml)
[![Autotools Build](https://github.com/cisco/libsrtp/actions/workflows/autotools.yml/badge.svg)](https://github.com/cisco/libsrtp/actions/workflows/autotools.yml)
[![Build Status](https://travis-ci.org/cisco/libsrtp.svg?branch=master)](https://travis-ci.org/cisco/libsrtp)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/14274/badge.svg)](https://scan.coverity.com/projects/cisco-libsrtp)
[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/systemd.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libsrtp)
<a name="introduction-to-libsrtp"></a>
# Introduction to libSRTP
@ -9,10 +15,10 @@ and the library is in libsrtp2.a (after compilation).
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.
@ -28,7 +34,7 @@ because it does its work behind the scenes.
--------------------------------------------------------------------------------
<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
@ -43,7 +49,7 @@ because it does its work behind the scenes.
## 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)
@ -51,6 +57,8 @@ because it does its work behind the scenes.
- [Supported Features](#supported-features)
- [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)
@ -133,16 +141,16 @@ can also be linked together to form an entire session policy. A linked
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.
@ -191,7 +199,7 @@ in which a key is used for both inbound and outbound data.
## 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
@ -208,15 +216,25 @@ supported. This includes
The user should be aware that it is possible to misuse this libary,
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
@ -275,11 +293,13 @@ Option | Description
-------------------------------|--------------------
\-\-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.
@ -291,6 +311,76 @@ OpenBSD (sparc-unknown-openbsd2.7).
--------------------------------------------------------------------------------
<a name="changing-build-configuration"></a>
## Changing Build Configuration
To build the `./configure` script mentioned above, libSRTP relies on the
[automake](https://www.gnu.org/software/automake/) toolchain. Since
`./configure` is built from `configure.in` by automake, if you make changes in
how `./configure` works (e.g., to add a new library dependency), you will need
to rebuild `./configure` and commit the updated version. In addition to
automake itself, you will need to have the `pkgconfig` tools installed as well.
For example, on macOS:
```
brew install automake pkgconfig
# Edit configure.in
autoremake -ivf
```
--------------------------------------------------------------------------------
<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.org).
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
@ -397,9 +487,12 @@ uint8_t key[30] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
// initialize libSRTP
srtp_init();
// default policy values
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;
@ -448,13 +541,13 @@ Copyright 2001-2005 by David A. McGrew, Cisco Systems, Inc.
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)

View File

@ -1 +1 @@
2.1.0-pre
2.5.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,410 @@
/*
* aes_gcm_mbedtls.c
*
* AES Galois Counter Mode
*
* YongCheng Yang
*
*/
/*
*
* Copyright (c) 2013-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 <mbedtls/gcm.h>
#include "aes_gcm.h"
#include "alloc.h"
#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 */
"aes gcm mbedtls" /* printable module name */
};
/**
* SRTP IV Formation for AES-GCM
* https://tools.ietf.org/html/rfc7714#section-8.1
* 0 0 0 0 0 0 0 0 0 0 1 1
* 0 1 2 3 4 5 6 7 8 9 0 1
* +--+--+--+--+--+--+--+--+--+--+--+--+
* |00|00| SSRC | ROC | SEQ |---+
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* |
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* | Encryption Salt |->(+)
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* |
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* | Initialization Vector |<--+
* +--+--+--+--+--+--+--+--+--+--+--+--+
*
* SRTCP IV Formation for AES-GCM
* https://tools.ietf.org/html/rfc7714#section-9.1
*
*/
/*
* For now we only support 8 and 16 octet tags. The spec allows for
* optional 12 byte tag, which may be supported in the future.
*/
#define GCM_IV_LEN 12
#define GCM_AUTH_TAG_LEN 16
#define GCM_AUTH_TAG_LEN_8 8
#define FUNC_ENTRY() debug_print(srtp_mod_aes_gcm, "%s entry", __func__);
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 28 or 44 for
* AES-128-GCM or AES-256-GCM respectively. Note that the
* key length includes the 14 byte salt value that is used when
* initializing the KDF.
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_alloc(srtp_cipher_t **c,
int key_len,
int tlen)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *gcm;
debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %d",
key_len);
debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %d", tlen);
/*
* Verify the key_len is valid for one of: AES-128/256
*/
if (key_len != SRTP_AES_GCM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_GCM_256_KEY_LEN_WSALT) {
return (srtp_err_status_bad_param);
}
if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
return (srtp_err_status_bad_param);
}
/* allocate memory a cipher of type aes_gcm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return (srtp_err_status_alloc_fail);
}
gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
if (gcm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return (srtp_err_status_alloc_fail);
}
gcm->ctx =
(mbedtls_gcm_context *)srtp_crypto_alloc(sizeof(mbedtls_gcm_context));
if (gcm->ctx == NULL) {
srtp_crypto_free(gcm);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
mbedtls_gcm_init(gcm->ctx);
/* set pointers */
(*c)->state = gcm;
/* setup cipher attributes */
switch (key_len) {
case SRTP_AES_GCM_128_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_128;
(*c)->algorithm = SRTP_AES_GCM_128;
gcm->key_size = SRTP_AES_128_KEY_LEN;
gcm->tag_len = tlen;
break;
case SRTP_AES_GCM_256_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_256;
(*c)->algorithm = SRTP_AES_GCM_256;
gcm->key_size = SRTP_AES_256_KEY_LEN;
gcm->tag_len = tlen;
break;
}
/* set key size */
(*c)->key_len = key_len;
return (srtp_err_status_ok);
}
/*
* This function deallocates a GCM session
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_dealloc(srtp_cipher_t *c)
{
srtp_aes_gcm_ctx_t *ctx;
FUNC_ENTRY();
ctx = (srtp_aes_gcm_ctx_t *)c->state;
if (ctx) {
mbedtls_gcm_free(ctx->ctx);
srtp_crypto_free(ctx->ctx);
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_gcm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return (srtp_err_status_ok);
}
static srtp_err_status_t srtp_aes_gcm_mbedtls_context_init(void *cv,
const uint8_t *key)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
uint32_t key_len_in_bits;
int errCode = 0;
c->dir = srtp_direction_any;
c->aad_size = 0;
debug_print(srtp_mod_aes_gcm, "key: %s",
srtp_octet_string_hex_string(key, c->key_size));
key_len_in_bits = (c->key_size << 3);
switch (c->key_size) {
case SRTP_AES_256_KEY_LEN:
case SRTP_AES_128_KEY_LEN:
break;
default:
return (srtp_err_status_bad_param);
break;
}
errCode = mbedtls_gcm_setkey(c->ctx, MBEDTLS_CIPHER_ID_AES,
(const unsigned char *)key, key_len_in_bits);
if (errCode != 0) {
debug_print(srtp_mod_aes_gcm, "mbedtls error code: %d", errCode);
return srtp_err_status_init_fail;
}
return (srtp_err_status_ok);
}
static srtp_err_status_t srtp_aes_gcm_mbedtls_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t direction)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
if (direction != srtp_direction_encrypt &&
direction != srtp_direction_decrypt) {
return (srtp_err_status_bad_param);
}
c->dir = direction;
debug_print(srtp_mod_aes_gcm, "setting iv: %s",
srtp_octet_string_hex_string(iv, GCM_IV_LEN));
c->iv_len = GCM_IV_LEN;
memcpy(c->iv, iv, c->iv_len);
return (srtp_err_status_ok);
}
/*
* This function processes the AAD
*
* Parameters:
* c Crypto context
* aad Additional data to process for AEAD cipher suites
* aad_len length of aad buffer
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_set_aad(void *cv,
const uint8_t *aad,
uint32_t aad_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
srtp_octet_string_hex_string(aad, aad_len));
if (aad_len + c->aad_size > MAX_AD_SIZE) {
return srtp_err_status_bad_param;
}
memcpy(c->aad + c->aad_size, aad, aad_len);
c->aad_size += aad_len;
return (srtp_err_status_ok);
}
/*
* This function encrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int errCode = 0;
if (c->dir != srtp_direction_encrypt && c->dir != srtp_direction_decrypt) {
return (srtp_err_status_bad_param);
}
errCode = mbedtls_gcm_crypt_and_tag(c->ctx, MBEDTLS_GCM_ENCRYPT, *enc_len,
c->iv, c->iv_len, c->aad, c->aad_size,
buf, buf, c->tag_len, c->tag);
c->aad_size = 0;
if (errCode != 0) {
debug_print(srtp_mod_aes_gcm, "mbedtls error code: %d", errCode);
return srtp_err_status_bad_param;
}
return (srtp_err_status_ok);
}
/*
* This function calculates and returns the GCM tag for a given context.
* This should be called after encrypting the data. The *len value
* is increased by the tag size. The caller must ensure that *buf has
* enough room to accept the appended tag.
*
* Parameters:
* c Crypto context
* buf data to encrypt
* len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_get_tag(void *cv,
uint8_t *buf,
uint32_t *len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
debug_print(srtp_mod_aes_gcm, "appended tag size: %d", c->tag_len);
*len = c->tag_len;
memcpy(buf, c->tag, c->tag_len);
return (srtp_err_status_ok);
}
/*
* This function decrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_decrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int errCode = 0;
if (c->dir != srtp_direction_encrypt && c->dir != srtp_direction_decrypt) {
return (srtp_err_status_bad_param);
}
debug_print(srtp_mod_aes_gcm, "AAD: %s",
srtp_octet_string_hex_string(c->aad, c->aad_size));
errCode = mbedtls_gcm_auth_decrypt(
c->ctx, (*enc_len - c->tag_len), c->iv, c->iv_len, c->aad, c->aad_size,
buf + (*enc_len - c->tag_len), c->tag_len, buf, buf);
c->aad_size = 0;
if (errCode != 0) {
return (srtp_err_status_auth_fail);
}
/*
* Reduce the buffer size by the tag length since the tag
* is not part of the original payload
*/
*enc_len -= c->tag_len;
return (srtp_err_status_ok);
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_gcm_128_mbedtls_description[] =
"AES-128 GCM using mbedtls";
static const char srtp_aes_gcm_256_mbedtls_description[] =
"AES-256 GCM using mbedtls";
/*
* This is the vector function table for this crypto engine.
*/
const srtp_cipher_type_t srtp_aes_gcm_128 = {
srtp_aes_gcm_mbedtls_alloc,
srtp_aes_gcm_mbedtls_dealloc,
srtp_aes_gcm_mbedtls_context_init,
srtp_aes_gcm_mbedtls_set_aad,
srtp_aes_gcm_mbedtls_encrypt,
srtp_aes_gcm_mbedtls_decrypt,
srtp_aes_gcm_mbedtls_set_iv,
srtp_aes_gcm_mbedtls_get_tag,
srtp_aes_gcm_128_mbedtls_description,
&srtp_aes_gcm_128_test_case_0,
SRTP_AES_GCM_128
};
/*
* This is the vector function table for this crypto engine.
*/
const srtp_cipher_type_t srtp_aes_gcm_256 = {
srtp_aes_gcm_mbedtls_alloc,
srtp_aes_gcm_mbedtls_dealloc,
srtp_aes_gcm_mbedtls_context_init,
srtp_aes_gcm_mbedtls_set_aad,
srtp_aes_gcm_mbedtls_encrypt,
srtp_aes_gcm_mbedtls_decrypt,
srtp_aes_gcm_mbedtls_set_iv,
srtp_aes_gcm_mbedtls_get_tag,
srtp_aes_gcm_256_mbedtls_description,
&srtp_aes_gcm_256_test_case_0,
SRTP_AES_GCM_256
};

View File

@ -0,0 +1,442 @@
/*
* aes_gcm_nss.c
*
* AES Galois Counter Mode
*
* Richard L. Barnes
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013-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 "aes_gcm.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "crypto_types.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
#include <secerr.h>
#include <nspr.h>
srtp_debug_module_t srtp_mod_aes_gcm = {
0, /* debugging is off by default */
"aes gcm nss" /* printable module name */
};
/*
* For now we only support 8 and 16 octet tags. The spec allows for
* optional 12 byte tag, which may be supported in the future.
*/
#define GCM_IV_LEN 12
#define GCM_AUTH_TAG_LEN 16
#define GCM_AUTH_TAG_LEN_8 8
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 28 or 44 for
* AES-128-GCM or AES-256-GCM respectively. Note that the
* key length includes the 14 byte salt value that is used when
* initializing the KDF.
*/
static srtp_err_status_t srtp_aes_gcm_nss_alloc(srtp_cipher_t **c,
int key_len,
int tlen)
{
srtp_aes_gcm_ctx_t *gcm;
NSSInitContext *nss;
debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %d",
key_len);
debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %d", tlen);
/*
* Verify the key_len is valid for one of: AES-128/256
*/
if (key_len != SRTP_AES_GCM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_GCM_256_KEY_LEN_WSALT) {
return (srtp_err_status_bad_param);
}
if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
return (srtp_err_status_bad_param);
}
/* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
nss = NSS_InitContext("", "", "", "", NULL,
NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
NSS_INIT_OPTIMIZESPACE);
if (!nss) {
return (srtp_err_status_cipher_fail);
}
/* allocate memory a cipher of type aes_gcm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
NSS_ShutdownContext(nss);
return (srtp_err_status_alloc_fail);
}
gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
if (gcm == NULL) {
NSS_ShutdownContext(nss);
srtp_crypto_free(*c);
*c = NULL;
return (srtp_err_status_alloc_fail);
}
gcm->nss = nss;
/* set pointers */
(*c)->state = gcm;
/* setup cipher attributes */
switch (key_len) {
case SRTP_AES_GCM_128_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_128;
(*c)->algorithm = SRTP_AES_GCM_128;
gcm->key_size = SRTP_AES_128_KEY_LEN;
gcm->tag_size = tlen;
gcm->params.ulTagBits = 8 * tlen;
break;
case SRTP_AES_GCM_256_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_256;
(*c)->algorithm = SRTP_AES_GCM_256;
gcm->key_size = SRTP_AES_256_KEY_LEN;
gcm->tag_size = tlen;
gcm->params.ulTagBits = 8 * tlen;
break;
default:
/* this should never hit, but to be sure... */
return (srtp_err_status_bad_param);
}
/* set key size and tag size*/
(*c)->key_len = key_len;
return (srtp_err_status_ok);
}
/*
* This function deallocates a GCM session
*/
static srtp_err_status_t srtp_aes_gcm_nss_dealloc(srtp_cipher_t *c)
{
srtp_aes_gcm_ctx_t *ctx;
ctx = (srtp_aes_gcm_ctx_t *)c->state;
if (ctx) {
/* release NSS resources */
if (ctx->key) {
PK11_FreeSymKey(ctx->key);
}
if (ctx->nss) {
NSS_ShutdownContext(ctx->nss);
ctx->nss = NULL;
}
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_gcm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return (srtp_err_status_ok);
}
/*
* aes_gcm_nss_context_init(...) initializes the aes_gcm_context
* using the value in key[].
*
* the key is the secret key
*/
static srtp_err_status_t srtp_aes_gcm_nss_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
c->dir = srtp_direction_any;
debug_print(srtp_mod_aes_gcm, "key: %s",
srtp_octet_string_hex_string(key, c->key_size));
if (c->key) {
PK11_FreeSymKey(c->key);
c->key = NULL;
}
PK11SlotInfo *slot = PK11_GetBestSlot(CKM_AES_GCM, NULL);
if (!slot) {
return (srtp_err_status_cipher_fail);
}
SECItem key_item = { siBuffer, (unsigned char *)key, c->key_size };
c->key = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
CKA_ENCRYPT, &key_item, NULL);
PK11_FreeSlot(slot);
if (!c->key) {
return (srtp_err_status_cipher_fail);
}
return (srtp_err_status_ok);
}
/*
* aes_gcm_nss_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
static srtp_err_status_t srtp_aes_gcm_nss_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t direction)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
if (direction != srtp_direction_encrypt &&
direction != srtp_direction_decrypt) {
return (srtp_err_status_bad_param);
}
c->dir = direction;
debug_print(srtp_mod_aes_gcm, "setting iv: %s",
srtp_octet_string_hex_string(iv, GCM_IV_LEN));
memcpy(c->iv, iv, GCM_IV_LEN);
return (srtp_err_status_ok);
}
/*
* This function processes the AAD
*
* Parameters:
* c Crypto context
* aad Additional data to process for AEAD cipher suites
* aad_len length of aad buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_set_aad(void *cv,
const uint8_t *aad,
uint32_t aad_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
srtp_octet_string_hex_string(aad, aad_len));
if (aad_len + c->aad_size > MAX_AD_SIZE) {
return srtp_err_status_bad_param;
}
memcpy(c->aad + c->aad_size, aad, aad_len);
c->aad_size += aad_len;
return (srtp_err_status_ok);
}
static srtp_err_status_t srtp_aes_gcm_nss_do_crypto(void *cv,
int encrypt,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
c->params.pIv = c->iv;
c->params.ulIvLen = GCM_IV_LEN;
c->params.pAAD = c->aad;
c->params.ulAADLen = c->aad_size;
// Reset AAD
c->aad_size = 0;
int rv;
SECItem param = { siBuffer, (unsigned char *)&c->params,
sizeof(CK_GCM_PARAMS) };
if (encrypt) {
rv = PK11_Encrypt(c->key, CKM_AES_GCM, &param, buf, enc_len,
*enc_len + 16, buf, *enc_len);
} else {
rv = PK11_Decrypt(c->key, CKM_AES_GCM, &param, buf, enc_len, *enc_len,
buf, *enc_len);
}
srtp_err_status_t status = (srtp_err_status_ok);
if (rv != SECSuccess) {
status = (srtp_err_status_cipher_fail);
}
return status;
}
/*
* This function encrypts a buffer using AES GCM mode
*
* XXX(rlb@ipv.sx): We're required to break off and cache the tag
* here, because the get_tag() method is separate and the tests expect
* encrypt() not to change the size of the plaintext. It might be
* good to update the calling API so that this is cleaner.
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
// When we get a non-NULL buffer, we know that the caller is
// prepared to also take the tag. When we get a NULL buffer,
// even though there's no data, we need to give NSS a buffer
// where it can write the tag. We can't just use c->tag because
// memcpy has undefined behavior on overlapping ranges.
unsigned char tagbuf[16];
unsigned char *non_null_buf = buf;
if (!non_null_buf && (*enc_len == 0)) {
non_null_buf = tagbuf;
} else if (!non_null_buf) {
return srtp_err_status_bad_param;
}
srtp_err_status_t status =
srtp_aes_gcm_nss_do_crypto(cv, 1, non_null_buf, enc_len);
if (status != srtp_err_status_ok) {
return status;
}
memcpy(c->tag, non_null_buf + (*enc_len - c->tag_size), c->tag_size);
*enc_len -= c->tag_size;
return srtp_err_status_ok;
}
/*
* This function calculates and returns the GCM tag for a given context.
* This should be called after encrypting the data. The *len value
* is increased by the tag size. The caller must ensure that *buf has
* enough room to accept the appended tag.
*
* Parameters:
* c Crypto context
* buf data to encrypt
* len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_get_tag(void *cv,
uint8_t *buf,
uint32_t *len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
*len = c->tag_size;
memcpy(buf, c->tag, c->tag_size);
return (srtp_err_status_ok);
}
/*
* This function decrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_decrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_err_status_t status = srtp_aes_gcm_nss_do_crypto(cv, 0, buf, enc_len);
if (status != srtp_err_status_ok) {
int err = PR_GetError();
if (err == SEC_ERROR_BAD_DATA) {
status = srtp_err_status_auth_fail;
}
}
return status;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_gcm_128_nss_description[] = "AES-128 GCM using NSS";
static const char srtp_aes_gcm_256_nss_description[] = "AES-256 GCM using NSS";
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_128 = {
srtp_aes_gcm_nss_alloc,
srtp_aes_gcm_nss_dealloc,
srtp_aes_gcm_nss_context_init,
srtp_aes_gcm_nss_set_aad,
srtp_aes_gcm_nss_encrypt,
srtp_aes_gcm_nss_decrypt,
srtp_aes_gcm_nss_set_iv,
srtp_aes_gcm_nss_get_tag,
srtp_aes_gcm_128_nss_description,
&srtp_aes_gcm_128_test_case_0,
SRTP_AES_GCM_128
};
/* clang-format on */
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_256 = {
srtp_aes_gcm_nss_alloc,
srtp_aes_gcm_nss_dealloc,
srtp_aes_gcm_nss_context_init,
srtp_aes_gcm_nss_set_aad,
srtp_aes_gcm_nss_encrypt,
srtp_aes_gcm_nss_decrypt,
srtp_aes_gcm_nss_set_iv,
srtp_aes_gcm_nss_get_tag,
srtp_aes_gcm_256_nss_description,
&srtp_aes_gcm_256_test_case_0,
SRTP_AES_GCM_256
};
/* clang-format on */

View File

@ -45,36 +45,28 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include <openssl/evp.h>
#include "aes_icm_ossl.h"
#include "aes_gcm_ossl.h"
#include "aes_gcm.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#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 */
"aes gcm" /* printable module name */
0, /* debugging is off by default */
"aes gcm" /* printable module name */
};
/*
* The following are the global singleton instances for the
* 128-bit and 256-bit GCM ciphers.
*/
extern const srtp_cipher_type_t srtp_aes_gcm_128_openssl;
extern const srtp_cipher_type_t srtp_aes_gcm_256_openssl;
/*
* For now we only support 8 and 16 octet tags. The spec allows for
* optional 12 byte tag, which may be supported in the future.
*/
#define GCM_AUTH_TAG_LEN 16
#define GCM_AUTH_TAG_LEN_8 8
#define GCM_AUTH_TAG_LEN 16
#define GCM_AUTH_TAG_LEN_8 8
/*
* This function allocates a new instance of this crypto engine.
@ -83,11 +75,14 @@ extern const srtp_cipher_type_t srtp_aes_gcm_256_openssl;
* key length includes the 14 byte salt value that is used when
* initializing the KDF.
*/
static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_len, int tlen)
static srtp_err_status_t srtp_aes_gcm_openssl_alloc(srtp_cipher_t **c,
int key_len,
int tlen)
{
srtp_aes_gcm_ctx_t *gcm;
debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %d", key_len);
debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %d",
key_len);
debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %d", tlen);
/*
@ -98,8 +93,7 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_
return (srtp_err_status_bad_param);
}
if (tlen != GCM_AUTH_TAG_LEN &&
tlen != GCM_AUTH_TAG_LEN_8) {
if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
return (srtp_err_status_bad_param);
}
@ -108,15 +102,13 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_
if (*c == NULL) {
return (srtp_err_status_alloc_fail);
}
memset(*c, 0x0, sizeof(srtp_cipher_t));
gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
if (gcm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
srtp_crypto_free(*c);
*c = NULL;
return (srtp_err_status_alloc_fail);
}
memset(gcm, 0x0, sizeof(srtp_aes_gcm_ctx_t));
gcm->ctx = EVP_CIPHER_CTX_new();
if (gcm->ctx == NULL) {
@ -132,13 +124,13 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_
/* setup cipher attributes */
switch (key_len) {
case SRTP_AES_GCM_128_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_128_openssl;
(*c)->type = &srtp_aes_gcm_128;
(*c)->algorithm = SRTP_AES_GCM_128;
gcm->key_size = SRTP_AES_128_KEY_LEN;
gcm->tag_len = tlen;
break;
case SRTP_AES_GCM_256_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_256_openssl;
(*c)->type = &srtp_aes_gcm_256;
(*c)->algorithm = SRTP_AES_GCM_256;
gcm->key_size = SRTP_AES_256_KEY_LEN;
gcm->tag_len = tlen;
@ -151,15 +143,14 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_
return (srtp_err_status_ok);
}
/*
* This function deallocates a GCM session
*/
static srtp_err_status_t srtp_aes_gcm_openssl_dealloc (srtp_cipher_t *c)
static srtp_err_status_t srtp_aes_gcm_openssl_dealloc(srtp_cipher_t *c)
{
srtp_aes_gcm_ctx_t *ctx;
ctx = (srtp_aes_gcm_ctx_t*)c->state;
ctx = (srtp_aes_gcm_ctx_t *)c->state;
if (ctx) {
EVP_CIPHER_CTX_free(ctx->ctx);
/* zeroize the key material */
@ -179,14 +170,16 @@ static srtp_err_status_t srtp_aes_gcm_openssl_dealloc (srtp_cipher_t *c)
*
* the key is the secret key
*/
static srtp_err_status_t srtp_aes_gcm_openssl_context_init (void* cv, const uint8_t *key)
static srtp_err_status_t srtp_aes_gcm_openssl_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
const EVP_CIPHER *evp;
c->dir = srtp_direction_any;
debug_print(srtp_mod_aes_gcm, "key: %s", srtp_octet_string_hex_string(key, c->key_size));
debug_print(srtp_mod_aes_gcm, "key: %s",
srtp_octet_string_hex_string(key, c->key_size));
switch (c->key_size) {
case SRTP_AES_256_KEY_LEN:
@ -200,6 +193,8 @@ static srtp_err_status_t srtp_aes_gcm_openssl_context_init (void* cv, const uint
break;
}
EVP_CIPHER_CTX_reset(c->ctx);
if (!EVP_CipherInit_ex(c->ctx, evp, NULL, key, NULL, 0)) {
return (srtp_err_status_init_fail);
}
@ -207,35 +202,32 @@ static srtp_err_status_t srtp_aes_gcm_openssl_context_init (void* cv, const uint
return (srtp_err_status_ok);
}
/*
* aes_gcm_openssl_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
static srtp_err_status_t srtp_aes_gcm_openssl_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t direction)
static srtp_err_status_t srtp_aes_gcm_openssl_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t direction)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
if (direction != srtp_direction_encrypt && direction != srtp_direction_decrypt) {
if (direction != srtp_direction_encrypt &&
direction != srtp_direction_decrypt) {
return (srtp_err_status_bad_param);
}
c->dir = direction;
debug_print(srtp_mod_aes_gcm, "setting iv: %s", v128_hex_string((v128_t*)iv));
debug_print(srtp_mod_aes_gcm, "setting iv: %s",
srtp_octet_string_hex_string(iv, 12));
if (!EVP_CipherInit_ex(c->ctx, NULL, NULL, NULL,
NULL, (c->dir == srtp_direction_encrypt ? 1 : 0))) {
return (srtp_err_status_init_fail);
}
/* set IV len and the IV value, the followiong 3 calls are required */
if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) {
return (srtp_err_status_init_fail);
}
if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, (void*)iv)) {
return (srtp_err_status_init_fail);
}
if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_IV_GEN, 0, (void*)iv)) {
if (!EVP_CipherInit_ex(c->ctx, NULL, NULL, NULL, iv,
(c->dir == srtp_direction_encrypt ? 1 : 0))) {
return (srtp_err_status_init_fail);
}
@ -250,28 +242,41 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_iv (void *cv, uint8_t *iv, srt
* aad Additional data to process for AEAD cipher suites
* aad_len length of aad buffer
*/
static srtp_err_status_t srtp_aes_gcm_openssl_set_aad (void *cv, const uint8_t *aad, uint32_t aad_len)
static srtp_err_status_t srtp_aes_gcm_openssl_set_aad(void *cv,
const uint8_t *aad,
uint32_t aad_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int rv;
/*
* Set dummy tag, OpenSSL requires the Tag to be set before
* processing AAD
*/
debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
srtp_octet_string_hex_string(aad, aad_len));
/*
* OpenSSL never write to address pointed by the last parameter of
* EVP_CIPHER_CTX_ctrl while EVP_CTRL_GCM_SET_TAG (in reality,
* OpenSSL copy its content to the context), so we can make
* aad read-only in this function and all its wrappers.
* EVP_CTRL_GCM_SET_TAG can only be used when decrypting
*/
unsigned char dummy_tag[GCM_AUTH_TAG_LEN];
memset(dummy_tag, 0x0, GCM_AUTH_TAG_LEN);
EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len, &dummy_tag);
if (c->dir == srtp_direction_decrypt) {
/*
* Set dummy tag, OpenSSL requires the Tag to be set before
* processing AAD
*/
/*
* OpenSSL never write to address pointed by the last parameter of
* EVP_CIPHER_CTX_ctrl while EVP_CTRL_GCM_SET_TAG (in reality,
* OpenSSL copy its content to the context), so we can make
* aad read-only in this function and all its wrappers.
*/
unsigned char dummy_tag[GCM_AUTH_TAG_LEN];
memset(dummy_tag, 0x0, GCM_AUTH_TAG_LEN);
if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len,
&dummy_tag)) {
return (srtp_err_status_algo_fail);
}
}
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);
@ -286,7 +291,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_aad (void *cv, const uint8_t *
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_openssl_encrypt (void *cv, unsigned char *buf, unsigned int *enc_len)
static srtp_err_status_t srtp_aes_gcm_openssl_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
if (c->dir != srtp_direction_encrypt && c->dir != srtp_direction_decrypt) {
@ -312,7 +319,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_encrypt (void *cv, unsigned char *
* buf data to encrypt
* len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_openssl_get_tag (void *cv, uint8_t *buf, uint32_t *len)
static srtp_err_status_t srtp_aes_gcm_openssl_get_tag(void *cv,
uint8_t *buf,
uint32_t *len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
/*
@ -323,7 +332,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_get_tag (void *cv, uint8_t *buf, u
/*
* Retreive the tag
*/
EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_GET_TAG, c->tag_len, buf);
if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_GET_TAG, c->tag_len, buf)) {
return (srtp_err_status_algo_fail);
}
/*
* Increase encryption length by desired tag size
@ -333,7 +344,6 @@ static srtp_err_status_t srtp_aes_gcm_openssl_get_tag (void *cv, uint8_t *buf, u
return (srtp_err_status_ok);
}
/*
* This function decrypts a buffer using AES GCM mode
*
@ -342,7 +352,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_get_tag (void *cv, uint8_t *buf, u
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_openssl_decrypt (void *cv, unsigned char *buf, unsigned int *enc_len)
static srtp_err_status_t srtp_aes_gcm_openssl_decrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
if (c->dir != srtp_direction_encrypt && c->dir != srtp_direction_decrypt) {
@ -352,8 +364,10 @@ static srtp_err_status_t srtp_aes_gcm_openssl_decrypt (void *cv, unsigned char *
/*
* Set the tag before decrypting
*/
EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len,
buf + (*enc_len - c->tag_len));
if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len,
buf + (*enc_len - c->tag_len))) {
return (srtp_err_status_auth_fail);
}
EVP_Cipher(c->ctx, buf, buf, *enc_len - c->tag_len);
/*
@ -372,169 +386,18 @@ static srtp_err_status_t srtp_aes_gcm_openssl_decrypt (void *cv, unsigned char *
return (srtp_err_status_ok);
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_gcm_128_openssl_description[] = "AES-128 GCM using openssl";
static const char srtp_aes_gcm_256_openssl_description[] = "AES-256 GCM using openssl";
/*
* KAT values for AES self-test. These
* values we're derived from independent test code
* using OpenSSL.
*/
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,
};
static uint8_t srtp_aes_gcm_test_case_0_iv[12] = {
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88
};
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
};
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
};
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,
};
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 */
};
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,
};
static uint8_t srtp_aes_gcm_test_case_1_iv[12] = {
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88
};
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
};
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
};
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,
};
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 */
};
static const char srtp_aes_gcm_128_openssl_description[] =
"AES-128 GCM using openssl";
static const char srtp_aes_gcm_256_openssl_description[] =
"AES-256 GCM using openssl";
/*
* This is the vector function table for this crypto engine.
*/
const srtp_cipher_type_t srtp_aes_gcm_128_openssl = {
const srtp_cipher_type_t srtp_aes_gcm_128 = {
srtp_aes_gcm_openssl_alloc,
srtp_aes_gcm_openssl_dealloc,
srtp_aes_gcm_openssl_context_init,
@ -544,14 +407,14 @@ const srtp_cipher_type_t srtp_aes_gcm_128_openssl = {
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
};
/*
* This is the vector function table for this crypto engine.
*/
const srtp_cipher_type_t srtp_aes_gcm_256_openssl = {
const srtp_cipher_type_t srtp_aes_gcm_256 = {
srtp_aes_gcm_openssl_alloc,
srtp_aes_gcm_openssl_dealloc,
srtp_aes_gcm_openssl_context_init,
@ -561,7 +424,6 @@ const srtp_cipher_type_t srtp_aes_gcm_256_openssl = {
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
};

View File

@ -44,21 +44,20 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#define ALIGN_32 0
#include "aes_icm.h"
#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 */
"aes icm" /* printable module name */
0, /* debugging is off by default */
"aes icm" /* printable module name */
};
extern const srtp_cipher_type_t srtp_aes_icm_128;
extern const srtp_cipher_type_t srtp_aes_icm_256;
/*
* integer counter mode works as follows:
@ -94,12 +93,15 @@ extern const srtp_cipher_type_t srtp_aes_icm_256;
*
*/
static srtp_err_status_t srtp_aes_icm_alloc (srtp_cipher_t **c, int key_len, int tlen)
static srtp_err_status_t srtp_aes_icm_alloc(srtp_cipher_t **c,
int key_len,
int tlen)
{
srtp_aes_icm_ctx_t *icm;
(void)tlen;
debug_print(srtp_mod_aes_icm,
"allocating cipher with key length %d", key_len);
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d",
key_len);
/*
* The check for key_len = 30/46 does not apply. Our usage
@ -107,7 +109,8 @@ static srtp_err_status_t srtp_aes_icm_alloc (srtp_cipher_t **c, int key_len, int
* has not broken anything. Don't know what would be the
* effect of skipping this check for srtp in general.
*/
if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT && key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
return srtp_err_status_bad_param;
}
@ -116,14 +119,13 @@ static srtp_err_status_t srtp_aes_icm_alloc (srtp_cipher_t **c, int key_len, int
if (*c == NULL) {
return srtp_err_status_alloc_fail;
}
memset(*c, 0x0, sizeof(srtp_cipher_t));
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
srtp_crypto_free(*c);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
memset(icm, 0x0, sizeof(srtp_aes_icm_ctx_t));
/* set pointers */
(*c)->state = icm;
@ -146,7 +148,7 @@ static srtp_err_status_t srtp_aes_icm_alloc (srtp_cipher_t **c, int key_len, int
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_aes_icm_dealloc (srtp_cipher_t *c)
static srtp_err_status_t srtp_aes_icm_dealloc(srtp_cipher_t *c)
{
srtp_aes_icm_ctx_t *ctx;
@ -167,7 +169,6 @@ static srtp_err_status_t srtp_aes_icm_dealloc (srtp_cipher_t *c)
return srtp_err_status_ok;
}
/*
* aes_icm_context_init(...) initializes the aes_icm_context
* using the value in key[].
@ -178,15 +179,16 @@ static srtp_err_status_t srtp_aes_icm_dealloc (srtp_cipher_t *c)
* randomizes the starting point in the keystream
*/
static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key)
static srtp_err_status_t srtp_aes_icm_context_init(void *cv, const uint8_t *key)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
srtp_err_status_t status;
int base_key_len, copy_len;
if (c->key_size == SRTP_AES_ICM_128_KEY_LEN_WSALT || c->key_size == SRTP_AES_ICM_256_KEY_LEN_WSALT) {
if (c->key_size == SRTP_AES_ICM_128_KEY_LEN_WSALT ||
c->key_size == SRTP_AES_ICM_256_KEY_LEN_WSALT) {
base_key_len = c->key_size - SRTP_SALT_LEN;
} else{
} else {
return srtp_err_status_bad_param;
}
@ -198,7 +200,8 @@ static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key
v128_set_to_zero(&c->offset);
copy_len = c->key_size - base_key_len;
/* force last two octets of the offset to be left zero (for srtp compatibility) */
/* force last two octets of the offset to be left zero (for srtp
* compatibility) */
if (copy_len > SRTP_SALT_LEN) {
copy_len = SRTP_SALT_LEN;
}
@ -206,13 +209,13 @@ static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key
memcpy(&c->counter, key + base_key_len, copy_len);
memcpy(&c->offset, key + base_key_len, copy_len);
debug_print(srtp_mod_aes_icm,
"key: %s", srtp_octet_string_hex_string(key, base_key_len));
debug_print(srtp_mod_aes_icm,
"offset: %s", v128_hex_string(&c->offset));
debug_print(srtp_mod_aes_icm, "key: %s",
srtp_octet_string_hex_string(key, base_key_len));
debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
/* expand key */
status = srtp_aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
status =
srtp_aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
if (status) {
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
@ -230,21 +233,23 @@ static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key
* the offset
*/
static srtp_err_status_t srtp_aes_icm_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t direction)
static srtp_err_status_t srtp_aes_icm_set_iv(void *cv,
uint8_t *iv,
srtp_cipher_direction_t direction)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
v128_t nonce;
(void)direction;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
debug_print(srtp_mod_aes_icm,
"setting iv: %s", v128_hex_string(&nonce));
debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce));
v128_xor(&c->counter, &c->offset, &nonce);
debug_print(srtp_mod_aes_icm,
"set_counter: %s", v128_hex_string(&c->counter));
debug_print(srtp_mod_aes_icm, "set_counter: %s",
v128_hex_string(&c->counter));
/* indicate that the keystream_buffer is empty */
c->bytes_in_buffer = 0;
@ -252,15 +257,13 @@ static srtp_err_status_t srtp_aes_icm_set_iv (void *cv, uint8_t *iv, srtp_cipher
return srtp_err_status_ok;
}
/*
* aes_icm_advance(...) refills the keystream_buffer and
* advances the block index of the sicm_context forward by one
*
* this is an internal, hopefully inlined function
*/
static void srtp_aes_icm_advance (srtp_aes_icm_ctx_t *c)
static void srtp_aes_icm_advance(srtp_aes_icm_ctx_t *c)
{
/* fill buffer with new keystream */
v128_copy(&c->keystream_buffer, &c->counter);
@ -278,7 +281,7 @@ static void srtp_aes_icm_advance (srtp_aes_icm_ctx_t *c)
}
}
/*e
/*
* icm_encrypt deals with the following cases:
*
* bytes_to_encr < bytes_in_buffer
@ -291,23 +294,24 @@ static void srtp_aes_icm_advance (srtp_aes_icm_ctx_t *c)
* - fill buffer then add in remaining (< 16) bytes of keystream
*/
static srtp_err_status_t srtp_aes_icm_encrypt (void *cv,
unsigned char *buf, unsigned int *enc_len)
static srtp_err_status_t srtp_aes_icm_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t*)cv;
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
unsigned int bytes_to_encr = *enc_len;
unsigned int i;
uint32_t *b;
/* check that there's enough segment left*/
if ((bytes_to_encr + htons(c->counter.v16[7])) > 0xffff) {
unsigned int bytes_of_new_keystream = bytes_to_encr - c->bytes_in_buffer;
unsigned int blocks_of_new_keystream = (bytes_of_new_keystream + 15) >> 4;
if ((blocks_of_new_keystream + htons(c->counter.v16[7])) > 0xffff) {
return srtp_err_status_terminus;
}
debug_print(srtp_mod_aes_icm, "block index: %d",
htons(c->counter.v16[7]));
debug_print(srtp_mod_aes_icm, "block index: %d", htons(c->counter.v16[7]));
if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
/* deal with odd case of small bytes_to_encr */
for (i = (sizeof(v128_t) - c->bytes_in_buffer);
i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++) {
@ -320,20 +324,18 @@ static srtp_err_status_t srtp_aes_icm_encrypt (void *cv,
return srtp_err_status_ok;
} else {
/* encrypt bytes until the remaining data is 16-byte aligned */
for (i = (sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++) {
for (i = (sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t);
i++) {
*buf++ ^= c->keystream_buffer.v8[i];
}
bytes_to_encr -= c->bytes_in_buffer;
c->bytes_in_buffer = 0;
}
/* now loop over entire 16-byte blocks of keystream */
for (i = 0; i < (bytes_to_encr / sizeof(v128_t)); i++) {
/* fill buffer with new keystream */
srtp_aes_icm_advance(c);
@ -343,14 +345,14 @@ static srtp_err_status_t srtp_aes_icm_encrypt (void *cv,
*/
#if ALIGN_32
b = (uint32_t*)buf;
b = (uint32_t *)buf;
*b++ ^= c->keystream_buffer.v32[0];
*b++ ^= c->keystream_buffer.v32[1];
*b++ ^= c->keystream_buffer.v32[2];
*b++ ^= c->keystream_buffer.v32[3];
buf = (uint8_t*)b;
buf = (uint8_t *)b;
#else
if ((((unsigned long)buf) & 0x03) != 0) {
if ((((uintptr_t)buf) & 0x03) != 0) {
*buf++ ^= c->keystream_buffer.v8[0];
*buf++ ^= c->keystream_buffer.v8[1];
*buf++ ^= c->keystream_buffer.v8[2];
@ -368,20 +370,18 @@ static srtp_err_status_t srtp_aes_icm_encrypt (void *cv,
*buf++ ^= c->keystream_buffer.v8[14];
*buf++ ^= c->keystream_buffer.v8[15];
} else {
b = (uint32_t*)buf;
b = (uint32_t *)buf;
*b++ ^= c->keystream_buffer.v32[0];
*b++ ^= c->keystream_buffer.v32[1];
*b++ ^= c->keystream_buffer.v32[2];
*b++ ^= c->keystream_buffer.v32[3];
buf = (uint8_t*)b;
buf = (uint8_t *)b;
}
#endif /* #if ALIGN_32 */
#endif /* #if ALIGN_32 */
}
/* if there is a tail end of the data, process it */
if ((bytes_to_encr & 0xf) != 0) {
/* fill buffer with new keystream */
srtp_aes_icm_advance(c);
@ -392,130 +392,46 @@ static srtp_err_status_t srtp_aes_icm_encrypt (void *cv,
/* reset the keystream buffer size to right value */
c->bytes_in_buffer = sizeof(v128_t) - i;
} else {
/* no tail, so just reset the keystream buffer size to zero */
c->bytes_in_buffer = 0;
}
return srtp_err_status_ok;
}
static const char srtp_aes_icm_128_description[] = "AES-128 integer counter mode";
static const char srtp_aes_icm_256_description[] = "AES-256 integer counter mode";
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
};
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
};
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,
};
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
};
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 */
};
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
};
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
};
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,
};
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
};
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 */
};
static const char srtp_aes_icm_128_description[] =
"AES-128 integer counter mode";
static const char srtp_aes_icm_256_description[] =
"AES-256 integer counter mode";
/*
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_128 = {
srtp_aes_icm_alloc,
srtp_aes_icm_dealloc,
srtp_aes_icm_context_init,
0, /* set_aad */
srtp_aes_icm_encrypt,
srtp_aes_icm_encrypt,
srtp_aes_icm_set_iv,
0, /* get_tag */
srtp_aes_icm_128_description,
&srtp_aes_icm_128_test_case_0,
SRTP_AES_ICM_128
srtp_aes_icm_alloc, /* */
srtp_aes_icm_dealloc, /* */
srtp_aes_icm_context_init, /* */
0, /* set_aad */
srtp_aes_icm_encrypt, /* */
srtp_aes_icm_encrypt, /* */
srtp_aes_icm_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_128_description, /* */
&srtp_aes_icm_128_test_case_0, /* */
SRTP_AES_ICM_128 /* */
};
const srtp_cipher_type_t srtp_aes_icm_256 = {
srtp_aes_icm_alloc,
srtp_aes_icm_dealloc,
srtp_aes_icm_context_init,
0, /* set_aad */
srtp_aes_icm_encrypt,
srtp_aes_icm_encrypt,
srtp_aes_icm_set_iv,
0, /* get_tag */
srtp_aes_icm_256_description,
&srtp_aes_icm_256_test_case_0,
SRTP_AES_ICM_256
srtp_aes_icm_alloc, /* */
srtp_aes_icm_dealloc, /* */
srtp_aes_icm_context_init, /* */
0, /* set_aad */
srtp_aes_icm_encrypt, /* */
srtp_aes_icm_encrypt, /* */
srtp_aes_icm_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_256_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};

View File

@ -0,0 +1,374 @@
/*
* aes_icm_mbedtls.c
*
* AES Integer Counter Mode
*
* YongCheng Yang
*/
/*
*
* Copyright (c) 2013-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 <mbedtls/aes.h>
#include "aes_icm_ext.h"
#include "crypto_types.h"
#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 */
"aes icm mbedtls" /* printable module name */
};
/*
* integer counter mode works as follows:
*
* https://tools.ietf.org/html/rfc3711#section-4.1.1
*
* E(k, IV) || E(k, IV + 1 mod 2^128) || E(k, IV + 2 mod 2^128) ...
* IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)
*
* IV SHALL be defined by the SSRC, the SRTP packet index i,
* and the SRTP session salting key k_s.
*
* SSRC: 32bits.
* Sequence number: 16bits.
* nonce is 64bits. .
* packet index = ROC || SEQ. (ROC: Rollover counter)
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | packet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30, 38, or 46 for
* AES-128, AES-192, and AES-256 respectively. Note, this key_len
* value is inflated, as it also accounts for the 112 bit salt
* value. The tlen argument is for the AEAD tag length, which
* isn't used in counter mode.
*/
static srtp_err_status_t srtp_aes_icm_mbedtls_alloc(srtp_cipher_t **c,
int key_len,
int tlen)
{
srtp_aes_icm_ctx_t *icm;
(void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d",
key_len);
/*
* Verify the key_len is valid for one of: AES-128/192/256
*/
if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_ICM_192_KEY_LEN_WSALT &&
key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
return srtp_err_status_bad_param;
}
/* allocate memory a cipher of type aes_icm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return srtp_err_status_alloc_fail;
}
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
icm->ctx =
(mbedtls_aes_context *)srtp_crypto_alloc(sizeof(mbedtls_aes_context));
if (icm->ctx == NULL) {
srtp_crypto_free(icm);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
mbedtls_aes_init(icm->ctx);
/* set pointers */
(*c)->state = icm;
/* setup cipher parameters */
switch (key_len) {
case SRTP_AES_ICM_128_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_128;
(*c)->type = &srtp_aes_icm_128;
icm->key_size = SRTP_AES_128_KEY_LEN;
break;
case SRTP_AES_ICM_192_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_192;
(*c)->type = &srtp_aes_icm_192;
icm->key_size = SRTP_AES_192_KEY_LEN;
break;
case SRTP_AES_ICM_256_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_256;
(*c)->type = &srtp_aes_icm_256;
icm->key_size = SRTP_AES_256_KEY_LEN;
break;
}
/* set key size */
(*c)->key_len = key_len;
return srtp_err_status_ok;
}
/*
* This function deallocates an instance of this engine
*/
static srtp_err_status_t srtp_aes_icm_mbedtls_dealloc(srtp_cipher_t *c)
{
srtp_aes_icm_ctx_t *ctx;
if (c == NULL) {
return srtp_err_status_bad_param;
}
/*
* Free the aes context
*/
ctx = (srtp_aes_icm_ctx_t *)c->state;
if (ctx != NULL) {
mbedtls_aes_free(ctx->ctx);
srtp_crypto_free(ctx->ctx);
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_aes_icm_mbedtls_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
uint32_t key_size_in_bits = (c->key_size << 3);
int errcode = 0;
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
memcpy(&c->counter, key + c->key_size, SRTP_SALT_LEN);
memcpy(&c->offset, key + c->key_size, SRTP_SALT_LEN);
/* force last two octets of the offset to zero (for srtp compatibility) */
c->offset.v8[SRTP_SALT_LEN] = c->offset.v8[SRTP_SALT_LEN + 1] = 0;
c->counter.v8[SRTP_SALT_LEN] = c->counter.v8[SRTP_SALT_LEN + 1] = 0;
debug_print(srtp_mod_aes_icm, "key: %s",
srtp_octet_string_hex_string(key, c->key_size));
debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
switch (c->key_size) {
case SRTP_AES_256_KEY_LEN:
case SRTP_AES_192_KEY_LEN:
case SRTP_AES_128_KEY_LEN:
break;
default:
return srtp_err_status_bad_param;
break;
}
errcode = mbedtls_aes_setkey_enc(c->ctx, key, key_size_in_bits);
if (errcode != 0) {
debug_print(srtp_mod_aes_icm, "errCode: %d", errcode);
}
return srtp_err_status_ok;
}
/*
* aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
static srtp_err_status_t srtp_aes_icm_mbedtls_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t dir)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
v128_t nonce;
(void)dir;
c->nc_off = 0;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce));
v128_xor(&c->counter, &c->offset, &nonce);
debug_print(srtp_mod_aes_icm, "set_counter: %s",
v128_hex_string(&c->counter));
return srtp_err_status_ok;
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_icm_mbedtls_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
int errCode = 0;
debug_print(srtp_mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter));
errCode =
mbedtls_aes_crypt_ctr(c->ctx, *enc_len, &(c->nc_off), c->counter.v8,
c->stream_block.v8, buf, buf);
if (errCode != 0) {
debug_print(srtp_mod_aes_icm, "encrypt error: %d", errCode);
return srtp_err_status_cipher_fail;
}
return srtp_err_status_ok;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_icm_128_mbedtls_description[] =
"AES-128 counter mode using mbedtls";
static const char srtp_aes_icm_192_mbedtls_description[] =
"AES-192 counter mode using mbedtls";
static const char srtp_aes_icm_256_mbedtls_description[] =
"AES-256 counter mode using mbedtls";
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_128 = {
srtp_aes_icm_mbedtls_alloc, /* */
srtp_aes_icm_mbedtls_dealloc, /* */
srtp_aes_icm_mbedtls_context_init, /* */
0, /* set_aad */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_128_mbedtls_description, /* */
&srtp_aes_icm_128_test_case_0, /* */
SRTP_AES_ICM_128 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_192 = {
srtp_aes_icm_mbedtls_alloc, /* */
srtp_aes_icm_mbedtls_dealloc, /* */
srtp_aes_icm_mbedtls_context_init, /* */
0, /* set_aad */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_192_mbedtls_description, /* */
&srtp_aes_icm_192_test_case_0, /* */
SRTP_AES_ICM_192 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_256 = {
srtp_aes_icm_mbedtls_alloc, /* */
srtp_aes_icm_mbedtls_dealloc, /* */
srtp_aes_icm_mbedtls_context_init, /* */
0, /* set_aad */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_256_mbedtls_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};

View File

@ -0,0 +1,406 @@
/*
* aes_icm_nss.c
*
* AES Integer Counter Mode
*
* Richard L. Barnes
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2013-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 "aes_icm_ext.h"
#include "crypto_types.h"
#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 */
"aes icm nss" /* printable module name */
};
/*
* integer counter mode works as follows:
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | packet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30, 38, or 46 for
* AES-128, AES-192, and AES-256 respectively. Note, this key_len
* value is inflated, as it also accounts for the 112 bit salt
* value. The tlen argument is for the AEAD tag length, which
* isn't used in counter mode.
*/
static srtp_err_status_t srtp_aes_icm_nss_alloc(srtp_cipher_t **c,
int key_len,
int tlen)
{
srtp_aes_icm_ctx_t *icm;
NSSInitContext *nss;
(void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d",
key_len);
/*
* Verify the key_len is valid for one of: AES-128/192/256
*/
if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_ICM_192_KEY_LEN_WSALT &&
key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
return srtp_err_status_bad_param;
}
/* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
nss = NSS_InitContext("", "", "", "", NULL,
NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
NSS_INIT_OPTIMIZESPACE);
if (!nss) {
return (srtp_err_status_cipher_fail);
}
/* allocate memory a cipher of type aes_icm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
NSS_ShutdownContext(nss);
return srtp_err_status_alloc_fail;
}
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
NSS_ShutdownContext(nss);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
icm->key = NULL;
icm->ctx = NULL;
icm->nss = nss;
/* set pointers */
(*c)->state = icm;
/* setup cipher parameters */
switch (key_len) {
case SRTP_AES_ICM_128_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_128;
(*c)->type = &srtp_aes_icm_128;
icm->key_size = SRTP_AES_128_KEY_LEN;
break;
case SRTP_AES_ICM_192_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_192;
(*c)->type = &srtp_aes_icm_192;
icm->key_size = SRTP_AES_192_KEY_LEN;
break;
case SRTP_AES_ICM_256_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_256;
(*c)->type = &srtp_aes_icm_256;
icm->key_size = SRTP_AES_256_KEY_LEN;
break;
}
/* set key size */
(*c)->key_len = key_len;
return srtp_err_status_ok;
}
/*
* This function deallocates an instance of this engine
*/
static srtp_err_status_t srtp_aes_icm_nss_dealloc(srtp_cipher_t *c)
{
srtp_aes_icm_ctx_t *ctx;
ctx = (srtp_aes_icm_ctx_t *)c->state;
if (ctx) {
/* free any PK11 values that have been created */
if (ctx->key) {
PK11_FreeSymKey(ctx->key);
ctx->key = NULL;
}
if (ctx->ctx) {
PK11_DestroyContext(ctx->ctx, PR_TRUE);
ctx->ctx = NULL;
}
if (ctx->nss) {
NSS_ShutdownContext(ctx->nss);
ctx->nss = NULL;
}
/* zeroize everything */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return (srtp_err_status_ok);
}
/*
* aes_icm_nss_context_init(...) initializes the aes_icm_context
* using the value in key[].
*
* the key is the secret key
*
* the salt is unpredictable (but not necessarily secret) data which
* randomizes the starting point in the keystream
*/
static srtp_err_status_t srtp_aes_icm_nss_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
memcpy(&c->counter, key + c->key_size, SRTP_SALT_LEN);
memcpy(&c->offset, key + c->key_size, SRTP_SALT_LEN);
/* force last two octets of the offset to zero (for srtp compatibility) */
c->offset.v8[SRTP_SALT_LEN] = c->offset.v8[SRTP_SALT_LEN + 1] = 0;
c->counter.v8[SRTP_SALT_LEN] = c->counter.v8[SRTP_SALT_LEN + 1] = 0;
debug_print(srtp_mod_aes_icm, "key: %s",
srtp_octet_string_hex_string(key, c->key_size));
debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
if (c->key) {
PK11_FreeSymKey(c->key);
c->key = NULL;
}
PK11SlotInfo *slot = PK11_GetBestSlot(CKM_AES_CTR, NULL);
if (!slot) {
return srtp_err_status_bad_param;
}
SECItem keyItem = { siBuffer, (unsigned char *)key, c->key_size };
c->key = PK11_ImportSymKey(slot, CKM_AES_CTR, PK11_OriginUnwrap,
CKA_ENCRYPT, &keyItem, NULL);
PK11_FreeSlot(slot);
if (!c->key) {
return srtp_err_status_cipher_fail;
}
return (srtp_err_status_ok);
}
/*
* aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
static srtp_err_status_t srtp_aes_icm_nss_set_iv(void *cv,
uint8_t *iv,
srtp_cipher_direction_t dir)
{
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);
debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce));
v128_xor(&c->counter, &c->offset, &nonce);
debug_print(srtp_mod_aes_icm, "set_counter: %s",
v128_hex_string(&c->counter));
/* set up the PK11 context now that we have all the info */
CK_AES_CTR_PARAMS param;
param.ulCounterBits = 16;
memcpy(param.cb, &c->counter, 16);
if (!c->key) {
return srtp_err_status_bad_param;
}
if (c->ctx) {
PK11_DestroyContext(c->ctx, PR_TRUE);
}
SECItem paramItem = { siBuffer, (unsigned char *)&param,
sizeof(CK_AES_CTR_PARAMS) };
c->ctx = PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, c->key,
&paramItem);
if (!c->ctx) {
return srtp_err_status_cipher_fail;
}
return srtp_err_status_ok;
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_icm_nss_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
if (!c->ctx) {
return srtp_err_status_bad_param;
}
int rv =
PK11_CipherOp(c->ctx, buf, (int *)enc_len, *enc_len, buf, *enc_len);
srtp_err_status_t status = (srtp_err_status_ok);
if (rv != SECSuccess) {
status = (srtp_err_status_cipher_fail);
}
return status;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_icm_128_nss_description[] =
"AES-128 counter mode using NSS";
static const char srtp_aes_icm_192_nss_description[] =
"AES-192 counter mode using NSS";
static const char srtp_aes_icm_256_nss_description[] =
"AES-256 counter mode using NSS";
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_128 = {
srtp_aes_icm_nss_alloc, /* */
srtp_aes_icm_nss_dealloc, /* */
srtp_aes_icm_nss_context_init, /* */
0, /* set_aad */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_128_nss_description, /* */
&srtp_aes_icm_128_test_case_0, /* */
SRTP_AES_ICM_128 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_192 = {
srtp_aes_icm_nss_alloc, /* */
srtp_aes_icm_nss_dealloc, /* */
srtp_aes_icm_nss_context_init, /* */
0, /* set_aad */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_192_nss_description, /* */
&srtp_aes_icm_192_test_case_0, /* */
SRTP_AES_ICM_192 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_256 = {
srtp_aes_icm_nss_alloc, /* */
srtp_aes_icm_nss_dealloc, /* */
srtp_aes_icm_nss_context_init, /* */
0, /* set_aad */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_256_nss_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};

View File

@ -49,23 +49,21 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include <openssl/evp.h>
#include "aes_icm_ossl.h"
#include "aes_icm_ext.h"
#include "crypto_types.h"
#include "err.h" /* for srtp_debug */
#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 */
"aes icm ossl" /* printable module name */
0, /* debugging is off by default */
"aes icm ossl" /* printable module name */
};
extern const srtp_cipher_type_t srtp_aes_icm_128;
extern const srtp_cipher_type_t srtp_aes_icm_192;
extern const srtp_cipher_type_t srtp_aes_icm_256;
/*
* integer counter mode works as follows:
@ -81,9 +79,9 @@ extern const srtp_cipher_type_t srtp_aes_icm_256;
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
@ -109,16 +107,21 @@ extern const srtp_cipher_type_t srtp_aes_icm_256;
* value. The tlen argument is for the AEAD tag length, which
* isn't used in counter mode.
*/
static srtp_err_status_t srtp_aes_icm_openssl_alloc (srtp_cipher_t **c, int key_len, int tlen)
static srtp_err_status_t srtp_aes_icm_openssl_alloc(srtp_cipher_t **c,
int key_len,
int tlen)
{
srtp_aes_icm_ctx_t *icm;
(void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", key_len);
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d",
key_len);
/*
* Verify the key_len is valid for one of: AES-128/192/256
*/
if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT && key_len != SRTP_AES_ICM_192_KEY_LEN_WSALT &&
if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_ICM_192_KEY_LEN_WSALT &&
key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
return srtp_err_status_bad_param;
}
@ -128,15 +131,13 @@ static srtp_err_status_t srtp_aes_icm_openssl_alloc (srtp_cipher_t **c, int key_
if (*c == NULL) {
return srtp_err_status_alloc_fail;
}
memset(*c, 0x0, sizeof(srtp_cipher_t));
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
memset(icm, 0x0, sizeof(srtp_aes_icm_ctx_t));
icm->ctx = EVP_CIPHER_CTX_new();
if (icm->ctx == NULL) {
@ -168,17 +169,16 @@ static srtp_err_status_t srtp_aes_icm_openssl_alloc (srtp_cipher_t **c, int key_
break;
}
/* set key size */
/* set key size */
(*c)->key_len = key_len;
return srtp_err_status_ok;
}
/*
* This function deallocates an instance of this engine
*/
static srtp_err_status_t srtp_aes_icm_openssl_dealloc (srtp_cipher_t *c)
static srtp_err_status_t srtp_aes_icm_openssl_dealloc(srtp_cipher_t *c)
{
srtp_aes_icm_ctx_t *ctx;
@ -189,7 +189,7 @@ static srtp_err_status_t srtp_aes_icm_openssl_dealloc (srtp_cipher_t *c)
/*
* Free the EVP context
*/
ctx = (srtp_aes_icm_ctx_t*)c->state;
ctx = (srtp_aes_icm_ctx_t *)c->state;
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx->ctx);
/* zeroize the key material */
@ -212,7 +212,8 @@ static srtp_err_status_t srtp_aes_icm_openssl_dealloc (srtp_cipher_t *c)
* the salt is unpredictable (but not necessarily secret) data which
* randomizes the starting point in the keystream
*/
static srtp_err_status_t srtp_aes_icm_openssl_context_init (void* cv, const uint8_t *key)
static srtp_err_status_t srtp_aes_icm_openssl_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
const EVP_CIPHER *evp;
@ -230,7 +231,8 @@ static srtp_err_status_t srtp_aes_icm_openssl_context_init (void* cv, const uint
c->offset.v8[SRTP_SALT_LEN] = c->offset.v8[SRTP_SALT_LEN + 1] = 0;
c->counter.v8[SRTP_SALT_LEN] = c->counter.v8[SRTP_SALT_LEN + 1] = 0;
debug_print(srtp_mod_aes_icm, "key: %s", srtp_octet_string_hex_string(key, c->key_size));
debug_print(srtp_mod_aes_icm, "key: %s",
srtp_octet_string_hex_string(key, c->key_size));
debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
switch (c->key_size) {
@ -248,25 +250,27 @@ static srtp_err_status_t srtp_aes_icm_openssl_context_init (void* cv, const uint
break;
}
if (!EVP_EncryptInit_ex(c->ctx, evp,
NULL, key, NULL)) {
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;
}
/*
* aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
static srtp_err_status_t srtp_aes_icm_openssl_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t dir)
static srtp_err_status_t srtp_aes_icm_openssl_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t dir)
{
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);
@ -275,14 +279,14 @@ static srtp_err_status_t srtp_aes_icm_openssl_set_iv (void *cv, uint8_t *iv, srt
v128_xor(&c->counter, &c->offset, &nonce);
debug_print(srtp_mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter));
debug_print(srtp_mod_aes_icm, "set_counter: %s",
v128_hex_string(&c->counter));
if (!EVP_EncryptInit_ex(c->ctx, NULL,
NULL, NULL, c->counter.v8)) {
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;
}
/*
@ -293,7 +297,9 @@ static srtp_err_status_t srtp_aes_icm_openssl_set_iv (void *cv, uint8_t *iv, srt
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_icm_openssl_encrypt (void *cv, unsigned char *buf, unsigned int *enc_len)
static srtp_err_status_t srtp_aes_icm_openssl_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
int len = 0;
@ -305,7 +311,7 @@ static srtp_err_status_t srtp_aes_icm_openssl_encrypt (void *cv, unsigned char *
}
*enc_len = len;
if (!EVP_EncryptFinal_ex(c->ctx, buf, &len)) {
if (!EVP_EncryptFinal_ex(c->ctx, buf + len, &len)) {
return srtp_err_status_cipher_fail;
}
*enc_len += len;
@ -316,162 +322,29 @@ static srtp_err_status_t srtp_aes_icm_openssl_encrypt (void *cv, unsigned char *
/*
* Name of this crypto engine
*/
static const char srtp_aes_icm_128_openssl_description[] = "AES-128 counter mode using openssl";
static const char srtp_aes_icm_192_openssl_description[] = "AES-192 counter mode using openssl";
static const char srtp_aes_icm_256_openssl_description[] = "AES-256 counter mode using openssl";
/*
* KAT values for AES self-test. These
* values came from the legacy libsrtp code.
*/
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
};
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
};
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,
};
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
};
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.
*/
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
};
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
};
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,
};
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
};
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.
*/
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
};
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
};
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,
};
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
};
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 */
};
static const char srtp_aes_icm_128_openssl_description[] =
"AES-128 counter mode using openssl";
static const char srtp_aes_icm_192_openssl_description[] =
"AES-192 counter mode using openssl";
static const char srtp_aes_icm_256_openssl_description[] =
"AES-256 counter mode using openssl";
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_128 = {
srtp_aes_icm_openssl_alloc,
srtp_aes_icm_openssl_dealloc,
srtp_aes_icm_openssl_context_init,
0, /* set_aad */
srtp_aes_icm_openssl_encrypt,
srtp_aes_icm_openssl_encrypt,
srtp_aes_icm_openssl_set_iv,
0, /* get_tag */
srtp_aes_icm_128_openssl_description,
&srtp_aes_icm_128_test_case_0,
SRTP_AES_ICM_128
srtp_aes_icm_openssl_alloc, /* */
srtp_aes_icm_openssl_dealloc, /* */
srtp_aes_icm_openssl_context_init, /* */
0, /* set_aad */
srtp_aes_icm_openssl_encrypt, /* */
srtp_aes_icm_openssl_encrypt, /* */
srtp_aes_icm_openssl_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_128_openssl_description, /* */
&srtp_aes_icm_128_test_case_0, /* */
SRTP_AES_ICM_128 /* */
};
/*
@ -479,17 +352,17 @@ const srtp_cipher_type_t srtp_aes_icm_128 = {
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_192 = {
srtp_aes_icm_openssl_alloc,
srtp_aes_icm_openssl_dealloc,
srtp_aes_icm_openssl_context_init,
0, /* set_aad */
srtp_aes_icm_openssl_encrypt,
srtp_aes_icm_openssl_encrypt,
srtp_aes_icm_openssl_set_iv,
0, /* get_tag */
srtp_aes_icm_192_openssl_description,
&srtp_aes_icm_192_test_case_0,
SRTP_AES_ICM_192
srtp_aes_icm_openssl_alloc, /* */
srtp_aes_icm_openssl_dealloc, /* */
srtp_aes_icm_openssl_context_init, /* */
0, /* set_aad */
srtp_aes_icm_openssl_encrypt, /* */
srtp_aes_icm_openssl_encrypt, /* */
srtp_aes_icm_openssl_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_192_openssl_description, /* */
&srtp_aes_icm_192_test_case_0, /* */
SRTP_AES_ICM_192 /* */
};
/*
@ -497,16 +370,15 @@ const srtp_cipher_type_t srtp_aes_icm_192 = {
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_256 = {
srtp_aes_icm_openssl_alloc,
srtp_aes_icm_openssl_dealloc,
srtp_aes_icm_openssl_context_init,
0, /* set_aad */
srtp_aes_icm_openssl_encrypt,
srtp_aes_icm_openssl_encrypt,
srtp_aes_icm_openssl_set_iv,
0, /* get_tag */
srtp_aes_icm_256_openssl_description,
&srtp_aes_icm_256_test_case_0,
SRTP_AES_ICM_256
srtp_aes_icm_openssl_alloc, /* */
srtp_aes_icm_openssl_dealloc, /* */
srtp_aes_icm_openssl_context_init, /* */
0, /* set_aad */
srtp_aes_icm_openssl_encrypt, /* */
srtp_aes_icm_openssl_encrypt, /* */
srtp_aes_icm_openssl_set_iv, /* */
0, /* get_tag */
srtp_aes_icm_256_openssl_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};

View File

@ -45,56 +45,62 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "cipher.h"
#include "cipher_priv.h"
#include "crypto_types.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h" /* for crypto_alloc(), crypto_free() */
#include "err.h" /* for srtp_debug */
#include "alloc.h" /* for crypto_alloc(), crypto_free() */
srtp_debug_module_t srtp_mod_cipher = {
0, /* debugging is off by default */
"cipher" /* printable module name */
0, /* debugging is off by default */
"cipher" /* printable module name */
};
srtp_err_status_t srtp_cipher_type_alloc (const srtp_cipher_type_t *ct, srtp_cipher_t **c, int key_len, int tlen)
srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct,
srtp_cipher_t **c,
int key_len,
int tlen)
{
if (!ct || !ct->alloc) {
return (srtp_err_status_bad_param);
return (srtp_err_status_bad_param);
}
return ((ct)->alloc((c), (key_len), (tlen)));
}
srtp_err_status_t srtp_cipher_dealloc (srtp_cipher_t *c)
srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c)
{
if (!c || !c->type) {
return (srtp_err_status_bad_param);
return (srtp_err_status_bad_param);
}
return (((c)->type)->dealloc(c));
}
srtp_err_status_t srtp_cipher_init (srtp_cipher_t *c, const uint8_t *key)
srtp_err_status_t srtp_cipher_init(srtp_cipher_t *c, const uint8_t *key)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
return (srtp_err_status_bad_param);
}
return (((c)->type)->init(((c)->state), (key)));
}
srtp_err_status_t srtp_cipher_set_iv (srtp_cipher_t *c, uint8_t *iv, int direction)
srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c,
uint8_t *iv,
int direction)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
return (srtp_err_status_bad_param);
}
return (((c)->type)->set_iv(((c)->state), iv, direction));
return (((c)->type)->set_iv(((c)->state), iv, direction));
}
srtp_err_status_t srtp_cipher_output (srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output)
srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c,
uint8_t *buffer,
uint32_t *num_octets_to_output)
{
/* zeroize the buffer */
octet_string_set_to_zero(buffer, *num_octets_to_output);
@ -102,43 +108,51 @@ srtp_err_status_t srtp_cipher_output (srtp_cipher_t *c, uint8_t *buffer, uint32_
return (((c)->type)->encrypt(((c)->state), buffer, num_octets_to_output));
}
srtp_err_status_t srtp_cipher_encrypt (srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output)
srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c,
uint8_t *buffer,
uint32_t *num_octets_to_output)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
return (srtp_err_status_bad_param);
}
return (((c)->type)->encrypt(((c)->state), buffer, num_octets_to_output));
}
srtp_err_status_t srtp_cipher_decrypt (srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output)
srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c,
uint8_t *buffer,
uint32_t *num_octets_to_output)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
return (srtp_err_status_bad_param);
}
return (((c)->type)->decrypt(((c)->state), buffer, num_octets_to_output));
}
srtp_err_status_t srtp_cipher_get_tag (srtp_cipher_t *c, uint8_t *buffer, uint32_t *tag_len)
srtp_err_status_t srtp_cipher_get_tag(srtp_cipher_t *c,
uint8_t *buffer,
uint32_t *tag_len)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
return (srtp_err_status_bad_param);
}
if (!((c)->type)->get_tag) {
return (srtp_err_status_no_such_op);
return (srtp_err_status_no_such_op);
}
return (((c)->type)->get_tag(((c)->state), buffer, tag_len));
}
srtp_err_status_t srtp_cipher_set_aad (srtp_cipher_t *c, const uint8_t *aad, uint32_t aad_len)
srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c,
const uint8_t *aad,
uint32_t aad_len)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
return (srtp_err_status_bad_param);
}
if (!((c)->type)->set_aad) {
return (srtp_err_status_no_such_op);
return (srtp_err_status_no_such_op);
}
return (((c)->type)->set_aad(((c)->state), aad, aad_len));
@ -146,57 +160,52 @@ srtp_err_status_t srtp_cipher_set_aad (srtp_cipher_t *c, const uint8_t *aad, uin
/* some bookkeeping functions */
int srtp_cipher_get_key_length (const srtp_cipher_t *c)
int srtp_cipher_get_key_length(const srtp_cipher_t *c)
{
return c->key_len;
}
/*
* A trivial platform independent random source.
* For use in test only.
*/
void srtp_cipher_rand_for_tests(void *dest, uint32_t len)
{
/* Generic C-library (rand()) version */
/* This is a random source of last resort */
uint8_t *dst = (uint8_t *)dest;
while (len) {
int val = rand();
/* rand() returns 0-32767 (ugh) */
/* Is this a good enough way to get random bytes?
It is if it passes FIPS-140... */
*dst++ = val & 0xff;
len--;
}
}
/*
* A trivial platform independent random source. The random
* data is used for some of the cipher self-tests.
* A trivial platform independent 32 bit random number.
* For use in test only.
*/
static srtp_err_status_t srtp_cipher_rand (void *dest, uint32_t len)
uint32_t srtp_cipher_rand_u32_for_tests(void)
{
#if defined(HAVE_RAND_S)
uint8_t *dst = (uint8_t *)dest;
while (len)
{
unsigned int val;
errno_t err = rand_s(&val);
if (err != 0)
return srtp_err_status_fail;
*dst++ = val & 0xff;
len--;
}
#else
/* Generic C-library (rand()) version */
/* This is a random source of last resort */
uint8_t *dst = (uint8_t *)dest;
while (len)
{
int val = rand();
/* rand() returns 0-32767 (ugh) */
/* Is this a good enough way to get random bytes?
It is if it passes FIPS-140... */
*dst++ = val & 0xff;
len--;
}
#endif
return srtp_err_status_ok;
uint32_t r;
srtp_cipher_rand_for_tests(&r, sizeof(r));
return r;
}
#define SELF_TEST_BUF_OCTETS 128
#define NUM_RAND_TESTS 128
#define MAX_KEY_LEN 64
#define NUM_RAND_TESTS 128
#define MAX_KEY_LEN 64
/*
* srtp_cipher_type_test(ct, test_data) tests a cipher of type ct against
* test cases provided in a list test_data of values of key, salt, iv,
* plaintext, and ciphertext that is known to be good
*/
srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srtp_cipher_test_case_t *test_data)
srtp_err_status_t srtp_cipher_type_test(
const srtp_cipher_type_t *ct,
const srtp_cipher_test_case_t *test_data)
{
const srtp_cipher_test_case_t *test_case = test_data;
srtp_cipher_t *c;
@ -206,6 +215,7 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
uint32_t tag_len;
unsigned int len;
int i, j, case_num = 0;
unsigned k = 0;
debug_print(srtp_mod_cipher, "running self-test for cipher %s",
ct->description);
@ -224,7 +234,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
*/
while (test_case != NULL) {
/* allocate cipher */
status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets);
status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets,
test_case->tag_length_octets);
if (status) {
return status;
}
@ -232,7 +243,7 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
/*
* test the encrypt function
*/
debug_print(srtp_mod_cipher, "testing encryption", NULL);
debug_print0(srtp_mod_cipher, "testing encryption");
/* initialize cipher */
status = srtp_cipher_init(c, test_case->key);
@ -246,36 +257,39 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
srtp_cipher_dealloc(c);
return srtp_err_status_bad_param;
}
for (i = 0; i < test_case->plaintext_length_octets; i++) {
buffer[i] = test_case->plaintext[i];
for (k = 0; k < test_case->plaintext_length_octets; k++) {
buffer[k] = test_case->plaintext[k];
}
debug_print(srtp_mod_cipher, "plaintext: %s",
srtp_octet_string_hex_string(buffer,
test_case->plaintext_length_octets));
srtp_octet_string_hex_string(
buffer, test_case->plaintext_length_octets));
/* set the initialization vector */
status = srtp_cipher_set_iv(c, (uint8_t*)test_case->idx, srtp_direction_encrypt);
status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
srtp_direction_encrypt);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) {
if (c->algorithm == SRTP_AES_GCM_128 ||
c->algorithm == SRTP_AES_GCM_256) {
debug_print(srtp_mod_cipher, "IV: %s",
srtp_octet_string_hex_string(test_case->idx, 12));
/*
* Set the AAD
*/
status = srtp_cipher_set_aad(c, test_case->aad, test_case->aad_length_octets);
status = srtp_cipher_set_aad(c, test_case->aad,
test_case->aad_length_octets);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "AAD: %s",
srtp_octet_string_hex_string(test_case->aad,
test_case->aad_length_octets));
srtp_octet_string_hex_string(
test_case->aad, test_case->aad_length_octets));
}
/* encrypt */
@ -286,7 +300,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
return status;
}
if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) {
if (c->algorithm == SRTP_AES_GCM_128 ||
c->algorithm == SRTP_AES_GCM_256) {
/*
* Get the GCM tag
*/
@ -299,8 +314,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
}
debug_print(srtp_mod_cipher, "ciphertext: %s",
srtp_octet_string_hex_string(buffer,
test_case->ciphertext_length_octets));
srtp_octet_string_hex_string(
buffer, test_case->ciphertext_length_octets));
/* compare the resulting ciphertext with that in the test case */
if (len != test_case->ciphertext_length_octets) {
@ -308,22 +323,22 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
return srtp_err_status_algo_fail;
}
status = srtp_err_status_ok;
for (i = 0; i < test_case->ciphertext_length_octets; i++) {
if (buffer[i] != test_case->ciphertext[i]) {
for (k = 0; k < test_case->ciphertext_length_octets; k++) {
if (buffer[k] != test_case->ciphertext[k]) {
status = srtp_err_status_algo_fail;
debug_print(srtp_mod_cipher, "test case %d failed", case_num);
debug_print(srtp_mod_cipher, "(failure at byte %d)", i);
debug_print(srtp_mod_cipher, "(failure at byte %u)", k);
break;
}
}
if (status) {
debug_print(srtp_mod_cipher, "c computed: %s",
srtp_octet_string_hex_string(buffer,
2 * test_case->plaintext_length_octets));
srtp_octet_string_hex_string(
buffer, 2 * test_case->plaintext_length_octets));
debug_print(srtp_mod_cipher, "c expected: %s",
srtp_octet_string_hex_string(test_case->ciphertext,
2 * test_case->plaintext_length_octets));
srtp_octet_string_hex_string(
test_case->ciphertext,
2 * test_case->plaintext_length_octets));
srtp_cipher_dealloc(c);
return srtp_err_status_algo_fail;
@ -332,7 +347,7 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
/*
* test the decrypt function
*/
debug_print(srtp_mod_cipher, "testing decryption", NULL);
debug_print0(srtp_mod_cipher, "testing decryption");
/* re-initialize cipher for decryption */
status = srtp_cipher_init(c, test_case->key);
@ -346,33 +361,36 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
srtp_cipher_dealloc(c);
return srtp_err_status_bad_param;
}
for (i = 0; i < test_case->ciphertext_length_octets; i++) {
buffer[i] = test_case->ciphertext[i];
for (k = 0; k < test_case->ciphertext_length_octets; k++) {
buffer[k] = test_case->ciphertext[k];
}
debug_print(srtp_mod_cipher, "ciphertext: %s",
srtp_octet_string_hex_string(buffer,
test_case->plaintext_length_octets));
srtp_octet_string_hex_string(
buffer, test_case->plaintext_length_octets));
/* set the initialization vector */
status = srtp_cipher_set_iv(c, (uint8_t*)test_case->idx, srtp_direction_decrypt);
status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
srtp_direction_decrypt);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) {
if (c->algorithm == SRTP_AES_GCM_128 ||
c->algorithm == SRTP_AES_GCM_256) {
/*
* Set the AAD
*/
status = srtp_cipher_set_aad(c, test_case->aad, test_case->aad_length_octets);
status = srtp_cipher_set_aad(c, test_case->aad,
test_case->aad_length_octets);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "AAD: %s",
srtp_octet_string_hex_string(test_case->aad,
test_case->aad_length_octets));
srtp_octet_string_hex_string(
test_case->aad, test_case->aad_length_octets));
}
/* decrypt */
@ -384,8 +402,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
}
debug_print(srtp_mod_cipher, "plaintext: %s",
srtp_octet_string_hex_string(buffer,
test_case->plaintext_length_octets));
srtp_octet_string_hex_string(
buffer, test_case->plaintext_length_octets));
/* compare the resulting plaintext with that in the test case */
if (len != test_case->plaintext_length_octets) {
@ -393,21 +411,21 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
return srtp_err_status_algo_fail;
}
status = srtp_err_status_ok;
for (i = 0; i < test_case->plaintext_length_octets; i++) {
if (buffer[i] != test_case->plaintext[i]) {
for (k = 0; k < test_case->plaintext_length_octets; k++) {
if (buffer[k] != test_case->plaintext[k]) {
status = srtp_err_status_algo_fail;
debug_print(srtp_mod_cipher, "test case %d failed", case_num);
debug_print(srtp_mod_cipher, "(failure at byte %d)", i);
debug_print(srtp_mod_cipher, "(failure at byte %u)", k);
}
}
if (status) {
debug_print(srtp_mod_cipher, "p computed: %s",
srtp_octet_string_hex_string(buffer,
2 * test_case->plaintext_length_octets));
srtp_octet_string_hex_string(
buffer, 2 * test_case->plaintext_length_octets));
debug_print(srtp_mod_cipher, "p expected: %s",
srtp_octet_string_hex_string(test_case->plaintext,
2 * test_case->plaintext_length_octets));
srtp_octet_string_hex_string(
test_case->plaintext,
2 * test_case->plaintext_length_octets));
srtp_cipher_dealloc(c);
return srtp_err_status_algo_fail;
@ -431,25 +449,22 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
/* allocate cipher, using paramaters from the first test case */
test_case = test_data;
status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets);
status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets,
test_case->tag_length_octets);
if (status) {
return status;
}
for (j = 0; j < NUM_RAND_TESTS; j++) {
unsigned length;
int plaintext_len;
unsigned int length;
unsigned int plaintext_len;
uint8_t key[MAX_KEY_LEN];
uint8_t iv[MAX_KEY_LEN];
/* choose a length at random (leaving room for IV and padding) */
length = rand() % (SELF_TEST_BUF_OCTETS - 64);
length = srtp_cipher_rand_u32_for_tests() % (SELF_TEST_BUF_OCTETS - 64);
debug_print(srtp_mod_cipher, "random plaintext length %d\n", length);
status = srtp_cipher_rand(buffer, length);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
srtp_cipher_rand_for_tests(buffer, length);
debug_print(srtp_mod_cipher, "plaintext: %s",
srtp_octet_string_hex_string(buffer, length));
@ -464,18 +479,10 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
srtp_cipher_dealloc(c);
return srtp_err_status_cant_check;
}
status = srtp_cipher_rand(key, test_case->key_length_octets);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
srtp_cipher_rand_for_tests(key, test_case->key_length_octets);
/* chose a random initialization vector */
status = srtp_cipher_rand(iv, MAX_KEY_LEN);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
srtp_cipher_rand_for_tests(iv, MAX_KEY_LEN);
/* initialize cipher */
status = srtp_cipher_init(c, key);
@ -485,24 +492,27 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
}
/* set initialization vector */
status = srtp_cipher_set_iv(c, (uint8_t*)test_case->idx, srtp_direction_encrypt);
status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
srtp_direction_encrypt);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) {
if (c->algorithm == SRTP_AES_GCM_128 ||
c->algorithm == SRTP_AES_GCM_256) {
/*
* Set the AAD
*/
status = srtp_cipher_set_aad(c, test_case->aad, test_case->aad_length_octets);
status = srtp_cipher_set_aad(c, test_case->aad,
test_case->aad_length_octets);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "AAD: %s",
srtp_octet_string_hex_string(test_case->aad,
test_case->aad_length_octets));
srtp_octet_string_hex_string(
test_case->aad, test_case->aad_length_octets));
}
/* encrypt buffer with cipher */
@ -512,7 +522,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
srtp_cipher_dealloc(c);
return status;
}
if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) {
if (c->algorithm == SRTP_AES_GCM_128 ||
c->algorithm == SRTP_AES_GCM_256) {
/*
* Get the GCM tag
*/
@ -535,23 +546,26 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
srtp_cipher_dealloc(c);
return status;
}
status = srtp_cipher_set_iv(c, (uint8_t*)test_case->idx, srtp_direction_decrypt);
status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx,
srtp_direction_decrypt);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) {
if (c->algorithm == SRTP_AES_GCM_128 ||
c->algorithm == SRTP_AES_GCM_256) {
/*
* Set the AAD
*/
status = srtp_cipher_set_aad(c, test_case->aad, test_case->aad_length_octets);
status = srtp_cipher_set_aad(c, test_case->aad,
test_case->aad_length_octets);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "AAD: %s",
srtp_octet_string_hex_string(test_case->aad,
test_case->aad_length_octets));
srtp_octet_string_hex_string(
test_case->aad, test_case->aad_length_octets));
}
status = srtp_cipher_decrypt(c, buffer, &length);
if (status) {
@ -568,18 +582,18 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
return srtp_err_status_algo_fail;
}
status = srtp_err_status_ok;
for (i = 0; i < plaintext_len; i++) {
if (buffer[i] != buffer2[i]) {
for (k = 0; k < plaintext_len; k++) {
if (buffer[k] != buffer2[k]) {
status = srtp_err_status_algo_fail;
debug_print(srtp_mod_cipher, "random test case %d failed", case_num);
debug_print(srtp_mod_cipher, "(failure at byte %d)", i);
debug_print(srtp_mod_cipher, "random test case %d failed",
case_num);
debug_print(srtp_mod_cipher, "(failure at byte %u)", k);
}
}
if (status) {
srtp_cipher_dealloc(c);
return srtp_err_status_algo_fail;
}
}
status = srtp_cipher_dealloc(c);
@ -590,12 +604,11 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt
return srtp_err_status_ok;
}
/*
* srtp_cipher_type_self_test(ct) performs srtp_cipher_type_test on ct's internal
* list of test data.
* srtp_cipher_type_self_test(ct) performs srtp_cipher_type_test on ct's
* internal list of test data.
*/
srtp_err_status_t srtp_cipher_type_self_test (const srtp_cipher_type_t *ct)
srtp_err_status_t srtp_cipher_type_self_test(const srtp_cipher_type_t *ct)
{
return srtp_cipher_type_test(ct, ct->test_data);
}
@ -610,31 +623,56 @@ srtp_err_status_t srtp_cipher_type_self_test (const srtp_cipher_type_t *ct)
*
* if an error is encountered, the value 0 is returned
*/
uint64_t srtp_cipher_bits_per_second (srtp_cipher_t *c, int octets_in_buffer, int num_trials)
uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c,
int octets_in_buffer,
int num_trials)
{
int i;
v128_t nonce;
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 */
}
/* time repeated trials */
v128_set_to_zero(&nonce);
timer = clock();
for (i = 0; i < num_trials; i++, nonce.v32[3] = i) {
if (srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt) != srtp_err_status_ok) {
// 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;

View File

@ -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 */
};

View File

@ -1,15 +1,6 @@
/*
* aes_icm.h
*
* Header for AES Integer Counter Mode.
*
* 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,20 +34,20 @@
*
*/
#ifndef AES_ICM_H
#define AES_ICM_H
#ifndef CHIPHER_TEST_CASES_H
#define CHIPHER_TEST_CASES_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "cipher.h"
#include "datatypes.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
typedef struct {
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
int key_size;
EVP_CIPHER_CTX* ctx;
} srtp_aes_icm_ctx_t;
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;
#endif /* AES_ICM_H */
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;
#endif

View File

@ -45,45 +45,43 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "datatypes.h"
#include "null_cipher.h"
#include "err.h" /* for srtp_debug */
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
/* the null_cipher uses the cipher debug module */
extern srtp_debug_module_t srtp_mod_cipher;
static srtp_err_status_t srtp_null_cipher_alloc (srtp_cipher_t **c, int key_len, int tlen)
static srtp_err_status_t srtp_null_cipher_alloc(srtp_cipher_t **c,
int key_len,
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);
debug_print(srtp_mod_cipher, "allocating cipher with key length %d",
key_len);
/* allocate memory a cipher of type null_cipher */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return srtp_err_status_alloc_fail;
}
memset(*c, 0x0, sizeof(srtp_cipher_t));
/* set pointers */
(*c)->algorithm = SRTP_NULL_CIPHER;
(*c)->type = &srtp_null_cipher;
(*c)->state = (void *) 0x1; /* The null cipher does not maintain state */
(*c)->state = (void *)0x1; /* The null cipher does not maintain state */
/* set key size */
(*c)->key_len = key_len;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_cipher_dealloc (srtp_cipher_t *c)
static srtp_err_status_t srtp_null_cipher_dealloc(srtp_cipher_t *c)
{
extern const srtp_cipher_type_t srtp_null_cipher;
@ -94,28 +92,37 @@ static srtp_err_status_t srtp_null_cipher_dealloc (srtp_cipher_t *c)
srtp_crypto_free(c);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_cipher_init (void *cv, const uint8_t *key)
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; */
debug_print(srtp_mod_cipher, "initializing null cipher", NULL);
/* 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;
}
static srtp_err_status_t srtp_null_cipher_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t dir)
static srtp_err_status_t srtp_null_cipher_set_iv(void *cv,
uint8_t *iv,
srtp_cipher_direction_t dir)
{
/* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */
/* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */
(void)cv;
(void)iv;
(void)dir;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_cipher_encrypt (void *cv,
unsigned char *buf, unsigned int *bytes_to_encr)
static srtp_err_status_t srtp_null_cipher_encrypt(void *cv,
unsigned char *buf,
unsigned int *bytes_to_encr)
{
/* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */
/* 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;
}
@ -129,28 +136,26 @@ static const srtp_cipher_test_case_t srtp_null_cipher_test_0 = {
NULL, /* plaintext */
0, /* octets in plaintext */
NULL, /* ciphertext */
0,
NULL,
0,
NULL /* pointer to next testcase */
0, /* */
NULL, /* */
0, /* */
NULL /* pointer to next testcase */
};
/*
* note: the decrypt function is idential to the encrypt function
*/
const srtp_cipher_type_t srtp_null_cipher = {
srtp_null_cipher_alloc,
srtp_null_cipher_dealloc,
srtp_null_cipher_init,
0, /* set_aad */
srtp_null_cipher_encrypt,
srtp_null_cipher_encrypt,
srtp_null_cipher_set_iv,
0, /* get_tag */
srtp_null_cipher_description,
&srtp_null_cipher_test_0,
SRTP_NULL_CIPHER
srtp_null_cipher_alloc, /* */
srtp_null_cipher_dealloc, /* */
srtp_null_cipher_init, /* */
0, /* set_aad */
srtp_null_cipher_encrypt, /* */
srtp_null_cipher_encrypt, /* */
srtp_null_cipher_set_iv, /* */
0, /* get_tag */
srtp_null_cipher_description, /* */
&srtp_null_cipher_test_0, /* */
SRTP_NULL_CIPHER /* */
};

View File

@ -44,32 +44,31 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "auth.h"
#include "err.h" /* for srtp_debug */
#include "datatypes.h" /* for octet_string */
#include "err.h" /* for srtp_debug */
#include "datatypes.h" /* for octet_string */
/* the debug module for authentiation */
srtp_debug_module_t srtp_mod_auth = {
0, /* debugging is off by default */
"auth func" /* printable name for module */
0, /* debugging is off by default */
"auth func" /* printable name for module */
};
int srtp_auth_get_key_length (const srtp_auth_t *a)
int srtp_auth_get_key_length(const srtp_auth_t *a)
{
return a->key_len;
}
int srtp_auth_get_tag_length (const srtp_auth_t *a)
int srtp_auth_get_tag_length(const srtp_auth_t *a)
{
return a->out_len;
}
int srtp_auth_get_prefix_length (const srtp_auth_t *a)
int srtp_auth_get_prefix_length(const srtp_auth_t *a)
{
return a->prefix_len;
}
@ -83,8 +82,8 @@ int srtp_auth_get_prefix_length (const srtp_auth_t *a)
/* should be big enough for most occasions */
#define SELF_TEST_TAG_BUF_OCTETS 32
srtp_err_status_t
srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *test_data)
srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at,
const srtp_auth_test_case_t *test_data)
{
const srtp_auth_test_case_t *test_case = test_data;
srtp_auth_t *a;
@ -105,7 +104,6 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te
/* loop over all test cases */
while (test_case != NULL) {
/* check test case parameters */
if (test_case->tag_length_octets > SELF_TEST_TAG_BUF_OCTETS) {
return srtp_err_status_bad_param;
@ -113,7 +111,7 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te
/* allocate auth */
status = srtp_auth_type_alloc(at, &a, test_case->key_length_octets,
test_case->tag_length_octets);
test_case->tag_length_octets);
if (status) {
return status;
}
@ -125,10 +123,16 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te
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,
test_case->data_length_octets, tag);
test_case->data_length_octets, tag);
if (status) {
srtp_auth_dealloc(a);
return status;
@ -138,10 +142,11 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te
srtp_octet_string_hex_string(test_case->key,
test_case->key_length_octets));
debug_print(srtp_mod_auth, "data: %s",
srtp_octet_string_hex_string(test_case->data,
test_case->data_length_octets));
debug_print(srtp_mod_auth, "tag computed: %s",
srtp_octet_string_hex_string(tag, test_case->tag_length_octets));
srtp_octet_string_hex_string(
test_case->data, test_case->data_length_octets));
debug_print(
srtp_mod_auth, "tag computed: %s",
srtp_octet_string_hex_string(tag, test_case->tag_length_octets));
debug_print(srtp_mod_auth, "tag expected: %s",
srtp_octet_string_hex_string(test_case->tag,
test_case->tag_length_octets));
@ -177,14 +182,12 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te
return srtp_err_status_ok;
}
/*
* auth_type_self_test(at) performs srtp_auth_type_test on at's internal
* srtp_auth_type_self_test(at) performs srtp_auth_type_test on at's internal
* list of test data.
*/
srtp_err_status_t srtp_auth_type_self_test (const srtp_auth_type_t *at)
srtp_err_status_t srtp_auth_type_self_test(const srtp_auth_type_t *at)
{
return srtp_auth_type_test(at, at->test_data);
}

View File

@ -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 */
};

View File

@ -1,33 +1,24 @@
/*
* 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
* 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
@ -43,25 +34,15 @@
*
*/
#ifndef AUTH_TEST_CASES_H
#define AUTH_TEST_CASES_H
#ifndef STAT_H
#define STAT_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 */

View File

@ -43,27 +43,32 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "hmac.h"
#include "alloc.h"
#include "cipher_types.h"
#include "auth_test_cases.h"
/* the debug module for authentiation */
srtp_debug_module_t srtp_mod_hmac = {
0, /* debugging is off by default */
"hmac sha-1" /* printable name for module */
0, /* debugging is off by default */
"hmac sha-1" /* printable name for module */
};
static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_len)
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;
uint8_t *pointer;
debug_print(srtp_mod_hmac, "allocating auth func with key length %d", key_len);
debug_print(srtp_mod_hmac, " tag length %d", out_len);
debug_print(srtp_mod_hmac, "allocating auth func with key length %d",
key_len);
debug_print(srtp_mod_hmac, " tag length %d",
out_len);
/*
* check key length - note that we don't support keys larger
@ -79,13 +84,14 @@ static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_
}
/* allocate memory for auth and srtp_hmac_ctx_t structures */
pointer = (uint8_t*)srtp_crypto_alloc(sizeof(srtp_hmac_ctx_t) + sizeof(srtp_auth_t));
pointer = (uint8_t *)srtp_crypto_alloc(sizeof(srtp_hmac_ctx_t) +
sizeof(srtp_auth_t));
if (pointer == NULL) {
return srtp_err_status_alloc_fail;
}
/* set pointers */
*a = (srtp_auth_t*)pointer;
*a = (srtp_auth_t *)pointer;
(*a)->type = &srtp_hmac;
(*a)->state = pointer + sizeof(srtp_auth_t);
(*a)->out_len = out_len;
@ -95,7 +101,7 @@ static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a)
static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a)
{
/* zeroize entire state*/
octet_string_set_to_zero(a, sizeof(srtp_hmac_ctx_t) + sizeof(srtp_auth_t));
@ -106,7 +112,9 @@ static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a)
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int key_len)
static srtp_err_status_t srtp_hmac_init(void *statev,
const uint8_t *key,
int key_len)
{
srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev;
int i;
@ -131,10 +139,11 @@ static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int k
/* set the rest of ipad, opad to constant values */
for (; i < 64; i++) {
ipad[i] = 0x36;
((uint8_t*)state->opad)[i] = 0x5c;
((uint8_t *)state->opad)[i] = 0x5c;
}
debug_print(srtp_mod_hmac, "ipad: %s", srtp_octet_string_hex_string(ipad, 64));
debug_print(srtp_mod_hmac, "ipad: %s",
srtp_octet_string_hex_string(ipad, 64));
/* initialize sha1 context */
srtp_sha1_init(&state->init_ctx);
@ -146,7 +155,7 @@ static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int k
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_start (void *statev)
static srtp_err_status_t srtp_hmac_start(void *statev)
{
srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev;
@ -155,7 +164,9 @@ static srtp_err_status_t srtp_hmac_start (void *statev)
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_update (void *statev, const uint8_t *message, int msg_octets)
static srtp_err_status_t srtp_hmac_update(void *statev,
const uint8_t *message,
int msg_octets)
{
srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev;
@ -168,8 +179,11 @@ static srtp_err_status_t srtp_hmac_update (void *statev, const uint8_t *message,
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message,
int msg_octets, int tag_len, uint8_t *result)
static srtp_err_status_t srtp_hmac_compute(void *statev,
const uint8_t *message,
int msg_octets,
int tag_len,
uint8_t *result)
{
srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev;
uint32_t hash_value[5];
@ -190,77 +204,46 @@ static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message
* function hmac_update() already did that for us
*/
debug_print(srtp_mod_hmac, "intermediate state: %s",
srtp_octet_string_hex_string((uint8_t*)H, 20));
srtp_octet_string_hex_string((uint8_t *)H, 20));
/* re-initialize hash context */
srtp_sha1_init(&state->ctx);
/* hash opad ^ key */
srtp_sha1_update(&state->ctx, (uint8_t*)state->opad, 64);
srtp_sha1_update(&state->ctx, (uint8_t *)state->opad, 64);
/* hash the result of the inner hash */
srtp_sha1_update(&state->ctx, (uint8_t*)H, 20);
srtp_sha1_update(&state->ctx, (uint8_t *)H, 20);
/* the result is returned in the array hash_value[] */
srtp_sha1_final(&state->ctx, hash_value);
/* copy hash_value to *result */
for (i = 0; i < tag_len; i++) {
result[i] = ((uint8_t*)hash_value)[i];
result[i] = ((uint8_t *)hash_value)[i];
}
debug_print(srtp_mod_hmac, "output: %s",
srtp_octet_string_hex_string((uint8_t*)hash_value, tag_len));
srtp_octet_string_hex_string((uint8_t *)hash_value, tag_len));
return srtp_err_status_ok;
}
/* begin test case 0 */
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
};
static const uint8_t srtp_hmac_test_case_0_data[8] = {
0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */
};
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
};
static const srtp_auth_test_case_t srtp_hmac_test_case_0 = {
20, /* octets in key */
srtp_hmac_test_case_0_key, /* key */
8, /* octets in data */
srtp_hmac_test_case_0_data, /* data */
20, /* 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";
static const char srtp_hmac_description[] =
"hmac sha-1 authentication function";
/*
* srtp_auth_type_t hmac is the hmac metaobject
*/
const srtp_auth_type_t srtp_hmac = {
srtp_hmac_alloc,
srtp_hmac_dealloc,
srtp_hmac_init,
srtp_hmac_compute,
srtp_hmac_update,
srtp_hmac_start,
srtp_hmac_description,
&srtp_hmac_test_case_0,
SRTP_HMAC_SHA1
const srtp_auth_type_t srtp_hmac = {
srtp_hmac_alloc, /* */
srtp_hmac_dealloc, /* */
srtp_hmac_init, /* */
srtp_hmac_compute, /* */
srtp_hmac_update, /* */
srtp_hmac_start, /* */
srtp_hmac_description, /* */
&srtp_hmac_test_case_0, /* */
SRTP_HMAC_SHA1 /* */
};

View File

@ -0,0 +1,217 @@
/*
* hmac_mbedtls.c
*
* Implementation of hmac srtp_auth_type_t that leverages Mbedtls
*
* YongCheng Yang
*/
/*
*
* Copyright(c) 2013-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 "auth.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "auth_test_cases.h"
#include <mbedtls/md.h>
#define SHA1_DIGEST_SIZE 20
/* the debug module for authentiation */
srtp_debug_module_t srtp_mod_hmac = {
0, /* debugging is off by default */
"hmac sha-1 mbedtls" /* printable name for module */
};
static srtp_err_status_t srtp_hmac_mbedtls_alloc(srtp_auth_t **a,
int key_len,
int out_len)
{
extern const srtp_auth_type_t srtp_hmac;
debug_print(srtp_mod_hmac, "allocating auth func with key length %d",
key_len);
debug_print(srtp_mod_hmac, " tag length %d",
out_len);
/* check output length - should be less than 20 bytes */
if (out_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
*a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t));
if (*a == NULL) {
return srtp_err_status_alloc_fail;
}
// allocate the buffer of mbedtls context.
(*a)->state = srtp_crypto_alloc(sizeof(mbedtls_md_context_t));
if ((*a)->state == NULL) {
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
mbedtls_md_init((mbedtls_md_context_t *)(*a)->state);
/* set pointers */
(*a)->type = &srtp_hmac;
(*a)->out_len = out_len;
(*a)->key_len = key_len;
(*a)->prefix_len = 0;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_dealloc(srtp_auth_t *a)
{
mbedtls_md_context_t *hmac_ctx;
hmac_ctx = (mbedtls_md_context_t *)a->state;
mbedtls_md_free(hmac_ctx);
srtp_crypto_free(hmac_ctx);
/* zeroize entire state*/
octet_string_set_to_zero(a, sizeof(srtp_auth_t));
/* free memory */
srtp_crypto_free(a);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_start(void *statev)
{
mbedtls_md_context_t *state = (mbedtls_md_context_t *)statev;
if (mbedtls_md_hmac_reset(state) != 0)
return srtp_err_status_auth_fail;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_init(void *statev,
const uint8_t *key,
int key_len)
{
mbedtls_md_context_t *state = (mbedtls_md_context_t *)statev;
const mbedtls_md_info_t *info = NULL;
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
if (info == NULL)
return srtp_err_status_auth_fail;
if (mbedtls_md_setup(state, info, 1) != 0)
return srtp_err_status_auth_fail;
debug_print(srtp_mod_hmac, "mbedtls setup, name: %s",
mbedtls_md_get_name(info));
debug_print(srtp_mod_hmac, "mbedtls setup, size: %d",
mbedtls_md_get_size(info));
if (mbedtls_md_hmac_starts(state, key, key_len) != 0)
return srtp_err_status_auth_fail;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_update(void *statev,
const uint8_t *message,
int msg_octets)
{
mbedtls_md_context_t *state = (mbedtls_md_context_t *)statev;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
if (mbedtls_md_hmac_update(state, message, msg_octets) != 0)
return srtp_err_status_auth_fail;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_compute(void *statev,
const uint8_t *message,
int msg_octets,
int tag_len,
uint8_t *result)
{
mbedtls_md_context_t *state = (mbedtls_md_context_t *)statev;
uint8_t hash_value[SHA1_DIGEST_SIZE];
int i;
/* check tag length, return error if we can't provide the value expected */
if (tag_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
/* hash message, copy output into H */
if (mbedtls_md_hmac_update(statev, message, msg_octets) != 0)
return srtp_err_status_auth_fail;
if (mbedtls_md_hmac_finish(state, hash_value) != 0)
return srtp_err_status_auth_fail;
/* copy hash_value to *result */
for (i = 0; i < tag_len; i++) {
result[i] = hash_value[i];
}
debug_print(srtp_mod_hmac, "output: %s",
srtp_octet_string_hex_string(hash_value, tag_len));
return srtp_err_status_ok;
}
/* end test case 0 */
static const char srtp_hmac_mbedtls_description[] =
"hmac sha-1 authentication function using mbedtls";
/*
* srtp_auth_type_t hmac is the hmac metaobject
*/
const srtp_auth_type_t srtp_hmac = {
srtp_hmac_mbedtls_alloc, /* */
srtp_hmac_mbedtls_dealloc, /* */
srtp_hmac_mbedtls_init, /* */
srtp_hmac_mbedtls_compute, /* */
srtp_hmac_mbedtls_update, /* */
srtp_hmac_mbedtls_start, /* */
srtp_hmac_mbedtls_description, /* */
&srtp_hmac_test_case_0, /* */
SRTP_HMAC_SHA1 /* */
};

290
third_party/srtp/crypto/hash/hmac_nss.c vendored Normal file
View File

@ -0,0 +1,290 @@
/*
*
* Copyright(c) 2013-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 "auth.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "auth_test_cases.h"
#define NSS_PKCS11_2_0_COMPAT 1
#include <nss.h>
#include <pk11pub.h>
#define SHA1_DIGEST_SIZE 20
/* the debug module for authentiation */
srtp_debug_module_t srtp_mod_hmac = {
0, /* debugging is off by default */
"hmac sha-1 nss" /* printable name for module */
};
typedef struct {
NSSInitContext *nss;
PK11SymKey *key;
PK11Context *ctx;
} srtp_hmac_nss_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_nss_ctx_t *hmac;
NSSInitContext *nss;
debug_print(srtp_mod_hmac, "allocating auth func with key length %d",
key_len);
debug_print(srtp_mod_hmac, " tag length %d",
out_len);
/* check output length - should be less than 20 bytes */
if (out_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
/* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
nss = NSS_InitContext("", "", "", "", NULL,
NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
NSS_INIT_OPTIMIZESPACE);
if (!nss) {
return srtp_err_status_auth_fail;
}
*a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t));
if (*a == NULL) {
NSS_ShutdownContext(nss);
return srtp_err_status_alloc_fail;
}
hmac =
(srtp_hmac_nss_ctx_t *)srtp_crypto_alloc(sizeof(srtp_hmac_nss_ctx_t));
if (hmac == NULL) {
NSS_ShutdownContext(nss);
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
hmac->nss = nss;
hmac->key = NULL;
hmac->ctx = NULL;
/* set pointers */
(*a)->state = hmac;
(*a)->type = &srtp_hmac;
(*a)->out_len = out_len;
(*a)->key_len = key_len;
(*a)->prefix_len = 0;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)a->state;
if (hmac) {
/* free any PK11 values that have been created */
if (hmac->key) {
PK11_FreeSymKey(hmac->key);
hmac->key = NULL;
}
if (hmac->ctx) {
PK11_DestroyContext(hmac->ctx, PR_TRUE);
hmac->ctx = NULL;
}
if (hmac->nss) {
NSS_ShutdownContext(hmac->nss);
hmac->nss = NULL;
}
/* zeroize everything */
octet_string_set_to_zero(hmac, sizeof(srtp_hmac_nss_ctx_t));
srtp_crypto_free(hmac);
}
/* free memory */
srtp_crypto_free(a);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_start(void *statev)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)statev;
if (PK11_DigestBegin(hmac->ctx) != SECSuccess) {
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_init(void *statev,
const uint8_t *key,
int key_len)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)statev;
PK11SymKey *sym_key;
PK11Context *ctx;
if (hmac->ctx) {
PK11_DestroyContext(hmac->ctx, PR_TRUE);
hmac->ctx = NULL;
}
if (hmac->key) {
PK11_FreeSymKey(hmac->key);
hmac->key = NULL;
}
PK11SlotInfo *slot = PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL);
if (!slot) {
return srtp_err_status_bad_param;
}
SECItem key_item = { siBuffer, (unsigned char *)key, key_len };
sym_key = PK11_ImportSymKey(slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap,
CKA_SIGN, &key_item, NULL);
PK11_FreeSlot(slot);
if (!sym_key) {
return srtp_err_status_auth_fail;
}
SECItem param_item = { siBuffer, NULL, 0 };
ctx = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, sym_key,
&param_item);
if (!ctx) {
PK11_FreeSymKey(sym_key);
return srtp_err_status_auth_fail;
}
hmac->key = sym_key;
hmac->ctx = ctx;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_update(void *statev,
const uint8_t *message,
int msg_octets)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)statev;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
if (PK11_DigestOp(hmac->ctx, message, msg_octets) != SECSuccess) {
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_compute(void *statev,
const uint8_t *message,
int msg_octets,
int tag_len,
uint8_t *result)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)statev;
uint8_t hash_value[SHA1_DIGEST_SIZE];
int i;
unsigned int len;
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) {
return srtp_err_status_bad_param;
}
if (PK11_DigestOp(hmac->ctx, message, msg_octets) != SECSuccess) {
return srtp_err_status_auth_fail;
}
if (PK11_DigestFinal(hmac->ctx, hash_value, &len, SHA1_DIGEST_SIZE) !=
SECSuccess) {
return srtp_err_status_auth_fail;
}
if (tag_len < 0 || len < (unsigned int)tag_len)
return srtp_err_status_auth_fail;
/* copy hash_value to *result */
for (i = 0; i < tag_len; i++) {
result[i] = hash_value[i];
}
debug_print(srtp_mod_hmac, "output: %s",
srtp_octet_string_hex_string(hash_value, tag_len));
return srtp_err_status_ok;
}
static const char srtp_hmac_description[] =
"hmac sha-1 authentication function";
/*
* srtp_auth_type_t hmac is the hmac metaobject
*/
const srtp_auth_type_t srtp_hmac = {
srtp_hmac_alloc, /* */
srtp_hmac_dealloc, /* */
srtp_hmac_init, /* */
srtp_hmac_compute, /* */
srtp_hmac_update, /* */
srtp_hmac_start, /* */
srtp_hmac_description, /* */
&srtp_hmac_test_case_0, /* */
SRTP_HMAC_SHA1 /* */
};

View File

@ -43,70 +43,119 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "auth.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#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>
#include <openssl/opensslv.h>
#endif
#define SHA1_DIGEST_SIZE 20
#if defined(LIBRESSL_VERSION_NUMBER)
# define USING_LIBRESSL 1
#else
# define USING_LIBRESSL 0
#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 */
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.
*/
static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_len)
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);
debug_print(srtp_mod_hmac, " tag length %d", out_len);
debug_print(srtp_mod_hmac, "allocating auth func with key length %d",
key_len);
debug_print(srtp_mod_hmac, " tag length %d",
out_len);
/* check output length - should be less than 20 bytes */
if (out_len > SHA1_DIGEST_SIZE) {
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 USING_LIBRESSL || OPENSSL_VERSION_NUMBER < 0x10100000L
{
/* 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));
*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;
@ -114,6 +163,7 @@ static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_
#endif
/* set pointers */
(*a)->state = hmac;
(*a)->type = &srtp_hmac;
(*a)->out_len = out_len;
(*a)->key_len = key_len;
@ -122,24 +172,26 @@ static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a)
static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a)
{
HMAC_CTX *hmac_ctx;
hmac_ctx = (HMAC_CTX*)a->state;
#if USING_LIBRESSL || OPENSSL_VERSION_NUMBER < 0x10100000L
HMAC_CTX_cleanup(hmac_ctx);
/* zeroize entire state*/
octet_string_set_to_zero(a, sizeof(HMAC_CTX) + sizeof(srtp_auth_t));
srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)a->state;
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);
@ -147,46 +199,89 @@ static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a)
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_start (void *statev)
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;
}
static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int key_len)
static srtp_err_status_t srtp_hmac_init(void *statev,
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;
}
static srtp_err_status_t srtp_hmac_update (void *statev, const uint8_t *message, int msg_octets)
static srtp_err_status_t srtp_hmac_update(void *statev,
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;
}
static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message,
int msg_octets, int tag_len, uint8_t *result)
static srtp_err_status_t srtp_hmac_compute(void *statev,
const uint8_t *message,
int msg_octets,
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) {
@ -194,13 +289,22 @@ static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message
}
/* 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 */
@ -214,52 +318,21 @@ static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message
return srtp_err_status_ok;
}
/* begin test case 0 */
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
};
static const uint8_t srtp_hmac_test_case_0_data[8] = {
0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */
};
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
};
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";
static const char srtp_hmac_description[] =
"hmac sha-1 authentication function";
/*
* srtp_auth_type_t hmac is the hmac metaobject
*/
const srtp_auth_type_t srtp_hmac = {
srtp_hmac_alloc,
srtp_hmac_dealloc,
srtp_hmac_init,
srtp_hmac_compute,
srtp_hmac_update,
srtp_hmac_start,
srtp_hmac_description,
&srtp_hmac_test_case_0,
SRTP_HMAC_SHA1
const srtp_auth_type_t srtp_hmac = {
srtp_hmac_alloc, /* */
srtp_hmac_dealloc, /* */
srtp_hmac_init, /* */
srtp_hmac_compute, /* */
srtp_hmac_update, /* */
srtp_hmac_start, /* */
srtp_hmac_description, /* */
&srtp_hmac_test_case_0, /* */
SRTP_HMAC_SHA1 /* */
};

View File

@ -45,33 +45,35 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "null_auth.h"
#include "err.h" /* for srtp_debug */
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
/* null_auth uses the auth debug module */
extern srtp_debug_module_t srtp_mod_auth;
static srtp_err_status_t srtp_null_auth_alloc (srtp_auth_t **a, int key_len, int out_len)
static srtp_err_status_t srtp_null_auth_alloc(srtp_auth_t **a,
int key_len,
int out_len)
{
extern const srtp_auth_type_t srtp_null_auth;
uint8_t *pointer;
debug_print(srtp_mod_auth, "allocating auth func with key length %d", key_len);
debug_print(srtp_mod_auth, " tag length %d", out_len);
debug_print(srtp_mod_auth, "allocating auth func with key length %d",
key_len);
debug_print(srtp_mod_auth, " tag length %d",
out_len);
/* allocate memory for auth and srtp_null_auth_ctx_t structures */
pointer = (uint8_t*)srtp_crypto_alloc(sizeof(srtp_null_auth_ctx_t) + sizeof(srtp_auth_t));
pointer = (uint8_t *)srtp_crypto_alloc(sizeof(srtp_null_auth_ctx_t) +
sizeof(srtp_auth_t));
if (pointer == NULL) {
return srtp_err_status_alloc_fail;
}
/* set pointers */
*a = (srtp_auth_t*)pointer;
*a = (srtp_auth_t *)pointer;
(*a)->type = &srtp_null_auth;
(*a)->state = pointer + sizeof(srtp_auth_t);
(*a)->out_len = out_len;
@ -81,12 +83,13 @@ static srtp_err_status_t srtp_null_auth_alloc (srtp_auth_t **a, int key_len, int
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_auth_dealloc (srtp_auth_t *a)
static srtp_err_status_t srtp_null_auth_dealloc(srtp_auth_t *a)
{
extern const srtp_auth_type_t srtp_null_auth;
/* zeroize entire state*/
octet_string_set_to_zero(a, sizeof(srtp_null_auth_ctx_t) + sizeof(srtp_auth_t));
octet_string_set_to_zero(a, sizeof(srtp_null_auth_ctx_t) +
sizeof(srtp_auth_t));
/* free memory */
srtp_crypto_free(a);
@ -94,33 +97,52 @@ static srtp_err_status_t srtp_null_auth_dealloc (srtp_auth_t *a)
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_auth_init (void *statev, const uint8_t *key, int key_len)
static srtp_err_status_t srtp_null_auth_init(void *statev,
const uint8_t *key,
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;
}
static srtp_err_status_t srtp_null_auth_compute (void *statev, const uint8_t *message,
int msg_octets, int tag_len, uint8_t *result)
static srtp_err_status_t srtp_null_auth_compute(void *statev,
const uint8_t *message,
int msg_octets,
int tag_len,
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;
}
static srtp_err_status_t srtp_null_auth_update (void *statev, const uint8_t *message,
int msg_octets)
static srtp_err_status_t srtp_null_auth_update(void *statev,
const uint8_t *message,
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;
}
static srtp_err_status_t srtp_null_auth_start (void *statev)
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;
}
@ -133,28 +155,27 @@ static srtp_err_status_t srtp_null_auth_start (void *statev)
/* begin test case 0 */
static const srtp_auth_test_case_t srtp_null_auth_test_case_0 = {
0, /* octets in key */
NULL, /* key */
0, /* octets in data */
NULL, /* data */
0, /* octets in tag */
NULL, /* tag */
NULL /* pointer to next testcase */
0, /* octets in key */
NULL, /* key */
0, /* octets in data */
NULL, /* data */
0, /* octets in tag */
NULL, /* tag */
NULL /* pointer to next testcase */
};
/* end test case 0 */
static const char srtp_null_auth_description[] = "null authentication function";
const srtp_auth_type_t srtp_null_auth = {
srtp_null_auth_alloc,
srtp_null_auth_dealloc,
srtp_null_auth_init,
srtp_null_auth_compute,
srtp_null_auth_update,
srtp_null_auth_start,
srtp_null_auth_description,
&srtp_null_auth_test_case_0,
SRTP_NULL_AUTH
const srtp_auth_type_t srtp_null_auth = {
srtp_null_auth_alloc, /* */
srtp_null_auth_dealloc, /* */
srtp_null_auth_init, /* */
srtp_null_auth_compute, /* */
srtp_null_auth_update, /* */
srtp_null_auth_start, /* */
srtp_null_auth_description, /* */
&srtp_null_auth_test_case_0, /* */
SRTP_NULL_AUTH /* */
};

View File

@ -45,19 +45,19 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "sha1.h"
srtp_debug_module_t srtp_mod_sha1 = {
0, /* debugging is off by default */
"sha-1" /* printable module name */
0, /* debugging is off by default */
"sha-1" /* printable module name */
};
/* SN == Rotate left N bits */
#define S1(X) ((X << 1) | (X >> 31))
#define S5(X) ((X << 5) | (X >> 27))
#define S1(X) ((X << 1) | (X >> 31))
#define S5(X) ((X << 5) | (X >> 27))
#define S30(X) ((X << 30) | (X >> 2))
#define f0(B, C, D) ((B & C) | (~B & D))
@ -71,20 +71,10 @@ srtp_debug_module_t srtp_mod_sha1 = {
* on systems that uses curses
*/
uint32_t SHA_K0 = 0x5A827999; /* Kt for 0 <= t <= 19 */
uint32_t SHA_K1 = 0x6ED9EBA1; /* Kt for 20 <= t <= 39 */
uint32_t SHA_K2 = 0x8F1BBCDC; /* Kt for 40 <= t <= 59 */
uint32_t SHA_K3 = 0xCA62C1D6; /* Kt for 60 <= t <= 79 */
void srtp_sha1 (const uint8_t *msg, int octets_in_msg, uint32_t hash_value[5])
{
srtp_sha1_ctx_t ctx;
srtp_sha1_init(&ctx);
srtp_sha1_update(&ctx, msg, octets_in_msg);
srtp_sha1_final(&ctx, hash_value);
}
uint32_t SHA_K0 = 0x5A827999; /* Kt for 0 <= t <= 19 */
uint32_t SHA_K1 = 0x6ED9EBA1; /* Kt for 20 <= t <= 39 */
uint32_t SHA_K2 = 0x8F1BBCDC; /* Kt for 40 <= t <= 59 */
uint32_t SHA_K3 = 0xCA62C1D6; /* Kt for 60 <= t <= 79 */
/*
* srtp_sha1_core(M, H) computes the core compression function, where M is
@ -98,7 +88,7 @@ void srtp_sha1 (const uint8_t *msg, int octets_in_msg, uint32_t hash_value[5])
* (crypto/cipher/seal.c)
*/
void srtp_sha1_core (const uint32_t M[16], uint32_t hash_value[5])
void srtp_sha1_core(const uint32_t M[16], uint32_t hash_value[5])
{
uint32_t H0;
uint32_t H1;
@ -118,38 +108,54 @@ void srtp_sha1_core (const uint32_t M[16], uint32_t hash_value[5])
/* copy/xor message into array */
W[0] = be32_to_cpu(M[0]);
W[1] = be32_to_cpu(M[1]);
W[2] = be32_to_cpu(M[2]);
W[3] = be32_to_cpu(M[3]);
W[4] = be32_to_cpu(M[4]);
W[5] = be32_to_cpu(M[5]);
W[6] = be32_to_cpu(M[6]);
W[7] = be32_to_cpu(M[7]);
W[8] = be32_to_cpu(M[8]);
W[9] = be32_to_cpu(M[9]);
W[0] = be32_to_cpu(M[0]);
W[1] = be32_to_cpu(M[1]);
W[2] = be32_to_cpu(M[2]);
W[3] = be32_to_cpu(M[3]);
W[4] = be32_to_cpu(M[4]);
W[5] = be32_to_cpu(M[5]);
W[6] = be32_to_cpu(M[6]);
W[7] = be32_to_cpu(M[7]);
W[8] = be32_to_cpu(M[8]);
W[9] = be32_to_cpu(M[9]);
W[10] = be32_to_cpu(M[10]);
W[11] = be32_to_cpu(M[11]);
W[12] = be32_to_cpu(M[12]);
W[13] = be32_to_cpu(M[13]);
W[14] = be32_to_cpu(M[14]);
W[15] = be32_to_cpu(M[15]);
TEMP = W[13] ^ W[8] ^ W[2] ^ W[0]; W[16] = S1(TEMP);
TEMP = W[14] ^ W[9] ^ W[3] ^ W[1]; W[17] = S1(TEMP);
TEMP = W[15] ^ W[10] ^ W[4] ^ W[2]; W[18] = S1(TEMP);
TEMP = W[16] ^ W[11] ^ W[5] ^ W[3]; W[19] = S1(TEMP);
TEMP = W[17] ^ W[12] ^ W[6] ^ W[4]; W[20] = S1(TEMP);
TEMP = W[18] ^ W[13] ^ W[7] ^ W[5]; W[21] = S1(TEMP);
TEMP = W[19] ^ W[14] ^ W[8] ^ W[6]; W[22] = S1(TEMP);
TEMP = W[20] ^ W[15] ^ W[9] ^ W[7]; W[23] = S1(TEMP);
TEMP = W[21] ^ W[16] ^ W[10] ^ W[8]; W[24] = S1(TEMP);
TEMP = W[22] ^ W[17] ^ W[11] ^ W[9]; W[25] = S1(TEMP);
TEMP = W[23] ^ W[18] ^ W[12] ^ W[10]; W[26] = S1(TEMP);
TEMP = W[24] ^ W[19] ^ W[13] ^ W[11]; W[27] = S1(TEMP);
TEMP = W[25] ^ W[20] ^ W[14] ^ W[12]; W[28] = S1(TEMP);
TEMP = W[26] ^ W[21] ^ W[15] ^ W[13]; W[29] = S1(TEMP);
TEMP = W[27] ^ W[22] ^ W[16] ^ W[14]; W[30] = S1(TEMP);
TEMP = W[28] ^ W[23] ^ W[17] ^ W[15]; W[31] = S1(TEMP);
TEMP = W[13] ^ W[8] ^ W[2] ^ W[0];
W[16] = S1(TEMP);
TEMP = W[14] ^ W[9] ^ W[3] ^ W[1];
W[17] = S1(TEMP);
TEMP = W[15] ^ W[10] ^ W[4] ^ W[2];
W[18] = S1(TEMP);
TEMP = W[16] ^ W[11] ^ W[5] ^ W[3];
W[19] = S1(TEMP);
TEMP = W[17] ^ W[12] ^ W[6] ^ W[4];
W[20] = S1(TEMP);
TEMP = W[18] ^ W[13] ^ W[7] ^ W[5];
W[21] = S1(TEMP);
TEMP = W[19] ^ W[14] ^ W[8] ^ W[6];
W[22] = S1(TEMP);
TEMP = W[20] ^ W[15] ^ W[9] ^ W[7];
W[23] = S1(TEMP);
TEMP = W[21] ^ W[16] ^ W[10] ^ W[8];
W[24] = S1(TEMP);
TEMP = W[22] ^ W[17] ^ W[11] ^ W[9];
W[25] = S1(TEMP);
TEMP = W[23] ^ W[18] ^ W[12] ^ W[10];
W[26] = S1(TEMP);
TEMP = W[24] ^ W[19] ^ W[13] ^ W[11];
W[27] = S1(TEMP);
TEMP = W[25] ^ W[20] ^ W[14] ^ W[12];
W[28] = S1(TEMP);
TEMP = W[26] ^ W[21] ^ W[15] ^ W[13];
W[29] = S1(TEMP);
TEMP = W[27] ^ W[22] ^ W[16] ^ W[14];
W[30] = S1(TEMP);
TEMP = W[28] ^ W[23] ^ W[17] ^ W[15];
W[31] = S1(TEMP);
/* process the remainder of the array */
for (t = 32; t < 80; t++) {
@ -157,23 +163,43 @@ void srtp_sha1_core (const uint32_t M[16], uint32_t hash_value[5])
W[t] = S1(TEMP);
}
A = H0; B = H1; C = H2; D = H3; E = H4;
A = H0;
B = H1;
C = H2;
D = H3;
E = H4;
for (t = 0; t < 20; t++) {
TEMP = S5(A) + f0(B, C, D) + E + W[t] + SHA_K0;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 40; t++) {
TEMP = S5(A) + f1(B, C, D) + E + W[t] + SHA_K1;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 60; t++) {
TEMP = S5(A) + f2(B, C, D) + E + W[t] + SHA_K2;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 80; t++) {
TEMP = S5(A) + f3(B, C, D) + E + W[t] + SHA_K3;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
hash_value[0] = H0 + A;
@ -185,9 +211,8 @@ void srtp_sha1_core (const uint32_t M[16], uint32_t hash_value[5])
return;
}
void srtp_sha1_init (srtp_sha1_ctx_t *ctx)
void srtp_sha1_init(srtp_sha1_ctx_t *ctx)
{
/* initialize state vector */
ctx->H[0] = 0x67452301;
ctx->H[1] = 0xefcdab89;
@ -200,22 +225,21 @@ void srtp_sha1_init (srtp_sha1_ctx_t *ctx)
/* reset message bit-count to zero */
ctx->num_bits_in_msg = 0;
}
void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_msg)
void srtp_sha1_update(srtp_sha1_ctx_t *ctx,
const uint8_t *msg,
int octets_in_msg)
{
int i;
uint8_t *buf = (uint8_t*)ctx->M;
uint8_t *buf = (uint8_t *)ctx->M;
/* update message bit-count */
ctx->num_bits_in_msg += octets_in_msg * 8;
/* loop over 16-word blocks of M */
while (octets_in_msg > 0) {
if (octets_in_msg + ctx->octets_in_buffer >= 64) {
/*
* copy words of M into msg buffer until that buffer is full,
* converting them into host byte order as needed
@ -228,13 +252,13 @@ void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_m
/* process a whole block */
debug_print(srtp_mod_sha1, "(update) running srtp_sha1_core()", NULL);
debug_print0(srtp_mod_sha1, "(update) running srtp_sha1_core()");
srtp_sha1_core(ctx->M, ctx->H);
} else {
debug_print(srtp_mod_sha1, "(update) not running srtp_sha1_core()", NULL);
debug_print0(srtp_mod_sha1,
"(update) not running srtp_sha1_core()");
for (i = ctx->octets_in_buffer;
i < (ctx->octets_in_buffer + octets_in_msg); i++) {
@ -243,9 +267,7 @@ void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_m
ctx->octets_in_buffer += octets_in_msg;
octets_in_msg = 0;
}
}
}
/*
@ -253,7 +275,7 @@ void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_m
* into the twenty octets located at *output
*/
void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output)
void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t output[5])
{
uint32_t A, B, C, D, E, TEMP;
uint32_t W[80];
@ -268,7 +290,7 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output)
/* copy/xor message into array */
for (i = 0; i < (ctx->octets_in_buffer + 3) / 4; i++) {
W[i] = be32_to_cpu(ctx->M[i]);
W[i] = be32_to_cpu(ctx->M[i]);
}
/* set the high bit of the octet immediately following the message */
@ -321,19 +343,35 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output)
for (t = 0; t < 20; t++) {
TEMP = S5(A) + f0(B, C, D) + E + W[t] + SHA_K0;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 40; t++) {
TEMP = S5(A) + f1(B, C, D) + E + W[t] + SHA_K1;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 60; t++) {
TEMP = S5(A) + f2(B, C, D) + E + W[t] + SHA_K2;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 80; t++) {
TEMP = S5(A) + f3(B, C, D) + E + W[t] + SHA_K3;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
ctx->H[0] += A;
@ -341,14 +379,12 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output)
ctx->H[2] += C;
ctx->H[3] += D;
ctx->H[4] += E;
}
debug_print(srtp_mod_sha1, "(final) running srtp_sha1_core()", NULL);
debug_print0(srtp_mod_sha1, "(final) running srtp_sha1_core()");
if (ctx->octets_in_buffer >= 56) {
debug_print(srtp_mod_sha1, "(final) running srtp_sha1_core() again", NULL);
debug_print0(srtp_mod_sha1, "(final) running srtp_sha1_core() again");
/* we need to do one final run of the compression algo */
@ -375,19 +411,35 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output)
for (t = 0; t < 20; t++) {
TEMP = S5(A) + f0(B, C, D) + E + W[t] + SHA_K0;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 40; t++) {
TEMP = S5(A) + f1(B, C, D) + E + W[t] + SHA_K1;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 60; t++) {
TEMP = S5(A) + f2(B, C, D) + E + W[t] + SHA_K2;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
for (; t < 80; t++) {
TEMP = S5(A) + f3(B, C, D) + E + W[t] + SHA_K3;
E = D; D = C; C = S30(B); B = A; A = TEMP;
E = D;
D = C;
C = S30(B);
B = A;
A = TEMP;
}
ctx->H[0] += A;
@ -409,6 +461,3 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output)
return;
}

View File

@ -70,9 +70,11 @@ srtp_err_status_t srtp_aes_expand_decryption_key(
int key_len,
srtp_aes_expanded_key_t *expanded_key);
void srtp_aes_encrypt(v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key);
void srtp_aes_encrypt(v128_t *plaintext,
const srtp_aes_expanded_key_t *exp_key);
void srtp_aes_decrypt(v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key);
void srtp_aes_decrypt(v128_t *plaintext,
const srtp_aes_expanded_key_t *exp_key);
#ifdef __cplusplus
}

View File

@ -1,34 +1,33 @@
/*
* ut_sim.c
* aes_gcm.h
*
* an unreliable transport simulator
* (for testing replay databases and suchlike)
*
* David A. McGrew
* Header for AES Galois Counter Mode.
*
* John A. Foley
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
*
* Copyright (c) 2013-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
@ -44,66 +43,68 @@
*
*/
#ifndef AES_GCM_H
#define AES_GCM_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "cipher.h"
#include "srtp.h"
#include "datatypes.h"
#include "ut_sim.h"
#ifdef OPENSSL
#include <openssl/evp.h>
#include <openssl/aes.h>
int
ut_compar(const void *a, const void *b) {
return rand() > (RAND_MAX/2) ? -1 : 1;
}
typedef struct {
int key_size;
int tag_len;
EVP_CIPHER_CTX *ctx;
srtp_cipher_direction_t dir;
} srtp_aes_gcm_ctx_t;
void
ut_init(ut_connection *utc) {
int i;
utc->index = 0;
#endif /* OPENSSL */
for (i=0; i < UT_BUF; i++)
utc->buffer[i] = i;
qsort(utc->buffer, UT_BUF, sizeof(uint32_t), ut_compar);
#ifdef MBEDTLS
#define MAX_AD_SIZE 2048
#include <mbedtls/aes.h>
#include <mbedtls/gcm.h>
utc->index = UT_BUF - 1;
}
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;
uint32_t
ut_next_index(ut_connection *utc) {
uint32_t tmp;
#endif /* MBEDTLS */
tmp = utc->buffer[0];
utc->index++;
utc->buffer[0] = utc->index;
#ifdef NSS
qsort(utc->buffer, UT_BUF, sizeof(uint32_t), ut_compar);
return tmp;
}
#define NSS_PKCS11_2_0_COMPAT 1
#include <nss.h>
#include <pk11pub.h>
#define MAX_AD_SIZE 2048
#ifdef UT_TEST
typedef struct {
int key_size;
int tag_size;
srtp_cipher_direction_t dir;
NSSInitContext *nss;
PK11SymKey *key;
uint8_t iv[12];
uint8_t aad[MAX_AD_SIZE];
int aad_size;
CK_GCM_PARAMS params;
uint8_t tag[16];
} srtp_aes_gcm_ctx_t;
#include <stdio.h>
#endif /* NSS */
int
main() {
uint32_t i, irecvd, idiff;
ut_connection utc;
ut_init(&utc);
for (i=0; i < 1000; i++) {
irecvd = ut_next_index(&utc);
idiff = i - irecvd;
printf("%lu\t%lu\t%d\n", i, irecvd, idiff);
}
return 0;
}
#endif
#endif /* AES_GCM_H */

View File

@ -9,26 +9,26 @@
*/
/*
*
*
* 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
@ -60,4 +60,3 @@ typedef struct {
} srtp_aes_icm_ctx_t;
#endif /* AES_ICM_H */

View File

@ -1,34 +1,33 @@
/*
* ut-sim.h
* aes_icm.h
*
* an unreliable transport simulator
* (for testing replay databases and suchlike)
* Header for AES Integer Counter Mode.
*
* 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
@ -44,44 +43,57 @@
*
*/
#ifndef AES_ICM_H
#define AES_ICM_H
#include "cipher.h"
#include "datatypes.h"
#ifndef UT_SIM_H
#define UT_SIM_H
#ifdef OPENSSL
#include "integers.h" /* for uint32_t */
#ifdef __cplusplus
extern "C" {
#endif
#define UT_BUF 160 /* maximum amount of packet reorder */
#include <openssl/evp.h>
#include <openssl/aes.h>
typedef struct {
uint32_t index;
uint32_t buffer[UT_BUF];
} ut_connection;
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
int key_size;
EVP_CIPHER_CTX *ctx;
} srtp_aes_icm_ctx_t;
/*
* ut_init(&u) initializes the ut_connection
*
* this function should always be the first one called on a new
* ut_connection
*/
#endif /* OPENSSL */
void
ut_init(ut_connection *utc);
#ifdef MBEDTLS
/*
* ut_next_index(&u) returns the next index from the simulated
* unreliable connection
*/
#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;
uint32_t
ut_next_index(ut_connection *utc);
#endif /* MBEDTLS */
#ifdef __cplusplus
}
#endif
#ifdef NSS
#endif /* UT_SIM_H */
#define NSS_PKCS11_2_0_COMPAT 1
#include <nss.h>
#include <pk11pub.h>
typedef struct {
v128_t counter;
v128_t offset;
int key_size;
uint8_t iv[16];
NSSInitContext *nss;
PK11SymKey *key;
PK11Context *ctx;
} srtp_aes_icm_ctx_t;
#endif /* NSS */
#endif /* AES_ICM_H */

View File

@ -1,32 +1,32 @@
/*
* alloc.h
*
* interface to memory allocation and deallocation, with optional debugging
* interface to memory allocation and deallocation, with optional debugging
*
* 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
@ -42,7 +42,6 @@
*
*/
#ifndef CRYPTO_ALLOC_H
#define CRYPTO_ALLOC_H
@ -52,8 +51,22 @@
extern "C" {
#endif
void * srtp_crypto_alloc(size_t size);
/*
* srtp_crypto_alloc
*
* Allocates a block of memory of given size. The memory will be
* initialized to zero's. Free the memory with a call to srtp_crypto_free.
*
* returns pointer to memory on success or else NULL
*/
void *srtp_crypto_alloc(size_t size);
/*
* srtp_crypto_free
*
* Frees the block of memory ptr previously allocated with
* srtp_crypto_alloc
*/
void srtp_crypto_free(void *ptr);
#ifdef __cplusplus

View File

@ -47,46 +47,51 @@
#define SRTP_AUTH_H
#include "srtp.h"
#include "crypto_types.h" /* for values of auth_type_id_t */
#include "crypto_types.h" /* for values of auth_type_id_t */
#ifdef __cplusplus
extern "C" {
#endif
typedef const struct srtp_auth_type_t *srtp_auth_type_pointer;
typedef struct srtp_auth_t *srtp_auth_pointer_t;
typedef struct srtp_auth_t *srtp_auth_pointer_t;
typedef srtp_err_status_t (*srtp_auth_alloc_func)
(srtp_auth_pointer_t *ap, int key_len, int out_len);
typedef srtp_err_status_t (*srtp_auth_alloc_func)(srtp_auth_pointer_t *ap,
int key_len,
int out_len);
typedef srtp_err_status_t (*srtp_auth_init_func)
(void *state, const uint8_t *key, int key_len);
typedef srtp_err_status_t (*srtp_auth_init_func)(void *state,
const uint8_t *key,
int key_len);
typedef srtp_err_status_t (*srtp_auth_dealloc_func)(srtp_auth_pointer_t ap);
typedef srtp_err_status_t (*srtp_auth_compute_func)
(void *state, const uint8_t *buffer, int octets_to_auth,
int tag_len, uint8_t *tag);
typedef srtp_err_status_t (*srtp_auth_compute_func)(void *state,
const uint8_t *buffer,
int octets_to_auth,
int tag_len,
uint8_t *tag);
typedef srtp_err_status_t (*srtp_auth_update_func)
(void *state, const uint8_t *buffer, int octets_to_auth);
typedef srtp_err_status_t (*srtp_auth_update_func)(void *state,
const uint8_t *buffer,
int octets_to_auth);
typedef srtp_err_status_t (*srtp_auth_start_func)(void *state);
/* some syntactic sugar on these function types */
#define srtp_auth_type_alloc(at, a, klen, outlen) \
#define srtp_auth_type_alloc(at, a, klen, outlen) \
((at)->alloc((a), (klen), (outlen)))
#define srtp_auth_init(a, key) \
#define srtp_auth_init(a, key) \
(((a)->type)->init((a)->state, (key), ((a)->key_len)))
#define srtp_auth_compute(a, buf, len, res) \
#define srtp_auth_compute(a, buf, len, res) \
(((a)->type)->compute((a)->state, (buf), (len), (a)->out_len, (res)))
#define srtp_auth_update(a, buf, len) \
#define srtp_auth_update(a, buf, len) \
(((a)->type)->update((a)->state, (buf), (len)))
#define srtp_auth_start(a)(((a)->type)->start((a)->state))
#define srtp_auth_start(a) (((a)->type)->start((a)->state))
#define srtp_auth_dealloc(c) (((c)->type)->dealloc(c))
@ -105,13 +110,14 @@ int srtp_auth_get_prefix_length(const struct srtp_auth_t *a);
* function below)
*/
typedef struct srtp_auth_test_case_t {
int key_length_octets; /* octets in key */
const uint8_t *key; /* key */
int data_length_octets; /* octets in data */
const uint8_t *data; /* data */
int tag_length_octets; /* octets in tag */
const uint8_t *tag; /* tag */
const struct srtp_auth_test_case_t *next_test_case; /* pointer to next testcase */
int key_length_octets; /* octets in key */
const uint8_t *key; /* key */
int data_length_octets; /* octets in data */
const uint8_t *data; /* data */
int tag_length_octets; /* octets in tag */
const uint8_t *tag; /* tag */
const struct srtp_auth_test_case_t
*next_test_case; /* pointer to next testcase */
} srtp_auth_test_case_t;
/* srtp_auth_type_t */
@ -122,17 +128,17 @@ typedef struct srtp_auth_type_t {
srtp_auth_compute_func compute;
srtp_auth_update_func update;
srtp_auth_start_func start;
const char *description;
const srtp_auth_test_case_t *test_data;
const char *description;
const srtp_auth_test_case_t *test_data;
srtp_auth_type_id_t id;
} srtp_auth_type_t;
typedef struct srtp_auth_t {
const srtp_auth_type_t *type;
void *state;
int out_len; /* length of output tag in octets */
int key_len; /* length of key in octets */
int prefix_len; /* length of keystream prefix */
void *state;
int out_len; /* length of output tag in octets */
int key_len; /* length of key in octets */
int prefix_len; /* length of keystream prefix */
} srtp_auth_t;
/*
@ -147,8 +153,8 @@ srtp_err_status_t srtp_auth_type_self_test(const srtp_auth_type_t *at);
* provided in an array of values of key/message/tag that is known to
* be good
*/
srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at,
const srtp_auth_test_case_t *test_data);
srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at,
const srtp_auth_test_case_t *test_data);
/*
* srtp_replace_auth_type(ct, id)
@ -157,7 +163,8 @@ srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at,
* with a new one passed in externally. The new auth type must pass all the
* existing auth_type's self tests as well as its own.
*/
srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *ct, srtp_auth_type_id_t id);
srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *ct,
srtp_auth_type_id_t id);
#ifdef __cplusplus
}

View File

@ -42,13 +42,11 @@
*
*/
#ifndef SRTP_CIPHER_H
#define SRTP_CIPHER_H
#include "srtp.h"
#include "crypto_types.h" /* for values of cipher_type_id_t */
#include "crypto_types.h" /* for values of cipher_type_id_t */
#ifdef __cplusplus
extern "C" {
@ -71,51 +69,60 @@ typedef enum {
* the srtp_cipher_pointer_t definition is needed
* as srtp_cipher_t is not yet defined
*/
typedef struct srtp_cipher_t *srtp_cipher_pointer_t;
typedef struct srtp_cipher_t *srtp_cipher_pointer_t;
/*
* a srtp_cipher_alloc_func_t allocates (but does not initialize) a srtp_cipher_t
* a srtp_cipher_alloc_func_t allocates (but does not initialize) a
* srtp_cipher_t
*/
typedef srtp_err_status_t (*srtp_cipher_alloc_func_t)
(srtp_cipher_pointer_t *cp, int key_len, int tag_len);
typedef srtp_err_status_t (*srtp_cipher_alloc_func_t)(srtp_cipher_pointer_t *cp,
int key_len,
int tag_len);
/*
* a srtp_cipher_init_func_t [re-]initializes a cipher_t with a given key
*/
typedef srtp_err_status_t (*srtp_cipher_init_func_t)
(void *state, const uint8_t *key);
typedef srtp_err_status_t (*srtp_cipher_init_func_t)(void *state,
const uint8_t *key);
/* a srtp_cipher_dealloc_func_t de-allocates a cipher_t */
typedef srtp_err_status_t (*srtp_cipher_dealloc_func_t)(srtp_cipher_pointer_t cp);
typedef srtp_err_status_t (*srtp_cipher_dealloc_func_t)(
srtp_cipher_pointer_t cp);
/*
* a srtp_cipher_set_aad_func_t processes the AAD data for AEAD ciphers
*/
typedef srtp_err_status_t (*srtp_cipher_set_aad_func_t)
(void *state, const uint8_t *aad, uint32_t aad_len);
typedef srtp_err_status_t (*srtp_cipher_set_aad_func_t)(void *state,
const uint8_t *aad,
uint32_t aad_len);
/* a srtp_cipher_encrypt_func_t encrypts data in-place */
typedef srtp_err_status_t (*srtp_cipher_encrypt_func_t)
(void *state, uint8_t *buffer, unsigned int *octets_to_encrypt);
typedef srtp_err_status_t (*srtp_cipher_encrypt_func_t)(
void *state,
uint8_t *buffer,
unsigned int *octets_to_encrypt);
/* a srtp_cipher_decrypt_func_t decrypts data in-place */
typedef srtp_err_status_t (*srtp_cipher_decrypt_func_t)
(void *state, uint8_t *buffer, unsigned int *octets_to_decrypt);
typedef srtp_err_status_t (*srtp_cipher_decrypt_func_t)(
void *state,
uint8_t *buffer,
unsigned int *octets_to_decrypt);
/*
* a srtp_cipher_set_iv_func_t function sets the current initialization vector
*/
typedef srtp_err_status_t (*srtp_cipher_set_iv_func_t)
(void *state, uint8_t *iv, srtp_cipher_direction_t direction);
typedef srtp_err_status_t (*srtp_cipher_set_iv_func_t)(
void *state,
uint8_t *iv,
srtp_cipher_direction_t direction);
/*
* a cipher_get_tag_func_t function is used to get the authentication
* tag that was calculated by an AEAD cipher.
*/
typedef srtp_err_status_t (*srtp_cipher_get_tag_func_t)
(void *state, uint8_t *tag, uint32_t *len);
typedef srtp_err_status_t (*srtp_cipher_get_tag_func_t)(void *state,
uint8_t *tag,
uint32_t *len);
/*
* srtp_cipher_test_case_t is a (list of) key, salt, plaintext, ciphertext,
@ -125,17 +132,18 @@ typedef srtp_err_status_t (*srtp_cipher_get_tag_func_t)
* (see the srtp_cipher_type_self_test() function below)
*/
typedef struct srtp_cipher_test_case_t {
int key_length_octets; /* octets in key */
const uint8_t *key; /* key */
uint8_t *idx; /* packet index */
int plaintext_length_octets; /* octets in plaintext */
const uint8_t *plaintext; /* plaintext */
int ciphertext_length_octets; /* octets in plaintext */
const uint8_t *ciphertext; /* ciphertext */
int aad_length_octets; /* octets in AAD */
const uint8_t *aad; /* AAD */
int tag_length_octets; /* Length of AEAD tag */
const struct srtp_cipher_test_case_t *next_test_case; /* pointer to next testcase */
int key_length_octets; /* octets in key */
const uint8_t *key; /* key */
uint8_t *idx; /* packet index */
unsigned int plaintext_length_octets; /* octets in plaintext */
const uint8_t *plaintext; /* plaintext */
unsigned int ciphertext_length_octets; /* octets in plaintext */
const uint8_t *ciphertext; /* ciphertext */
int aad_length_octets; /* octets in AAD */
const uint8_t *aad; /* AAD */
int tag_length_octets; /* Length of AEAD tag */
const struct srtp_cipher_test_case_t
*next_test_case; /* pointer to next testcase */
} srtp_cipher_test_case_t;
/* srtp_cipher_type_t defines the 'metadata' for a particular cipher type */
@ -148,8 +156,8 @@ typedef struct srtp_cipher_type_t {
srtp_cipher_encrypt_func_t decrypt;
srtp_cipher_set_iv_func_t set_iv;
srtp_cipher_get_tag_func_t get_tag;
const char *description;
const srtp_cipher_test_case_t *test_data;
const char *description;
const srtp_cipher_test_case_t *test_data;
srtp_cipher_type_id_t id;
} srtp_cipher_type_t;
@ -159,7 +167,7 @@ typedef struct srtp_cipher_type_t {
*/
typedef struct srtp_cipher_t {
const srtp_cipher_type_t *type;
void *state;
void *state;
int key_len;
int algorithm;
} srtp_cipher_t;
@ -167,7 +175,6 @@ typedef struct srtp_cipher_t {
/* some bookkeeping functions */
int srtp_cipher_get_key_length(const srtp_cipher_t *c);
/*
* srtp_cipher_type_self_test() tests a cipher against test cases provided in
* an array of values of key/srtp_xtd_seq_num_t/plaintext/ciphertext
@ -175,14 +182,15 @@ int srtp_cipher_get_key_length(const srtp_cipher_t *c);
*/
srtp_err_status_t srtp_cipher_type_self_test(const srtp_cipher_type_t *ct);
/*
* srtp_cipher_type_test() tests a cipher against external test cases provided in
* srtp_cipher_type_test() tests a cipher against external test cases provided
* in
* an array of values of key/srtp_xtd_seq_num_t/plaintext/ciphertext
* that is known to be good
*/
srtp_err_status_t srtp_cipher_type_test(const srtp_cipher_type_t *ct, const srtp_cipher_test_case_t *test_data);
srtp_err_status_t srtp_cipher_type_test(
const srtp_cipher_type_t *ct,
const srtp_cipher_test_case_t *test_data);
/*
* srtp_cipher_bits_per_second(c, l, t) computes (an estimate of) the
@ -194,17 +202,34 @@ srtp_err_status_t srtp_cipher_type_test(const srtp_cipher_type_t *ct, const srtp
*
* if an error is encountered, then the value 0 is returned
*/
uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c, int octets_in_buffer, int num_trials);
uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c,
int octets_in_buffer,
int num_trials);
srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct, srtp_cipher_t **c, int key_len, int tlen);
srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct,
srtp_cipher_t **c,
int key_len,
int tlen);
srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c);
srtp_err_status_t srtp_cipher_init(srtp_cipher_t *c, const uint8_t *key);
srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c, uint8_t *iv, int direction);
srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output);
srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output);
srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output);
srtp_err_status_t srtp_cipher_get_tag(srtp_cipher_t *c, uint8_t *buffer, uint32_t *tag_len);
srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c, const uint8_t *aad, uint32_t aad_len);
srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c,
uint8_t *iv,
int direction);
srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c,
uint8_t *buffer,
uint32_t *num_octets_to_output);
srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c,
uint8_t *buffer,
uint32_t *num_octets_to_output);
srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c,
uint8_t *buffer,
uint32_t *num_octets_to_output);
srtp_err_status_t srtp_cipher_get_tag(srtp_cipher_t *c,
uint8_t *buffer,
uint32_t *tag_len);
srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c,
const uint8_t *aad,
uint32_t aad_len);
/*
* srtp_replace_cipher_type(ct, id)
@ -213,7 +238,8 @@ srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c, const uint8_t *aad, uint
* with a new one passed in externally. The new cipher must pass all the
* existing cipher_type's self tests as well as its own.
*/
srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *ct, srtp_cipher_type_id_t id);
srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *ct,
srtp_cipher_type_id_t id);
#ifdef __cplusplus
}

View File

@ -1,15 +1,6 @@
/*
* aes_gcm_ossl.h
*
* Header for AES Galois Counter Mode.
*
* John A. Foley
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,21 +34,29 @@
*
*/
#ifndef AES_GCM_OSSL_H
#define AES_GCM_OSSL_H
#ifndef SRTP_CIHPER_PRIV_H
#define SRTP_CIHPER_PRIV_H
#include "cipher.h"
#include "srtp.h"
#include "datatypes.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
typedef struct {
int key_size;
int tag_len;
EVP_CIPHER_CTX* ctx;
srtp_cipher_direction_t dir;
} srtp_aes_gcm_ctx_t;
#ifdef __cplusplus
extern "C" {
#endif
#endif /* AES_GCM_OSSL_H */
/*
* A trivial platform independent random source.
* For use in test only.
*/
void srtp_cipher_rand_for_tests(void *dest, uint32_t len);
/*
* A trivial platform independent 32 bit random number.
* For use in test only.
*/
uint32_t srtp_cipher_rand_u32_for_tests(void);
#ifdef __cplusplus
}
#endif
#endif /* SRTP_CIPHER_PRIV_H */

View File

@ -1,32 +1,24 @@
/*
* 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.
* 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
@ -42,27 +34,47 @@
*
*/
#ifndef GETOPT_S_H
#define GETOPT_S_H
#ifndef CIHPER_TYPES_H
#define CIHPER_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif
#include "cipher.h"
#include "auth.h"
/*
* getopt_s(), optarg_s, and optind_s are small, locally defined
* versions of the POSIX standard getopt() interface.
/*
* cipher types that can be included in the kernel
*/
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
}
extern const srtp_cipher_type_t srtp_null_cipher;
extern const srtp_cipher_type_t srtp_aes_icm_128;
extern const srtp_cipher_type_t srtp_aes_icm_256;
#ifdef GCM
extern const srtp_cipher_type_t srtp_aes_icm_192;
extern const srtp_cipher_type_t srtp_aes_gcm_128;
extern const srtp_cipher_type_t srtp_aes_gcm_256;
#endif
#endif /* GETOPT_S_H */
/*
* auth func types that can be included in the kernel
*/
extern const srtp_auth_type_t srtp_null_auth;
extern const srtp_auth_type_t srtp_hmac;
/*
* other generic debug modules that can be included in the kernel
*/
extern srtp_debug_module_t srtp_mod_auth;
extern srtp_debug_module_t srtp_mod_cipher;
extern srtp_debug_module_t srtp_mod_alloc;
/* debug modules for cipher types */
extern srtp_debug_module_t srtp_mod_aes_icm;
#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

View File

@ -42,7 +42,6 @@
*
*/
#ifndef CRYPTO_KERNEL
#define CRYPTO_KERNEL
@ -72,7 +71,7 @@ typedef enum {
*/
typedef struct srtp_kernel_cipher_type {
srtp_cipher_type_id_t id;
const srtp_cipher_type_t *cipher_type;
const srtp_cipher_type_t *cipher_type;
struct srtp_kernel_cipher_type *next;
} srtp_kernel_cipher_type_t;
@ -81,7 +80,7 @@ typedef struct srtp_kernel_cipher_type {
*/
typedef struct srtp_kernel_auth_type {
srtp_auth_type_id_t id;
const srtp_auth_type_t *auth_type;
const srtp_auth_type_t *auth_type;
struct srtp_kernel_auth_type *next;
} srtp_kernel_auth_type_t;
@ -93,7 +92,6 @@ typedef struct srtp_kernel_debug_module {
struct srtp_kernel_debug_module *next;
} srtp_kernel_debug_module_t;
/*
* crypto_kernel_t is the data structure for the crypto kernel
*
@ -101,18 +99,17 @@ typedef struct srtp_kernel_debug_module {
* a global variable defined in crypto_kernel.c
*/
typedef struct {
srtp_crypto_kernel_state_t state; /* current state of kernel */
srtp_kernel_cipher_type_t *cipher_type_list; /* list of all cipher types */
srtp_kernel_auth_type_t *auth_type_list; /* list of all auth func types */
srtp_kernel_debug_module_t *debug_module_list; /* list of all debug modules */
srtp_crypto_kernel_state_t state; /* current state of kernel */
srtp_kernel_cipher_type_t *cipher_type_list; /* list of all cipher types */
srtp_kernel_auth_type_t *auth_type_list; /* list of all auth func types */
srtp_kernel_debug_module_t
*debug_module_list; /* list of all debug modules */
} srtp_crypto_kernel_t;
/*
* srtp_crypto_kernel_t external api
*/
/*
* The function srtp_crypto_kernel_init() initialized the crypto kernel and
* runs the self-test operations on the random number generators and
@ -126,7 +123,6 @@ typedef struct {
*/
srtp_err_status_t srtp_crypto_kernel_init(void);
/*
* The function srtp_crypto_kernel_shutdown() de-initializes the
* crypto_kernel, zeroizes keys and other cryptographic material, and
@ -150,7 +146,6 @@ srtp_err_status_t srtp_crypto_kernel_shutdown(void);
*/
srtp_err_status_t srtp_crypto_kernel_status(void);
/*
* srtp_crypto_kernel_list_debug_modules() outputs a list of debugging modules
*
@ -161,11 +156,15 @@ srtp_err_status_t srtp_crypto_kernel_list_debug_modules(void);
* srtp_crypto_kernel_load_cipher_type()
*
*/
srtp_err_status_t srtp_crypto_kernel_load_cipher_type(const srtp_cipher_type_t *ct, srtp_cipher_type_id_t id);
srtp_err_status_t srtp_crypto_kernel_load_cipher_type(
const srtp_cipher_type_t *ct,
srtp_cipher_type_id_t id);
srtp_err_status_t srtp_crypto_kernel_load_auth_type(const srtp_auth_type_t *ct, srtp_auth_type_id_t id);
srtp_err_status_t srtp_crypto_kernel_load_auth_type(const srtp_auth_type_t *ct,
srtp_auth_type_id_t id);
srtp_err_status_t srtp_crypto_kernel_load_debug_module(srtp_debug_module_t *new_dm);
srtp_err_status_t srtp_crypto_kernel_load_debug_module(
srtp_debug_module_t *new_dm);
/*
* srtp_crypto_kernel_alloc_cipher(id, cp, key_len);
@ -177,7 +176,10 @@ srtp_err_status_t srtp_crypto_kernel_load_debug_module(srtp_debug_module_t *new_
* srtp_err_status_alloc_fail an allocation failure occured
* srtp_err_status_fail couldn't find cipher with identifier 'id'
*/
srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id, srtp_cipher_pointer_t *cp, int key_len, int tag_len);
srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id,
srtp_cipher_pointer_t *cp,
int key_len,
int tag_len);
/*
* srtp_crypto_kernel_alloc_auth(id, ap, key_len, tag_len);
@ -190,8 +192,10 @@ srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id, srtp
* srtp_err_status_alloc_fail an allocation failure occured
* srtp_err_status_fail couldn't find auth with identifier 'id'
*/
srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id, srtp_auth_pointer_t *ap, int key_len, int tag_len);
srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id,
srtp_auth_pointer_t *ap,
int key_len,
int tag_len);
/*
* srtp_crypto_kernel_set_debug_module(mod_name, v)
@ -201,7 +205,8 @@ srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id, srtp_aut
*
* returns srtp_err_status_ok on success, srtp_err_status_fail otherwise
*/
srtp_err_status_t srtp_crypto_kernel_set_debug_module(const char *mod_name, int v);
srtp_err_status_t srtp_crypto_kernel_set_debug_module(const char *mod_name,
int v);
#ifdef __cplusplus
}

View File

@ -7,26 +7,26 @@
* 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
@ -48,62 +48,62 @@
/*
* The null cipher performs no encryption.
*
* The SRTP_NULL_CIPHER leaves its inputs unaltered, during both the
* The SRTP_NULL_CIPHER leaves its inputs unaltered, during both the
* encryption and decryption operations. This cipher can be chosen
* to indicate that no encryption is to be performed.
*/
#define SRTP_NULL_CIPHER 0
#define SRTP_NULL_CIPHER 0
/*
/*
* AES-128 Integer Counter Mode (AES ICM)
*
* AES-128 ICM is the variant of counter mode that is used by
* Secure RTP. This cipher uses a 16-octet key concatenated with a
* 14-octet offset (or salt) value.
*/
#define SRTP_AES_ICM_128 1
#define SRTP_AES_ICM_128 1
/*
/*
* AES-192 Integer Counter Mode (AES ICM)
*
* AES-128 ICM is the variant of counter mode that is used by
* Secure RTP. This cipher uses a 24-octet key concatenated with a
* 14-octet offset (or salt) value.
*/
#define SRTP_AES_ICM_192 4
#define SRTP_AES_ICM_192 4
/*
/*
* AES-256 Integer Counter Mode (AES ICM)
*
* AES-128 ICM is the variant of counter mode that is used by
* Secure RTP. This cipher uses a 32-octet key concatenated with a
* 14-octet offset (or salt) value.
*/
#define SRTP_AES_ICM_256 5
#define SRTP_AES_ICM_256 5
/*
* AES-128_GCM Galois Counter Mode (AES GCM)
/*
* AES-128_GCM Galois Counter Mode (AES GCM)
*
* AES-128 GCM is the variant of galois counter mode that is used by
* AES-128 GCM is the variant of galois counter mode that is used by
* Secure RTP. This cipher uses a 16-octet key.
*/
#define SRTP_AES_GCM_128 6
#define SRTP_AES_GCM_128 6
/*
* AES-256_GCM Galois Counter Mode (AES GCM)
/*
* AES-256_GCM Galois Counter Mode (AES GCM)
*
* AES-256 GCM is the variant of galois counter mode that is used by
* AES-256 GCM is the variant of galois counter mode that is used by
* Secure RTP. This cipher uses a 32-octet key.
*/
#define SRTP_AES_GCM_256 7
#define SRTP_AES_GCM_256 7
/*
* The null authentication function performs no authentication.
*
* The NULL_AUTH function does nothing, and can be selected to indicate
* that authentication should not be performed.
*/
#define SRTP_NULL_AUTH 0
*/
#define SRTP_NULL_AUTH 0
/*
* HMAC-SHA1
@ -111,6 +111,6 @@
* SRTP_HMAC_SHA1 implements the Hash-based MAC using the NIST Secure
* Hash Algorithm version 1 (SHA1).
*/
#define SRTP_HMAC_SHA1 3
#define SRTP_HMAC_SHA1 3
#endif /* SRTP_CRYPTO_TYPES_H */
#endif /* SRTP_CRYPTO_TYPES_H */

View File

@ -1,6 +1,6 @@
/*
* datatypes.h
*
*
* data types for bit vectors and finite fields
*
* David A. McGrew
@ -8,26 +8,26 @@
*/
/*
*
*
* 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
@ -43,11 +43,10 @@
*
*/
#ifndef DATATYPES_H
#define DATATYPES_H
#include "integers.h" /* definitions of uint32_t, et cetera */
#include "integers.h" /* definitions of uint32_t, et cetera */
#include "alloc.h"
#include <stdarg.h>
@ -56,163 +55,62 @@
#include <string.h>
#include <time.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#include <netinet/in.h>
#elif defined HAVE_WINSOCK2_H
# include <winsock2.h>
#include <winsock2.h>
#else
#error "Platform not recognized"
#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];
uint32_t v32[4];
uint64_t v64[2];
uint8_t v8[16];
uint16_t v16[8];
uint32_t v32[4];
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);
char *srtp_octet_string_hex_string(const void *str, int length);
char *
v128_bit_string(v128_t *x);
char *v128_bit_string(v128_t *x);
char *
v128_hex_string(v128_t *x);
char *v128_hex_string(v128_t *x);
void
v128_copy_octet_string(v128_t *x, const uint8_t s[16]);
void v128_copy_octet_string(v128_t *x, const uint8_t s[16]);
void
v128_left_shift(v128_t *x, int shift_index);
void
v128_right_shift(v128_t *x, int shift_index);
void v128_left_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) \
( \
(x)->v32[0] = 0, \
(x)->v32[1] = 0, \
(x)->v32[2] = 0, \
(x)->v32[3] = 0 \
)
#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) \
( \
(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_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) \
( \
(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] \
)
#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])
/* 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) \
( \
(z)->v32[0] ^= (x)->v32[0], \
(z)->v32[1] ^= (x)->v32[1], \
(z)->v32[2] ^= (x)->v32[2], \
(z)->v32[3] ^= (x)->v32[3] \
)
#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) \
( \
(z)->v64[0] ^= (x)->v64[0], \
(z)->v64[1] ^= (x)->v64[1] \
)
#define v128_xor_eq(z, x) \
((z)->v64[0] ^= (x)->v64[0], (z)->v64[1] ^= (x)->v64[1])
#endif
/* NOTE! This assumes an odd ordering! */
@ -224,229 +122,125 @@ v128_right_shift(v128_t *x, int shift_index);
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) \
( \
(((x)->v32[(bit) >> 5]) |= ((uint32_t)1 << ((bit) & 31))) \
)
#define v128_set_bit(x, bit) \
((((x)->v32[(bit) >> 5]) |= ((uint32_t)1 << ((bit)&31))))
#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 */
#define v128_clear_bit(x, bit) \
((((x)->v32[(bit) >> 5]) &= ~((uint32_t)1 << ((bit)&31))))
/*
* 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
* 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
* comparison depends only on len, making this safe to use for (e.g.)
* verifying authentication tags.
*/
int
octet_string_is_eq(uint8_t *a, uint8_t *b, int len);
int srtp_octet_string_is_eq(uint8_t *a, uint8_t *b, int len);
/*
* A portable way to zero out memory as recommended by
* https://cryptocoding.net/index.php/Coding_rules#Clean_memory_of_secret_data
* This is used to zero memory when OPENSSL_cleanse() is not available.
*/
void
srtp_cleanse(void *s, size_t len);
void srtp_cleanse(void *s, size_t len);
/*
* Functions as a wrapper that delegates to either srtp_cleanse() or
* OPENSSL_cleanse() if available to zero memory.
*/
void
octet_string_set_to_zero(void *s, size_t len);
void octet_string_set_to_zero(void *s, size_t len);
#if defined(HAVE_CONFIG_H)
#if defined(HAVE_CONFIG_H)
/*
/*
* Convert big endian integers to CPU byte order.
*/
#ifdef WORDS_BIGENDIAN
/* Nothing to do. */
# define be32_to_cpu(x) (x)
# define be64_to_cpu(x) (x)
#define be32_to_cpu(x) (x)
#define be64_to_cpu(x) (x)
#elif defined(HAVE_BYTESWAP_H)
/* We have (hopefully) optimized versions in byteswap.h */
# include <byteswap.h>
# define be32_to_cpu(x) bswap_32((x))
# define be64_to_cpu(x) bswap_64((x))
#else
#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__) && (defined(HAVE_X86) || defined(__x86_64__))
/* Fall back. */
static inline uint32_t be32_to_cpu(uint32_t v) {
/* optimized for x86. */
asm("bswap %0" : "=r" (v) : "0" (v));
return v;
static inline uint32_t be32_to_cpu(uint32_t v)
{
/* optimized for x86. */
asm("bswap %0" : "=r"(v) : "0"(v));
return v;
}
# else /* HAVE_X86 */
# ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
# elif defined HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# define be32_to_cpu(x) ntohl((x))
# endif /* HAVE_X86 */
#else /* HAVE_X86 */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#elif defined HAVE_WINSOCK2_H
#include <winsock2.h>
#endif /* HAVE_NETINET_IN_H */
#define be32_to_cpu(x) ntohl((x))
#endif /* HAVE_X86 */
static inline uint64_t be64_to_cpu(uint64_t v) {
# ifdef NO_64BIT_MATH
/* use the make64 functions to do 64-bit math */
v = make64(htonl(low32(v)),htonl(high32(v)));
# else
/* use the native 64-bit math */
v= (uint64_t)((be32_to_cpu((uint32_t)(v >> 32))) | (((uint64_t)be32_to_cpu((uint32_t)v)) << 32));
# endif
return v;
static inline uint64_t be64_to_cpu(uint64_t v)
{
#ifdef NO_64BIT_MATH
/* use the make64 functions to do 64-bit math */
v = make64(htonl(low32(v)), htonl(high32(v)));
#else /* NO_64BIT_MATH */
/* use the native 64-bit math */
v = (uint64_t)((be32_to_cpu((uint32_t)(v >> 32))) |
(((uint64_t)be32_to_cpu((uint32_t)v)) << 32));
#endif /* NO_64BIT_MATH */
return v;
}
#endif
#endif /* WORDS_BIGENDIAN */
#endif /* HAVE_CONFIG_H */
/*
* functions manipulating bitvector_t
* functions manipulating bitvector_t
*
* A bitvector_t consists of an array of words and an integer
* representing the number of significant bits stored in the array.
* The bits are packed as follows: the least significant bit is that
* of word[0], while the most significant bit is the nth most
* significant bit of word[m], where length = bits_per_word * m + n.
*
*
*/
#define bits_per_word 32
#define bits_per_word 32
#define bytes_per_word 4
typedef struct {
uint32_t length;
uint32_t *word;
uint32_t length;
uint32_t *word;
} bitvector_t;
#define bitvector_get_bit(v, bit_index) \
(((((v)->word[((bit_index) >> 5)]) >> ((bit_index)&31)) & 1))
#define _bitvector_get_bit(v, bit_index) \
( \
((((v)->word[((bit_index) >> 5)]) >> ((bit_index) & 31)) & 1) \
)
#define bitvector_set_bit(v, bit_index) \
((((v)->word[((bit_index) >> 5)] |= ((uint32_t)1 << ((bit_index)&31)))))
#define bitvector_get_length(v) (((v)->length))
#define _bitvector_set_bit(v, bit_index) \
( \
(((v)->word[((bit_index) >> 5)] |= ((uint32_t)1 << ((bit_index) & 31)))) \
)
int bitvector_alloc(bitvector_t *v, unsigned long length);
#define _bitvector_clear_bit(v, bit_index) \
( \
(((v)->word[((bit_index) >> 5)] &= ~((uint32_t)1 << ((bit_index) & 31)))) \
)
void bitvector_dealloc(bitvector_t *v);
#define _bitvector_get_length(v) \
( \
((v)->length) \
)
void bitvector_set_to_zero(bitvector_t *x);
#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
int
bitvector_alloc(bitvector_t *v, unsigned long length);
void
bitvector_dealloc(bitvector_t *v);
void
bitvector_set_to_zero(bitvector_t *x);
void
bitvector_left_shift(bitvector_t *x, int index);
char *
bitvector_bit_string(bitvector_t *x, char* buf, int len);
void bitvector_left_shift(bitvector_t *x, int index);
#ifdef __cplusplus
}

View File

@ -42,7 +42,6 @@
*
*/
#ifndef ERR_H
#define ERR_H
@ -50,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
@ -62,7 +72,6 @@ extern "C" {
* @{
*/
/**
* @}
*/
@ -82,9 +91,11 @@ typedef enum {
srtp_err_status_t srtp_err_reporting_init(void);
typedef void (srtp_err_report_handler_func_t)(srtp_err_reporting_level_t level, const char * msg);
typedef void(srtp_err_report_handler_func_t)(srtp_err_reporting_level_t level,
const char *msg);
srtp_err_status_t srtp_install_err_report_handler(srtp_err_report_handler_func_t func);
srtp_err_status_t srtp_install_err_report_handler(
srtp_err_report_handler_func_t func);
/*
* srtp_err_report reports a 'printf' formatted error
@ -96,9 +107,8 @@ srtp_err_status_t srtp_install_err_report_handler(srtp_err_report_handler_func_t
*
*/
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
@ -111,17 +121,26 @@ typedef struct {
#ifdef ENABLE_DEBUG_LOGGING
#define debug_print(mod, format, arg) \
#define debug_print0(mod, format) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name)
#define debug_print(mod, format, arg) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg)
#define debug_print2(mod, format, arg1, arg2) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg1, arg2)
#define debug_print2(mod, format, arg1, arg2) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, \
arg1, arg2)
#else
#define debug_print(mod, format, arg) \
if (mod.on) srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg)
#define debug_print2(mod, format, arg1, arg2) \
if (mod.on) srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg1, arg2)
#define debug_print0(mod, format) \
if (mod.on) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name)
#define debug_print(mod, format, arg) \
if (mod.on) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg)
#define debug_print2(mod, format, arg1, arg2) \
if (mod.on) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, \
arg1, arg2)
#endif

View File

@ -8,26 +8,26 @@
*/
/*
*
*
* 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
@ -43,29 +43,27 @@
*
*/
#ifndef INTEGERS_H
#define INTEGERS_H
/* use standard integer definitions, if they're available */
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#include <stdlib.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#include <inttypes.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_INT_TYPES_H
# include <sys/int_types.h> /* this exists on Sun OS */
#include <sys/int_types.h> /* this exists on Sun OS */
#endif
#ifdef HAVE_MACHINE_TYPES_H
# include <machine/types.h>
#include <machine/types.h>
#endif
#ifdef __cplusplus
@ -74,31 +72,30 @@ extern "C" {
/* Can we do 64 bit integers? */
#if !defined(HAVE_UINT64_T)
# if SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long uint64_t;
# elif SIZEOF_UNSIGNED_LONG_LONG == 8
typedef unsigned long long uint64_t;
# else
# define NO_64BIT_MATH 1
# endif
#if SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long uint64_t;
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
typedef unsigned long long uint64_t;
#else
#define NO_64BIT_MATH 1
#endif
#endif
/* Reasonable defaults for 32 bit machines - you may need to
* edit these definitions for your own machine. */
#ifndef HAVE_UINT8_T
typedef unsigned char uint8_t;
typedef unsigned char uint8_t;
#endif
#ifndef HAVE_UINT16_T
typedef unsigned short int uint16_t;
typedef unsigned short int uint16_t;
#endif
#ifndef HAVE_UINT32_T
typedef unsigned int uint32_t;
typedef unsigned int uint32_t;
#endif
#ifndef HAVE_INT32_T
typedef int int32_t;
#endif
#if defined(NO_64BIT_MATH) && defined(HAVE_CONFIG_H)
typedef double uint64_t;
/* assert that sizeof(double) == 8 */
@ -107,39 +104,38 @@ extern uint32_t high32(uint64_t value);
extern uint32_t low32(uint64_t value);
#endif
/* These macros are to load and store 32-bit values from un-aligned
addresses. This is required for processors that do not allow unaligned
loads. */
#ifdef ALIGNMENT_32BIT_REQUIRED
/* Note that if it's in a variable, you can memcpy it */
#ifdef WORDS_BIGENDIAN
#define PUT_32(addr,value) \
{ \
((unsigned char *) (addr))[0] = (value >> 24); \
((unsigned char *) (addr))[1] = (value >> 16) & 0xff; \
((unsigned char *) (addr))[2] = (value >> 8) & 0xff; \
((unsigned char *) (addr))[3] = (value) & 0xff; \
#define PUT_32(addr, value) \
{ \
((unsigned char *)(addr))[0] = (value >> 24); \
((unsigned char *)(addr))[1] = (value >> 16) & 0xff; \
((unsigned char *)(addr))[2] = (value >> 8) & 0xff; \
((unsigned char *)(addr))[3] = (value)&0xff; \
}
#define GET_32(addr) ((((unsigned char *) (addr))[0] << 24) | \
(((unsigned char *) (addr))[1] << 16) | \
(((unsigned char *) (addr))[2] << 8) | \
(((unsigned char *) (addr))[3]))
#define GET_32(addr) \
((((unsigned char *)(addr))[0] << 24) | \
(((unsigned char *)(addr))[1] << 16) | \
(((unsigned char *)(addr))[2] << 8) | (((unsigned char *)(addr))[3]))
#else
#define PUT_32(addr,value) \
{ \
((unsigned char *) (addr))[3] = (value >> 24); \
((unsigned char *) (addr))[2] = (value >> 16) & 0xff; \
((unsigned char *) (addr))[1] = (value >> 8) & 0xff; \
((unsigned char *) (addr))[0] = (value) & 0xff; \
#define PUT_32(addr, value) \
{ \
((unsigned char *)(addr))[3] = (value >> 24); \
((unsigned char *)(addr))[2] = (value >> 16) & 0xff; \
((unsigned char *)(addr))[1] = (value >> 8) & 0xff; \
((unsigned char *)(addr))[0] = (value)&0xff; \
}
#define GET_32(addr) ((((unsigned char *) (addr))[3] << 24) | \
(((unsigned char *) (addr))[2] << 16) | \
(((unsigned char *) (addr))[1] << 8) | \
(((unsigned char *) (addr))[0]))
#define GET_32(addr) \
((((unsigned char *)(addr))[3] << 24) | \
(((unsigned char *)(addr))[2] << 16) | \
(((unsigned char *)(addr))[1] << 8) | (((unsigned char *)(addr))[0]))
#endif // WORDS_BIGENDIAN
#else
#define PUT_32(addr,value) *(((uint32_t *) (addr)) = (value)
#define PUT_32(addr, value) *(((uint32_t *) (addr)) = (value)
#define GET_32(addr) (*(((uint32_t *) (addr)))
#endif

View File

@ -45,7 +45,7 @@
#ifndef KEY_H
#define KEY_H
#include "rdbx.h" /* for srtp_xtd_seq_num_t */
#include "rdbx.h" /* for srtp_xtd_seq_num_t */
#include "err.h"
#ifdef __cplusplus
@ -60,11 +60,11 @@ typedef enum {
srtp_key_event_hard_limit
} srtp_key_event_t;
srtp_err_status_t srtp_key_limit_set(srtp_key_limit_t key, const srtp_xtd_seq_num_t s);
srtp_err_status_t srtp_key_limit_set(srtp_key_limit_t key,
const srtp_xtd_seq_num_t s);
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_err_status_t srtp_key_limit_clone(srtp_key_limit_t original,
srtp_key_limit_t *new_key);
srtp_key_event_t srtp_key_limit_update(srtp_key_limit_t key);

View File

@ -55,17 +55,6 @@ typedef struct {
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

View File

@ -44,7 +44,6 @@
*
*/
#ifndef NULL_CIPHER_H
#define NULL_CIPHER_H

View File

@ -7,28 +7,27 @@
* 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
@ -47,9 +46,9 @@
#ifndef REPLAY_DB_H
#define REPLAY_DB_H
#include "integers.h" /* for uint32_t */
#include "datatypes.h" /* for v128_t */
#include "err.h" /* for srtp_err_status_t */
#include "integers.h" /* for uint32_t */
#include "datatypes.h" /* for v128_t */
#include "err.h" /* for srtp_err_status_t */
#ifdef __cplusplus
extern "C" {
@ -65,8 +64,6 @@ typedef struct {
v128_t bitmask;
} srtp_rdb_t;
#define rdb_bits_in_bitmask (8 * sizeof(v128_t))
/*
* srtp_rdb_init
*
@ -76,7 +73,6 @@ typedef struct {
*/
srtp_err_status_t srtp_rdb_init(srtp_rdb_t *rdb);
/*
* srtp_rdb_check
*
@ -103,7 +99,6 @@ srtp_err_status_t srtp_rdb_add_index(srtp_rdb_t *rdb, uint32_t rdb_index);
* srtp_rdb_t upon which srtp_rdb_add_index is used!
*/
/*
* srtp_rdb_increment(db) increments the sequence number in db, if it is
* not too high
@ -121,7 +116,6 @@ srtp_err_status_t srtp_rdb_increment(srtp_rdb_t *rdb);
*/
uint32_t srtp_rdb_get_value(const srtp_rdb_t *rdb);
#ifdef __cplusplus
}
#endif

View File

@ -9,26 +9,26 @@
*/
/*
*
*
* 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
@ -58,10 +58,10 @@ extern "C" {
#ifndef ROC_TEST
typedef uint16_t srtp_sequence_number_t; /* 16 bit sequence number */
typedef uint32_t srtp_rollover_counter_t; /* 32 bit rollover counter */
typedef uint16_t srtp_sequence_number_t; /* 16 bit sequence number */
typedef uint32_t srtp_rollover_counter_t; /* 32 bit rollover counter */
#else /* use small seq_num and roc datatypes for testing purposes */
#else /* use small seq_num and roc datatypes for testing purposes */
typedef unsigned char srtp_sequence_number_t; /* 8 bit sequence number */
typedef uint16_t srtp_rollover_counter_t; /* 16 bit rollover counter */
@ -69,7 +69,7 @@ typedef uint16_t srtp_rollover_counter_t; /* 16 bit rollover counter */
#endif
#define seq_num_median (1 << (8 * sizeof(srtp_sequence_number_t) - 1))
#define seq_num_max (1 << (8 * sizeof(srtp_sequence_number_t)))
#define seq_num_max (1 << (8 * sizeof(srtp_sequence_number_t)))
/*
* An rtp_xtd_seq_num_t is a 64-bit unsigned integer used as an 'extended'
@ -77,7 +77,6 @@ typedef uint16_t srtp_rollover_counter_t; /* 16 bit rollover counter */
*/
typedef uint64_t srtp_xtd_seq_num_t;
/*
* An srtp_rdbx_t is a replay database with extended range; it uses an
* xtd_seq_num_t and a bitmask of recently received indices.
@ -87,7 +86,6 @@ typedef struct {
bitvector_t bitmask;
} srtp_rdbx_t;
/*
* srtp_rdbx_init(rdbx_ptr, ws)
*
@ -96,7 +94,6 @@ typedef struct {
*/
srtp_err_status_t srtp_rdbx_init(srtp_rdbx_t *rdbx, unsigned long ws);
/*
* srtp_rdbx_dealloc(rdbx_ptr)
*
@ -104,7 +101,6 @@ srtp_err_status_t srtp_rdbx_init(srtp_rdbx_t *rdbx, unsigned long ws);
*/
srtp_err_status_t srtp_rdbx_dealloc(srtp_rdbx_t *rdbx);
/*
* srtp_rdbx_estimate_index(rdbx, guess, s)
*
@ -113,7 +109,9 @@ srtp_err_status_t srtp_rdbx_dealloc(srtp_rdbx_t *rdbx);
* index to which s corresponds, and returns the difference between
* *guess and the locally stored synch info
*/
int32_t srtp_rdbx_estimate_index(const srtp_rdbx_t *rdbx, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s);
int32_t srtp_rdbx_estimate_index(const srtp_rdbx_t *rdbx,
srtp_xtd_seq_num_t *guess,
srtp_sequence_number_t s);
/*
* srtp_rdbx_check(rdbx, delta);
@ -136,7 +134,6 @@ srtp_err_status_t srtp_rdbx_check(const srtp_rdbx_t *rdbx, int difference);
*/
srtp_err_status_t srtp_rdbx_add_index(srtp_rdbx_t *rdbx, int delta);
/*
* srtp_rdbx_set_roc(rdbx, roc) initalizes the srtp_rdbx_t at the location rdbx
* to have the rollover counter value roc. If that value is less than
@ -147,7 +144,8 @@ srtp_err_status_t srtp_rdbx_add_index(srtp_rdbx_t *rdbx, int delta);
srtp_err_status_t srtp_rdbx_set_roc(srtp_rdbx_t *rdbx, uint32_t roc);
/*
* srtp_rdbx_get_packet_index(rdbx) returns the value of the rollover counter for
* srtp_rdbx_get_packet_index(rdbx) returns the value of the rollover counter
* for
* the srtp_rdbx_t pointed to by rdbx
*
*/
@ -166,14 +164,12 @@ srtp_xtd_seq_num_t srtp_rdbx_get_packet_index(const srtp_rdbx_t *rdbx);
*/
unsigned long srtp_rdbx_get_window_size(const srtp_rdbx_t *rdbx);
/* index_init(&pi) initializes a packet index pi (sets it to zero) */
void srtp_index_init(srtp_xtd_seq_num_t *pi);
/* index_advance(&pi, s) advances a xtd_seq_num_t forward by s */
void srtp_index_advance(srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s);
/*
* srtp_index_guess(local, guess, s)
*
@ -183,7 +179,9 @@ void srtp_index_advance(srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s);
* guess of the packet index to which s corresponds, and returns the
* difference between *guess and *local
*/
int32_t srtp_index_guess(const srtp_xtd_seq_num_t *local, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s);
int32_t srtp_index_guess(const srtp_xtd_seq_num_t *local,
srtp_xtd_seq_num_t *guess,
srtp_sequence_number_t s);
/*
* srtp_rdbx_get_roc(rdbx)
@ -200,9 +198,9 @@ uint32_t srtp_rdbx_get_roc(const srtp_rdbx_t *rdbx);
* rollover counter value, then the function returns
* srtp_err_status_replay_old, otherwise, srtp_err_status_ok is returned.
*/
srtp_err_status_t srtp_rdbx_set_roc_seq (srtp_rdbx_t *rdbx,
uint32_t roc,
uint16_t seq);
srtp_err_status_t srtp_rdbx_set_roc_seq(srtp_rdbx_t *rdbx,
uint32_t roc,
uint16_t seq);
#ifdef __cplusplus
}

View File

@ -48,88 +48,16 @@
#define SHA1_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "err.h"
#ifdef OPENSSL
#include <openssl/evp.h>
#include <stdint.h>
#else
#include "datatypes.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef OPENSSL
/*
* srtp_sha1_init(&ctx) initializes the SHA1 context ctx
*
* srtp_sha1_update(&ctx, msg, len) hashes the len octets starting at msg
* into the SHA1 context
*
* srtp_sha1_final(&ctx, output) performs the final processing of the SHA1
* context and writes the result to the 20 octets at output
*
* Return values are ignored on the EVP functions since all three
* of these functions return void.
*
*/
/* OpenSSL 1.1.0 made EVP_MD_CTX an opaque structure, which must be allocated
using EVP_MD_CTX_new. But this function doesn't exist in OpenSSL 1.0.x. */
#if OPENSSL_VERSION_NUMBER < 0x10100000L
typedef EVP_MD_CTX srtp_sha1_ctx_t;
static inline void srtp_sha1_init (srtp_sha1_ctx_t *ctx)
{
EVP_MD_CTX_init(ctx);
EVP_DigestInit(ctx, EVP_sha1());
}
static inline void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg)
{
EVP_DigestUpdate(ctx, M, octets_in_msg);
}
static inline void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output)
{
unsigned int len = 0;
EVP_DigestFinal(ctx, (unsigned char*)output, &len);
EVP_MD_CTX_cleanup(ctx);
}
#else
typedef EVP_MD_CTX* srtp_sha1_ctx_t;
static inline void srtp_sha1_init (srtp_sha1_ctx_t *ctx)
{
*ctx = EVP_MD_CTX_new();
EVP_DigestInit(*ctx, EVP_sha1());
}
static inline void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg)
{
EVP_DigestUpdate(*ctx, M, octets_in_msg);
}
static inline void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output)
{
unsigned int len = 0;
EVP_DigestFinal(*ctx, (unsigned char*)output, &len);
EVP_MD_CTX_free(*ctx);
}
#endif
#else
typedef struct {
uint32_t H[5]; /* state vector */
uint32_t M[16]; /* message buffer */
@ -137,7 +65,6 @@ typedef struct {
uint32_t num_bits_in_msg; /* total number of bits in message */
} srtp_sha1_ctx_t;
/*
* srtp_sha1_init(&ctx) initializes the SHA1 context ctx
*
@ -150,27 +77,11 @@ typedef struct {
*/
void srtp_sha1_init(srtp_sha1_ctx_t *ctx);
void srtp_sha1_update(srtp_sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg);
void srtp_sha1_update(srtp_sha1_ctx_t *ctx,
const uint8_t *M,
int octets_in_msg);
void srtp_sha1_final(srtp_sha1_ctx_t * ctx, uint32_t output[5]);
/*
* The srtp_sha1_core function is INTERNAL to SHA-1, but it is declared
* here because it is also used by the cipher SEAL 3.0 in its key
* setup algorithm.
*/
/*
* srtp_sha1_core(M, H) computes the core sha1 compression function, where M is
* the next part of the message and H is the intermediate state {H0,
* H1, ...}
*
* this function does not do any of the padding required in the
* complete sha1 function
*/
void srtp_sha1_core(const uint32_t M[16], uint32_t hash_value[5]);
#endif /* else OPENSSL */
void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t output[5]);
#ifdef __cplusplus
}

View File

@ -1,32 +1,32 @@
/*
* alloc.c
*
* memory allocation and deallocation
* memory allocation and deallocation
*
* 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
@ -43,7 +43,7 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "alloc.h"
@ -51,9 +51,9 @@
/* the debug module for memory allocation */
srtp_debug_module_t mod_alloc = {
0, /* debugging is off by default */
"alloc" /* printable name for module */
srtp_debug_module_t srtp_mod_alloc = {
0, /* debugging is off by default */
"alloc" /* printable name for module */
};
/*
@ -67,29 +67,35 @@ srtp_debug_module_t mod_alloc = {
#if defined(HAVE_STDLIB_H)
void * srtp_crypto_alloc(size_t size) {
void *ptr;
void *srtp_crypto_alloc(size_t size)
{
void *ptr;
ptr = malloc(size);
if (ptr) {
debug_print(mod_alloc, "(location: %p) allocated", ptr);
} else {
debug_print(mod_alloc, "allocation failed (asked for %d bytes)\n", size);
}
if (!size) {
return NULL;
}
return ptr;
ptr = calloc(1, size);
if (ptr) {
debug_print(srtp_mod_alloc, "(location: %p) allocated", ptr);
} else {
debug_print(srtp_mod_alloc, "allocation failed (asked for %zu bytes)\n",
size);
}
return ptr;
}
void srtp_crypto_free(void *ptr) {
void srtp_crypto_free(void *ptr)
{
debug_print(srtp_mod_alloc, "(location: %p) freed", ptr);
debug_print(mod_alloc, "(location: %p) freed", ptr);
free(ptr);
free(ptr);
}
#else /* we need to define our own memory allocation routines */
#else /* we need to define our own memory allocation routines */
#error no memory allocation defined yet
#error no memory allocation defined yet
#endif

View File

@ -42,63 +42,25 @@
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "alloc.h"
#include "crypto_kernel.h"
#include "cipher_types.h"
/* the debug module for the crypto_kernel */
srtp_debug_module_t srtp_mod_crypto_kernel = {
0, /* debugging is off by default */
"crypto kernel" /* printable name for module */
0, /* debugging is off by default */
"crypto kernel" /* printable name for module */
};
/*
* other generic debug modules that can be included in the kernel
*/
extern srtp_debug_module_t srtp_mod_auth;
extern srtp_debug_module_t srtp_mod_cipher;
extern srtp_debug_module_t mod_stat;
extern srtp_debug_module_t mod_alloc;
/*
* cipher types that can be included in the kernel
*/
extern srtp_cipher_type_t srtp_null_cipher;
extern srtp_cipher_type_t srtp_aes_icm_128;
extern srtp_cipher_type_t srtp_aes_icm_256;
#ifdef OPENSSL
extern srtp_cipher_type_t srtp_aes_icm_192;
extern srtp_cipher_type_t srtp_aes_gcm_128_openssl;
extern srtp_cipher_type_t srtp_aes_gcm_256_openssl;
#endif
/* 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
/*
* auth func types that can be included in the kernel
*/
extern srtp_auth_type_t srtp_null_auth;
extern srtp_auth_type_t srtp_hmac;
/* debug modules for auth types */
extern srtp_debug_module_t srtp_mod_hmac;
/* 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 */
@ -107,13 +69,12 @@ srtp_crypto_kernel_t crypto_kernel = {
#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;
/* check the security state */
if (crypto_kernel.state == srtp_crypto_kernel_state_secure) {
/*
* we're already in the secure state, but we've been asked to
* re-initialize, so we just re-run the self-tests and then return
@ -140,25 +101,24 @@ srtp_err_status_t srtp_crypto_kernel_init ()
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&mod_stat);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&mod_alloc);
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_alloc);
if (status) {
return status;
}
/* load cipher types */
status = srtp_crypto_kernel_load_cipher_type(&srtp_null_cipher, SRTP_NULL_CIPHER);
status = srtp_crypto_kernel_load_cipher_type(&srtp_null_cipher,
SRTP_NULL_CIPHER);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_128, SRTP_AES_ICM_128);
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_128,
SRTP_AES_ICM_128);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_256, SRTP_AES_ICM_256);
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_256,
SRTP_AES_ICM_256);
if (status) {
return status;
}
@ -166,16 +126,19 @@ srtp_err_status_t srtp_crypto_kernel_init ()
if (status) {
return status;
}
#ifdef OPENSSL
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_192, SRTP_AES_ICM_192);
#ifdef GCM
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_192,
SRTP_AES_ICM_192);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_128_openssl, SRTP_AES_GCM_128);
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_128,
SRTP_AES_GCM_128);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_256_openssl, SRTP_AES_GCM_256);
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_256,
SRTP_AES_GCM_256);
if (status) {
return status;
}
@ -205,19 +168,21 @@ srtp_err_status_t srtp_crypto_kernel_init ()
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;
srtp_kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
srtp_kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
/* for each cipher type, describe and test */
while (ctype != NULL) {
srtp_err_report(srtp_err_level_info, "cipher: %s\n", ctype->cipher_type->description);
srtp_err_report(srtp_err_level_info, "cipher: %s\n",
ctype->cipher_type->description);
srtp_err_report(srtp_err_level_info, " self-test: ");
status = srtp_cipher_type_self_test(ctype->cipher_type);
if (status) {
srtp_err_report(srtp_err_level_error, "failed with error code %d\n", status);
srtp_err_report(srtp_err_level_error, "failed with error code %d\n",
status);
exit(status);
}
srtp_err_report(srtp_err_level_info, "passed\n");
@ -226,11 +191,13 @@ srtp_err_status_t srtp_crypto_kernel_status ()
/* for each auth type, describe and test */
while (atype != NULL) {
srtp_err_report(srtp_err_level_info, "auth func: %s\n", atype->auth_type->description);
srtp_err_report(srtp_err_level_info, "auth func: %s\n",
atype->auth_type->description);
srtp_err_report(srtp_err_level_info, " self-test: ");
status = srtp_auth_type_self_test(atype->auth_type);
if (status) {
srtp_err_report(srtp_err_level_error, "failed with error code %d\n", status);
srtp_err_report(srtp_err_level_error, "failed with error code %d\n",
status);
exit(status);
}
srtp_err_report(srtp_err_level_info, "passed\n");
@ -242,7 +209,7 @@ srtp_err_status_t srtp_crypto_kernel_status ()
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;
@ -252,7 +219,7 @@ srtp_err_status_t srtp_crypto_kernel_list_debug_modules ()
srtp_err_report(srtp_err_level_info, " %s ", dm->mod->name);
if (dm->mod->on) {
srtp_err_report(srtp_err_level_info, "(on)\n");
} else{
} else {
srtp_err_report(srtp_err_level_info, "(off)\n");
}
dm = dm->next;
@ -261,7 +228,7 @@ srtp_err_status_t srtp_crypto_kernel_list_debug_modules ()
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
@ -271,8 +238,7 @@ srtp_err_status_t srtp_crypto_kernel_shutdown ()
while (crypto_kernel.cipher_type_list != NULL) {
srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
crypto_kernel.cipher_type_list = ctype->next;
debug_print(srtp_mod_crypto_kernel,
"freeing memory for cipher %s",
debug_print(srtp_mod_crypto_kernel, "freeing memory for cipher %s",
ctype->cipher_type->description);
srtp_crypto_free(ctype);
}
@ -292,8 +258,7 @@ srtp_err_status_t srtp_crypto_kernel_shutdown ()
srtp_kernel_debug_module_t *kdm = crypto_kernel.debug_module_list;
crypto_kernel.debug_module_list = kdm->next;
debug_print(srtp_mod_crypto_kernel,
"freeing memory for debug module %s",
kdm->mod->name);
"freeing memory for debug module %s", kdm->mod->name);
srtp_crypto_free(kdm);
}
@ -303,9 +268,13 @@ srtp_err_status_t srtp_crypto_kernel_shutdown ()
return srtp_err_status_ok;
}
static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type (const srtp_cipher_type_t *new_ct, srtp_cipher_type_id_t id, int replace)
static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type(
const srtp_cipher_type_t *new_ct,
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 */
@ -330,13 +299,14 @@ static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type (const sr
if (!replace) {
return srtp_err_status_bad_param;
}
status = srtp_cipher_type_test(new_ct, ctype->cipher_type->test_data);
status =
srtp_cipher_type_test(new_ct, ctype->cipher_type->test_data);
if (status) {
return status;
}
new_ctype = ctype;
break;
}else if (new_ct == ctype->cipher_type) {
} else if (new_ct == ctype->cipher_type) {
return srtp_err_status_bad_param;
}
ctype = ctype->next;
@ -345,7 +315,8 @@ static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type (const sr
/* if not found, put new_ct at the head of the list */
if (ctype == NULL) {
/* allocate memory */
new_ctype = (srtp_kernel_cipher_type_t*)srtp_crypto_alloc(sizeof(srtp_kernel_cipher_type_t));
new_ctype = (srtp_kernel_cipher_type_t *)srtp_crypto_alloc(
sizeof(srtp_kernel_cipher_type_t));
if (new_ctype == NULL) {
return srtp_err_status_alloc_fail;
}
@ -362,19 +333,26 @@ static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type (const sr
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_load_cipher_type (const srtp_cipher_type_t *new_ct, srtp_cipher_type_id_t id)
srtp_err_status_t srtp_crypto_kernel_load_cipher_type(
const srtp_cipher_type_t *new_ct,
srtp_cipher_type_id_t id)
{
return srtp_crypto_kernel_do_load_cipher_type(new_ct, id, 0);
}
srtp_err_status_t srtp_replace_cipher_type (const srtp_cipher_type_t *new_ct, srtp_cipher_type_id_t id)
srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *new_ct,
srtp_cipher_type_id_t id)
{
return srtp_crypto_kernel_do_load_cipher_type(new_ct, id, 1);
}
srtp_err_status_t srtp_crypto_kernel_do_load_auth_type (const srtp_auth_type_t *new_at, srtp_auth_type_id_t id, int replace)
srtp_err_status_t srtp_crypto_kernel_do_load_auth_type(
const srtp_auth_type_t *new_at,
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 */
@ -405,7 +383,7 @@ srtp_err_status_t srtp_crypto_kernel_do_load_auth_type (const srtp_auth_type_t *
}
new_atype = atype;
break;
}else if (new_at == atype->auth_type) {
} else if (new_at == atype->auth_type) {
return srtp_err_status_bad_param;
}
atype = atype->next;
@ -414,7 +392,8 @@ srtp_err_status_t srtp_crypto_kernel_do_load_auth_type (const srtp_auth_type_t *
/* if not found, put new_at at the head of the list */
if (atype == NULL) {
/* allocate memory */
new_atype = (srtp_kernel_auth_type_t*)srtp_crypto_alloc(sizeof(srtp_kernel_auth_type_t));
new_atype = (srtp_kernel_auth_type_t *)srtp_crypto_alloc(
sizeof(srtp_kernel_auth_type_t));
if (new_atype == NULL) {
return srtp_err_status_alloc_fail;
}
@ -429,21 +408,23 @@ srtp_err_status_t srtp_crypto_kernel_do_load_auth_type (const srtp_auth_type_t *
new_atype->id = id;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_load_auth_type (const srtp_auth_type_t *new_at, srtp_auth_type_id_t id)
srtp_err_status_t srtp_crypto_kernel_load_auth_type(
const srtp_auth_type_t *new_at,
srtp_auth_type_id_t id)
{
return srtp_crypto_kernel_do_load_auth_type(new_at, id, 0);
}
srtp_err_status_t srtp_replace_auth_type (const srtp_auth_type_t *new_at, srtp_auth_type_id_t id)
srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *new_at,
srtp_auth_type_id_t id)
{
return srtp_crypto_kernel_do_load_auth_type(new_at, id, 1);
}
const srtp_cipher_type_t * srtp_crypto_kernel_get_cipher_type (srtp_cipher_type_id_t id)
const srtp_cipher_type_t *srtp_crypto_kernel_get_cipher_type(
srtp_cipher_type_id_t id)
{
srtp_kernel_cipher_type_t *ctype;
@ -460,8 +441,10 @@ const srtp_cipher_type_t * srtp_crypto_kernel_get_cipher_type (srtp_cipher_type_
return NULL;
}
srtp_err_status_t srtp_crypto_kernel_alloc_cipher (srtp_cipher_type_id_t id, srtp_cipher_pointer_t *cp, int key_len, int tag_len)
srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id,
srtp_cipher_pointer_t *cp,
int key_len,
int tag_len)
{
const srtp_cipher_type_t *ct;
@ -481,9 +464,7 @@ srtp_err_status_t srtp_crypto_kernel_alloc_cipher (srtp_cipher_type_id_t id, srt
return ((ct)->alloc(cp, key_len, tag_len));
}
const srtp_auth_type_t * srtp_crypto_kernel_get_auth_type (srtp_auth_type_id_t id)
const srtp_auth_type_t *srtp_crypto_kernel_get_auth_type(srtp_auth_type_id_t id)
{
srtp_kernel_auth_type_t *atype;
@ -500,7 +481,10 @@ const srtp_auth_type_t * srtp_crypto_kernel_get_auth_type (srtp_auth_type_id_t i
return NULL;
}
srtp_err_status_t srtp_crypto_kernel_alloc_auth (srtp_auth_type_id_t id, srtp_auth_pointer_t *ap, int key_len, int tag_len)
srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id,
srtp_auth_pointer_t *ap,
int key_len,
int tag_len)
{
const srtp_auth_type_t *at;
@ -520,12 +504,13 @@ srtp_err_status_t srtp_crypto_kernel_alloc_auth (srtp_auth_type_id_t id, srtp_au
return ((at)->alloc(ap, key_len, tag_len));
}
srtp_err_status_t srtp_crypto_kernel_load_debug_module (srtp_debug_module_t *new_dm)
srtp_err_status_t srtp_crypto_kernel_load_debug_module(
srtp_debug_module_t *new_dm)
{
srtp_kernel_debug_module_t *kdm, *new;
/* defensive coding */
if (new_dm == NULL) {
if (new_dm == NULL || new_dm->name == NULL) {
return srtp_err_status_bad_param;
}
@ -540,7 +525,8 @@ srtp_err_status_t srtp_crypto_kernel_load_debug_module (srtp_debug_module_t *new
/* put new_dm at the head of the list */
/* allocate memory */
new = (srtp_kernel_debug_module_t*)srtp_crypto_alloc(sizeof(srtp_kernel_debug_module_t));
new = (srtp_kernel_debug_module_t *)srtp_crypto_alloc(
sizeof(srtp_kernel_debug_module_t));
if (new == NULL) {
return srtp_err_status_alloc_fail;
}
@ -555,7 +541,7 @@ srtp_err_status_t srtp_crypto_kernel_load_debug_module (srtp_debug_module_t *new
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_set_debug_module (const char *name, int on)
srtp_err_status_t srtp_crypto_kernel_set_debug_module(const char *name, int on)
{
srtp_kernel_debug_module_t *kdm;

View File

@ -43,7 +43,7 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "err.h"
@ -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;
@ -69,16 +69,18 @@ srtp_err_status_t srtp_err_reporting_init ()
return srtp_err_status_ok;
}
static srtp_err_report_handler_func_t * srtp_err_report_handler = NULL;
static srtp_err_report_handler_func_t *srtp_err_report_handler = NULL;
srtp_err_status_t srtp_install_err_report_handler(srtp_err_report_handler_func_t func)
srtp_err_status_t srtp_install_err_report_handler(
srtp_err_report_handler_func_t func)
{
srtp_err_report_handler = func;
return srtp_err_status_ok;
}
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, ...)
{
char msg[512];
va_list args;
if (srtp_err_file != NULL) {
va_start(args, format);
@ -87,16 +89,16 @@ void srtp_err_report (srtp_err_reporting_level_t level, const char *format, ...)
}
if (srtp_err_report_handler != NULL) {
va_start(args, format);
char msg[512];
if (vsnprintf(msg, sizeof(msg), format, args) > 0) {
/* strip trailing \n, callback should not have one */
size_t l = strlen(msg);
if (l && msg[l-1] == '\n') {
msg[l-1] = '\0';
if (l && msg[l - 1] == '\n') {
msg[l - 1] = '\0';
}
srtp_err_report_handler(level, msg);
/*
* NOTE, need to be carefull, there is a potential that octet_string_set_to_zero() could
* NOTE, need to be carefull, there is a potential that
* octet_string_set_to_zero() could
* call srtp_err_report() in the future, leading to recursion
*/
octet_string_set_to_zero(msg, sizeof(msg));

View File

@ -43,14 +43,15 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "key.h"
#define soft_limit 0x10000
srtp_err_status_t srtp_key_limit_set (srtp_key_limit_t key, const srtp_xtd_seq_num_t s)
srtp_err_status_t srtp_key_limit_set(srtp_key_limit_t key,
const srtp_xtd_seq_num_t s)
{
#ifdef NO_64BIT_MATH
if (high32(s) == 0 && low32(s) < soft_limit) {
@ -66,7 +67,8 @@ srtp_err_status_t srtp_key_limit_set (srtp_key_limit_t key, const srtp_xtd_seq_n
return srtp_err_status_ok;
}
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_clone(srtp_key_limit_t original,
srtp_key_limit_t *new_key)
{
if (original == NULL) {
return srtp_err_status_bad_param;
@ -75,21 +77,14 @@ srtp_err_status_t srtp_key_limit_clone (srtp_key_limit_t original, srtp_key_limi
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)
srtp_key_event_t srtp_key_limit_update(srtp_key_limit_t key)
{
#ifdef NO_64BIT_MATH
if (low32(key->num_left) == 0) {
// carry
key->num_left = make64(high32(key->num_left) - 1, low32(key->num_left) - 1);
}else {
key->num_left =
make64(high32(key->num_left) - 1, low32(key->num_left) - 1);
} else {
// no carry
key->num_left = make64(high32(key->num_left), low32(key->num_left) - 1);
}
@ -111,10 +106,9 @@ srtp_key_event_t srtp_key_limit_update (srtp_key_limit_t key)
#else
if (key->num_left < 1)
#endif
{ /* we just hit the hard limit */
{ /* we just hit the hard limit */
key->state = srtp_key_state_expired;
return srtp_key_event_hard_limit;
}
return srtp_key_event_soft_limit;
}

View File

@ -8,26 +8,26 @@
* 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
@ -44,7 +44,7 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#ifdef OPENSSL
@ -53,466 +53,235 @@
#include "datatypes.h"
int
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
};
int
octet_get_weight(uint8_t octet) {
extern int octet_weight[256];
return octet_weight[octet];
}
/*
* bit_string is a buffer that is used to hold output strings, e.g.
* for printing.
*/
/* the value MAX_PRINT_STRING_LEN is defined in datatypes.h */
/* include space for null terminator */
static char bit_string[MAX_PRINT_STRING_LEN + 1];
char bit_string[MAX_PRINT_STRING_LEN];
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' };
return buf[nibble & 0xF];
static uint8_t srtp_nibble_to_hex_char(uint8_t nibble)
{
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];
}
char * srtp_octet_string_hex_string(const void *s, int length) {
const uint8_t *str = (const uint8_t *)s;
int i;
/* double length, since one octet takes two hex characters */
length *= 2;
char *srtp_octet_string_hex_string(const void *s, int length)
{
const uint8_t *str = (const uint8_t *)s;
int i;
/* truncate string if it would be too long */
if (length > MAX_PRINT_STRING_LEN)
length = MAX_PRINT_STRING_LEN-2;
for (i=0; i < length; i+=2) {
bit_string[i] = srtp_nibble_to_hex_char(*str >> 4);
bit_string[i+1] = srtp_nibble_to_hex_char(*str++ & 0xF);
}
bit_string[i] = 0; /* null terminate string */
return bit_string;
}
/* double length, since one octet takes two hex characters */
length *= 2;
char *
v128_hex_string(v128_t *x) {
int i, j;
/* truncate string if it would be too long */
if (length > MAX_PRINT_STRING_LEN)
length = MAX_PRINT_STRING_LEN - 2;
for (i=j=0; i < 16; i++) {
bit_string[j++] = srtp_nibble_to_hex_char(x->v8[i] >> 4);
bit_string[j++] = srtp_nibble_to_hex_char(x->v8[i] & 0xF);
}
bit_string[j] = 0; /* null terminate string */
return bit_string;
}
char *
v128_bit_string(v128_t *x) {
int j, i;
uint32_t mask;
for (j=i=0; j < 4; j++) {
for (mask=0x80000000; mask > 0; mask >>= 1) {
if (x->v32[j] & mask)
bit_string[i] = '1';
else
bit_string[i] = '0';
++i;
for (i = 0; i < length; i += 2) {
bit_string[i] = srtp_nibble_to_hex_char(*str >> 4);
bit_string[i + 1] = srtp_nibble_to_hex_char(*str++ & 0xF);
}
}
bit_string[128] = 0; /* null terminate string */
return bit_string;
bit_string[i] = 0; /* null terminate string */
return bit_string;
}
void
v128_copy_octet_string(v128_t *x, const uint8_t s[16]) {
#ifdef ALIGNMENT_32BIT_REQUIRED
if ((((uint32_t) &s[0]) & 0x3) != 0)
#endif
{
x->v8[0] = s[0];
x->v8[1] = s[1];
x->v8[2] = s[2];
x->v8[3] = s[3];
x->v8[4] = s[4];
x->v8[5] = s[5];
x->v8[6] = s[6];
x->v8[7] = s[7];
x->v8[8] = s[8];
x->v8[9] = s[9];
x->v8[10] = s[10];
x->v8[11] = s[11];
x->v8[12] = s[12];
x->v8[13] = s[13];
x->v8[14] = s[14];
x->v8[15] = s[15];
}
#ifdef ALIGNMENT_32BIT_REQUIRED
else
{
v128_t *v = (v128_t *) &s[0];
char *v128_hex_string(v128_t *x)
{
int i, j;
v128_copy(x,v);
}
for (i = j = 0; i < 16; i++) {
bit_string[j++] = srtp_nibble_to_hex_char(x->v8[i] >> 4);
bit_string[j++] = srtp_nibble_to_hex_char(x->v8[i] & 0xF);
}
bit_string[j] = 0; /* null terminate string */
return bit_string;
}
char *v128_bit_string(v128_t *x)
{
int j, i;
uint32_t mask;
for (j = i = 0; j < 4; j++) {
for (mask = 0x80000000; mask > 0; mask >>= 1) {
if (x->v32[j] & mask)
bit_string[i] = '1';
else
bit_string[i] = '0';
++i;
}
}
bit_string[128] = 0; /* null terminate string */
return bit_string;
}
void v128_copy_octet_string(v128_t *x, const uint8_t s[16])
{
#ifdef ALIGNMENT_32BIT_REQUIRED
if ((((uint32_t)&s[0]) & 0x3) != 0)
#endif
{
x->v8[0] = s[0];
x->v8[1] = s[1];
x->v8[2] = s[2];
x->v8[3] = s[3];
x->v8[4] = s[4];
x->v8[5] = s[5];
x->v8[6] = s[6];
x->v8[7] = s[7];
x->v8[8] = s[8];
x->v8[9] = s[9];
x->v8[10] = s[10];
x->v8[11] = s[11];
x->v8[12] = s[12];
x->v8[13] = s[13];
x->v8[14] = s[14];
x->v8[15] = s[15];
}
#ifdef ALIGNMENT_32BIT_REQUIRED
else {
v128_t *v = (v128_t *)&s[0];
v128_copy(x, v);
}
#endif
}
#ifndef DATATYPES_USE_MACROS /* little functions are not macros */
void v128_left_shift(v128_t *x, int shift)
{
int i;
const int base_index = shift >> 5;
const int bit_index = shift & 31;
void
v128_set_to_zero(v128_t *x) {
_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];
} 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;
if (shift > 127) {
v128_set_to_zero(x);
return;
}
}
/* now wrap up the final portion */
for (i=0; i < base_index; i++)
x->v32[i] = 0;
}
void
v128_left_shift(v128_t *x, int shift) {
int i;
const int base_index = shift >> 5;
const int bit_index = shift & 31;
if (shift > 127) {
v128_set_to_zero(x);
return;
}
if (bit_index == 0) {
for (i=0; i < 4 - base_index; i++)
x->v32[i] = x->v32[i+base_index];
} else {
for (i=0; i < 4 - base_index - 1; i++)
x->v32[i] = (x->v32[i+base_index] >> bit_index) ^
(x->v32[i+base_index+1] << (32 - bit_index));
x->v32[4 - base_index-1] = x->v32[4-1] >> bit_index;
}
/* now wrap up the final portion */
for (i = 4 - base_index; i < 4; i++)
x->v32[i] = 0;
if (bit_index == 0) {
for (i = 0; i < 4 - base_index; i++)
x->v32[i] = x->v32[i + base_index];
} else {
for (i = 0; i < 4 - base_index - 1; i++)
x->v32[i] = (x->v32[i + base_index] >> bit_index) ^
(x->v32[i + base_index + 1] << (32 - bit_index));
x->v32[4 - base_index - 1] = x->v32[4 - 1] >> bit_index;
}
/* now wrap up the final portion */
for (i = 4 - base_index; i < 4; i++)
x->v32[i] = 0;
}
/* functions manipulating bitvector_t */
#ifndef DATATYPES_USE_MACROS /* little functions are not macros */
int
bitvector_get_bit(const bitvector_t *v, int bit_index)
int bitvector_alloc(bitvector_t *v, unsigned long length)
{
return _bitvector_get_bit(v, bit_index);
unsigned long l;
/* Round length up to a multiple of bits_per_word */
length =
(length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1));
l = length / bits_per_word * bytes_per_word;
/* allocate memory, then set parameters */
if (l == 0) {
v->word = NULL;
v->length = 0;
return -1;
} else {
v->word = (uint32_t *)srtp_crypto_alloc(l);
if (v->word == NULL) {
v->length = 0;
return -1;
}
}
v->length = length;
/* initialize bitvector to zero */
bitvector_set_to_zero(v);
return 0;
}
void
bitvector_set_bit(bitvector_t *v, int bit_index)
void bitvector_dealloc(bitvector_t *v)
{
_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;
/* Round length up to a multiple of bits_per_word */
length = (length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1));
l = length / bits_per_word * bytes_per_word;
/* allocate memory, then set parameters */
if (l == 0)
if (v->word != NULL)
srtp_crypto_free(v->word);
v->word = NULL;
else {
v->word = (uint32_t*)srtp_crypto_alloc(l);
if (v->word == NULL) {
v->word = NULL;
v->length = 0;
return -1;
v->length = 0;
}
void bitvector_set_to_zero(bitvector_t *x)
{
/* C99 guarantees that memset(0) will set the value 0 for uint32_t */
memset(x->word, 0, x->length >> 3);
}
void bitvector_left_shift(bitvector_t *x, int shift)
{
int i;
const int base_index = shift >> 5;
const int bit_index = shift & 31;
const int word_length = x->length >> 5;
if (shift >= (int)x->length) {
bitvector_set_to_zero(x);
return;
}
}
v->length = length;
/* initialize bitvector to zero */
bitvector_set_to_zero(v);
return 0;
}
void
bitvector_dealloc(bitvector_t *v) {
if (v->word != NULL)
srtp_crypto_free(v->word);
v->word = NULL;
v->length = 0;
}
void
bitvector_set_to_zero(bitvector_t *x)
{
/* C99 guarantees that memset(0) will set the value 0 for uint32_t */
memset(x->word, 0, x->length >> 3);
}
char *
bitvector_bit_string(bitvector_t *x, char* buf, int len) {
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 (bit_index == 0) {
for (i = 0; i < word_length - base_index; i++)
x->word[i] = x->word[i + base_index];
} else {
for (i = 0; i < word_length - base_index - 1; i++)
x->word[i] = (x->word[i + base_index] >> bit_index) ^
(x->word[i + base_index + 1] << (32 - bit_index));
x->word[word_length - base_index - 1] =
x->word[word_length - 1] >> bit_index;
}
}
buf[i] = 0; /* null terminate string */
return buf;
/* now wrap up the final portion */
for (i = word_length - base_index; i < word_length; i++)
x->word[i] = 0;
}
void
bitvector_left_shift(bitvector_t *x, int shift) {
int i;
const int base_index = shift >> 5;
const int bit_index = shift & 31;
const int word_length = x->length >> 5;
if (shift >= (int)x->length) {
bitvector_set_to_zero(x);
return;
}
if (bit_index == 0) {
for (i=0; i < word_length - base_index; i++)
x->word[i] = x->word[i+base_index];
} else {
for (i=0; i < word_length - base_index - 1; i++)
x->word[i] = (x->word[i+base_index] >> bit_index) ^
(x->word[i+base_index+1] << (32 - bit_index));
x->word[word_length - base_index-1] = x->word[word_length-1] >> bit_index;
}
/* now wrap up the final portion */
for (i = word_length - base_index; i < word_length; i++)
x->word[i] = 0;
}
int
octet_string_is_eq(uint8_t *a, uint8_t *b, int len) {
uint8_t *end = b + len;
uint8_t accumulator = 0;
/*
* 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.
*/
while (b < end)
accumulator |= (*a++ ^ *b++);
/* Return 1 if *not* equal. */
return accumulator != 0;
}
void
srtp_cleanse(void *s, size_t len)
int srtp_octet_string_is_eq(uint8_t *a, uint8_t *b, int len)
{
volatile unsigned char *p = (volatile unsigned char *)s;
while(len--) *p++ = 0;
uint8_t *end = b + len;
uint8_t accumulator = 0;
/*
* 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.
*/
while (b < end)
accumulator |= (*a++ ^ *b++);
/* Return 1 if *not* equal. */
return accumulator != 0;
}
void
octet_string_set_to_zero(void *s, size_t len)
void srtp_cleanse(void *s, size_t len)
{
#ifdef OPENSSL
OPENSSL_cleanse(s, len);
volatile unsigned char *p = (volatile unsigned char *)s;
while (len--)
*p++ = 0;
}
void octet_string_set_to_zero(void *s, size_t len)
{
#if defined(OPENSSL)
OPENSSL_cleanse(s, len);
#else
srtp_cleanse(s, len);
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

View File

@ -1,226 +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 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(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(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(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(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(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(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 (mod_stat.on) {
debug_print(mod_stat, "runs test", NULL);
for (i=0; i < 6; i++)
debug_print(mod_stat, " runs[]: %d", runs[i]);
for (i=0; i < 6; i++)
debug_print(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;
}

View File

@ -43,13 +43,13 @@
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "rdb.h"
#define rdb_bits_in_bitmask (8 * sizeof(v128_t))
/*
* this implementation of a replay database works as follows:
@ -61,7 +61,7 @@
*/
/* srtp_rdb_init initalizes rdb */
srtp_err_status_t srtp_rdb_init (srtp_rdb_t *rdb)
srtp_err_status_t srtp_rdb_init(srtp_rdb_t *rdb)
{
v128_set_to_zero(&rdb->bitmask);
rdb->window_start = 0;
@ -71,9 +71,8 @@ srtp_err_status_t srtp_rdb_init (srtp_rdb_t *rdb)
/*
* srtp_rdb_check checks to see if index appears in rdb
*/
srtp_err_status_t srtp_rdb_check (const srtp_rdb_t *rdb, uint32_t p_index)
srtp_err_status_t srtp_rdb_check(const srtp_rdb_t *rdb, uint32_t p_index)
{
/* if the index appears after (or at very end of) the window, its good */
if (p_index >= rdb->window_start + rdb_bits_in_bitmask) {
return srtp_err_status_ok;
@ -101,35 +100,32 @@ srtp_err_status_t srtp_rdb_check (const srtp_rdb_t *rdb, uint32_t p_index)
* indicated that the index does not appear in the rdb, e.g., a mutex
* should protect the rdb between these calls
*/
srtp_err_status_t srtp_rdb_add_index (srtp_rdb_t *rdb, uint32_t p_index)
srtp_err_status_t srtp_rdb_add_index(srtp_rdb_t *rdb, uint32_t p_index)
{
int delta;
unsigned int delta;
/* here we *assume* that p_index > rdb->window_start */
if (p_index < rdb->window_start)
return srtp_err_status_replay_fail;
delta = (p_index - rdb->window_start);
if (delta < rdb_bits_in_bitmask) {
/* if the p_index is within the window, set the appropriate bit */
v128_set_bit(&rdb->bitmask, delta);
} else {
delta -= rdb_bits_in_bitmask - 1;
/* shift the window forward by delta bits*/
v128_left_shift(&rdb->bitmask, delta);
v128_set_bit(&rdb->bitmask, rdb_bits_in_bitmask - 1);
rdb->window_start += delta;
}
return srtp_err_status_ok;
}
srtp_err_status_t srtp_rdb_increment (srtp_rdb_t *rdb)
srtp_err_status_t srtp_rdb_increment(srtp_rdb_t *rdb)
{
if (rdb->window_start >= 0x7fffffff) {
return srtp_err_status_key_expired;
}
@ -137,7 +133,7 @@ srtp_err_status_t srtp_rdb_increment (srtp_rdb_t *rdb)
return srtp_err_status_ok;
}
uint32_t srtp_rdb_get_value (const srtp_rdb_t *rdb)
uint32_t srtp_rdb_get_value(const srtp_rdb_t *rdb)
{
return rdb->window_start;
}

View File

@ -44,12 +44,11 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <config.h>
#endif
#include "rdbx.h"
/*
* from RFC 3711:
*
@ -64,8 +63,6 @@
* incremented by one (if the packet containing s is authentic).
*/
/*
* rdbx implementation notes
*
@ -83,14 +80,13 @@
* srtp_index_advance(&guess, delta), where delta is the difference.
*
*
* A srtp_rdbx_t consists of a srtp_xtd_seq_num_t and a bitmask. The index is highest
* sequence number that has been received, and the bitmask indicates
* A srtp_rdbx_t consists of a srtp_xtd_seq_num_t and a bitmask. The index is
* highest sequence number that has been received, and the bitmask indicates
* which of the recent indicies have been received as well. The
* highest bit in the bitmask corresponds to the index in the bitmask.
*/
void srtp_index_init (srtp_xtd_seq_num_t *pi)
void srtp_index_init(srtp_xtd_seq_num_t *pi)
{
#ifdef NO_64BIT_MATH
*pi = make64(0, 0);
@ -99,7 +95,7 @@ void srtp_index_init (srtp_xtd_seq_num_t *pi)
#endif
}
void srtp_index_advance (srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s)
void srtp_index_advance(srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s)
{
#ifdef NO_64BIT_MATH
/* a > ~b means a+b will generate a carry */
@ -110,7 +106,6 @@ void srtp_index_advance (srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s)
#endif
}
/*
* srtp_index_guess(local, guess, s)
*
@ -124,24 +119,19 @@ void srtp_index_advance (srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s)
* unsigned integer!
*/
int32_t srtp_index_guess (const srtp_xtd_seq_num_t *local, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s)
int32_t srtp_index_guess(const srtp_xtd_seq_num_t *local,
srtp_xtd_seq_num_t *guess,
srtp_sequence_number_t s)
{
#ifdef NO_64BIT_MATH
uint32_t local_roc = ((high32(*local) << 16) |
(low32(*local) >> 16));
uint32_t local_roc = ((high32(*local) << 16) | (low32(*local) >> 16));
uint16_t local_seq = (uint16_t)(low32(*local));
#else
uint32_t local_roc = (uint32_t)(*local >> 16);
uint16_t local_seq = (uint16_t)*local;
#endif
#ifdef NO_64BIT_MATH
uint32_t guess_roc = ((high32(*guess) << 16) |
(low32(*guess) >> 16));
uint16_t guess_seq = (uint16_t)(low32(*guess));
#else
uint32_t guess_roc = (uint32_t)(*guess >> 16);
uint16_t guess_seq = (uint16_t)*guess;
#endif
uint32_t guess_roc;
uint16_t guess_seq;
int32_t difference;
if (local_seq < seq_num_median) {
@ -163,10 +153,9 @@ int32_t srtp_index_guess (const srtp_xtd_seq_num_t *local, srtp_xtd_seq_num_t *g
}
guess_seq = s;
/* Note: guess_roc is 32 bits, so this generates a 48-bit result! */
/* Note: guess_roc is 32 bits, so this generates a 48-bit result! */
#ifdef NO_64BIT_MATH
*guess = make64(guess_roc >> 16,
(guess_roc << 16) | guess_seq);
*guess = make64(guess_roc >> 16, (guess_roc << 16) | guess_seq);
#else
*guess = (((uint64_t)guess_roc) << 16) | guess_seq;
#endif
@ -179,11 +168,11 @@ int32_t srtp_index_guess (const srtp_xtd_seq_num_t *local, srtp_xtd_seq_num_t *g
*
*/
/*
* srtp_rdbx_init(&r, ws) initializes the srtp_rdbx_t pointed to by r with window size ws
* srtp_rdbx_init(&r, ws) initializes the srtp_rdbx_t pointed to by r with
* window size ws
*/
srtp_err_status_t srtp_rdbx_init (srtp_rdbx_t *rdbx, unsigned long ws)
srtp_err_status_t srtp_rdbx_init(srtp_rdbx_t *rdbx, unsigned long ws)
{
if (ws == 0) {
return srtp_err_status_bad_param;
@ -201,7 +190,7 @@ srtp_err_status_t srtp_rdbx_init (srtp_rdbx_t *rdbx, unsigned long ws)
/*
* srtp_rdbx_dealloc(&r) frees memory for the srtp_rdbx_t pointed to by r
*/
srtp_err_status_t srtp_rdbx_dealloc (srtp_rdbx_t *rdbx)
srtp_err_status_t srtp_rdbx_dealloc(srtp_rdbx_t *rdbx)
{
bitvector_dealloc(&rdbx->bitmask);
@ -215,12 +204,12 @@ srtp_err_status_t srtp_rdbx_dealloc (srtp_rdbx_t *rdbx)
* srtp_err_status_replay_old; otherwise, srtp_err_status_ok is returned.
*
*/
srtp_err_status_t srtp_rdbx_set_roc (srtp_rdbx_t *rdbx, uint32_t roc)
srtp_err_status_t srtp_rdbx_set_roc(srtp_rdbx_t *rdbx, uint32_t roc)
{
bitvector_set_to_zero(&rdbx->bitmask);
#ifdef NO_64BIT_MATH
#error not yet implemented
#error not yet implemented
#else
/* make sure that we're not moving backwards */
@ -240,7 +229,7 @@ srtp_err_status_t srtp_rdbx_set_roc (srtp_rdbx_t *rdbx, uint32_t roc)
* for the srtp_rdbx_t pointed to by rdbx
*
*/
srtp_xtd_seq_num_t srtp_rdbx_get_packet_index (const srtp_rdbx_t *rdbx)
srtp_xtd_seq_num_t srtp_rdbx_get_packet_index(const srtp_rdbx_t *rdbx)
{
return rdbx->index;
}
@ -250,7 +239,7 @@ srtp_xtd_seq_num_t srtp_rdbx_get_packet_index (const srtp_rdbx_t *rdbx)
* for the srtp_rdbx_t pointed to by rdbx
*
*/
unsigned long srtp_rdbx_get_window_size (const srtp_rdbx_t *rdbx)
unsigned long srtp_rdbx_get_window_size(const srtp_rdbx_t *rdbx)
{
return bitvector_get_length(&rdbx->bitmask);
}
@ -259,16 +248,17 @@ unsigned long srtp_rdbx_get_window_size (const srtp_rdbx_t *rdbx)
* srtp_rdbx_check(&r, delta) checks to see if the srtp_xtd_seq_num_t
* which is at rdbx->index + delta is in the rdb
*/
srtp_err_status_t srtp_rdbx_check (const srtp_rdbx_t *rdbx, int delta)
srtp_err_status_t srtp_rdbx_check(const srtp_rdbx_t *rdbx, int delta)
{
if (delta > 0) { /* if delta is positive, it's good */
if (delta > 0) { /* if delta is positive, it's good */
return srtp_err_status_ok;
} else if ((int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta < 0) {
/* if delta is lower than the bitmask, it's bad */
return srtp_err_status_replay_old;
} else if (bitvector_get_bit(&rdbx->bitmask,
(int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta) == 1) {
} else if (bitvector_get_bit(
&rdbx->bitmask,
(int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta) ==
1) {
/* delta is within the window, so check the bitmask */
return srtp_err_status_replay_fail;
}
@ -285,17 +275,18 @@ srtp_err_status_t srtp_rdbx_check (const srtp_rdbx_t *rdbx, int delta)
* indicated that the index does not appear in the rdbx, e.g., a mutex
* should protect the rdbx between these calls if need be
*/
srtp_err_status_t srtp_rdbx_add_index (srtp_rdbx_t *rdbx, int delta)
srtp_err_status_t srtp_rdbx_add_index(srtp_rdbx_t *rdbx, int delta)
{
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);
bitvector_set_bit(&rdbx->bitmask,
bitvector_get_length(&rdbx->bitmask) - 1);
} else {
/* delta is in window */
bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) - 1 + delta);
bitvector_set_bit(&rdbx->bitmask,
bitvector_get_length(&rdbx->bitmask) - 1 + delta);
}
/* note that we need not consider the case that delta == 0 */
@ -303,8 +294,6 @@ srtp_err_status_t srtp_rdbx_add_index (srtp_rdbx_t *rdbx, int delta)
return srtp_err_status_ok;
}
/*
* srtp_rdbx_estimate_index(rdbx, guess, s)
*
@ -313,9 +302,10 @@ srtp_err_status_t srtp_rdbx_add_index (srtp_rdbx_t *rdbx, int delta)
* index to which s corresponds, and returns the difference between
* *guess and the locally stored synch info
*/
int32_t srtp_rdbx_estimate_index (const srtp_rdbx_t *rdbx, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s)
int32_t srtp_rdbx_estimate_index(const srtp_rdbx_t *rdbx,
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
@ -326,12 +316,13 @@ int32_t srtp_rdbx_estimate_index (const srtp_rdbx_t *rdbx, srtp_xtd_seq_num_t *g
#ifdef NO_64BIT_MATH
/* seq_num_median = 0x8000 */
if (high32(rdbx->index) > 0 ||
low32(rdbx->index) > seq_num_median)
if (high32(rdbx->index) > 0 || low32(rdbx->index) > seq_num_median)
#else
if (rdbx->index > seq_num_median)
#endif
{ return srtp_index_guess(&rdbx->index, guess, s); }
{
return srtp_index_guess(&rdbx->index, guess, s);
}
#ifdef NO_64BIT_MATH
*guess = make64(0, (uint32_t)s);
@ -372,12 +363,12 @@ uint32_t srtp_rdbx_get_roc(const srtp_rdbx_t *rdbx)
* rollover counter value, then the function returns
* srtp_err_status_replay_old, otherwise, srtp_err_status_ok is returned.
*/
srtp_err_status_t srtp_rdbx_set_roc_seq (srtp_rdbx_t *rdbx,
uint32_t roc,
uint16_t seq)
srtp_err_status_t srtp_rdbx_set_roc_seq(srtp_rdbx_t *rdbx,
uint32_t roc,
uint16_t seq)
{
#ifdef NO_64BIT_MATH
#error not yet implemented
#error not yet implemented
#else
/* make sure that we're not moving backwards */
@ -393,4 +384,3 @@ srtp_err_status_t srtp_rdbx_set_roc_seq (srtp_rdbx_t *rdbx,
return srtp_err_status_ok;
}

View File

@ -1,174 +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 */

File diff suppressed because it is too large Load Diff

View File

@ -7,26 +7,26 @@
* 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
@ -55,21 +55,21 @@
#include "cipher.h"
#include "auth.h"
#include "aes.h"
#include "key.h"
#include "crypto_kernel.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SRTP_VER_STRING PACKAGE_STRING
#define SRTP_VERSION PACKAGE_VERSION
#define SRTP_VER_STRING PACKAGE_STRING
#define SRTP_VERSION PACKAGE_VERSION
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
* the following declarations are libSRTP internal functions
*/
/*
@ -78,7 +78,6 @@ typedef srtp_stream_ctx_t *srtp_stream_t;
*/
srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
/*
* srtp_stream_init_keys(s, k) (re)initializes the srtp_stream_t s by
* deriving all of the needed keys using the KDF and the key k.
@ -88,29 +87,23 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp,
const unsigned int current_mki_index);
/*
* srtp_stream_init_all_master_keys(s, k, m) (re)initializes the srtp_stream_t s by
* deriving all of the needed keys for all the master keys using the KDF and the keys from k.
* srtp_stream_init_all_master_keys(s, k, m) (re)initializes the srtp_stream_t s
* by deriving all of the needed keys for all the master keys using the KDF and
* the keys from k.
*/
srtp_err_status_t srtp_steam_init_all_master_keys(srtp_stream_ctx_t *srtp,
unsigned char *key,
srtp_master_key_t **keys,
const unsigned int max_master_keys);
srtp_err_status_t srtp_steam_init_all_master_keys(
srtp_stream_ctx_t *srtp,
unsigned char *key,
srtp_master_key_t **keys,
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
* libsrtp internal datatypes
*/
srtp_err_status_t srtp_stream_init(srtp_stream_t srtp, const srtp_policy_t *p);
/*
* libsrtp internal datatypes
*/
typedef enum direction_t {
dir_unknown = 0,
dir_srtp_sender = 1,
dir_srtp_receiver = 2
typedef enum direction_t {
dir_unknown = 0,
dir_srtp_sender = 1,
dir_srtp_receiver = 2
} direction_t;
/*
@ -119,56 +112,58 @@ typedef enum direction_t {
* MKI ID which is used to identify the session keys.
*/
typedef struct srtp_session_keys_t {
srtp_cipher_t *rtp_cipher;
srtp_cipher_t *rtp_xtn_hdr_cipher;
srtp_auth_t *rtp_auth;
srtp_cipher_t *rtcp_cipher;
srtp_auth_t *rtcp_auth;
uint8_t salt[SRTP_AEAD_SALT_LEN];
uint8_t c_salt[SRTP_AEAD_SALT_LEN];
uint8_t *mki_id;
unsigned int mki_size;
srtp_key_limit_ctx_t *limit;
srtp_cipher_t *rtp_cipher;
srtp_cipher_t *rtp_xtn_hdr_cipher;
srtp_auth_t *rtp_auth;
srtp_cipher_t *rtcp_cipher;
srtp_auth_t *rtcp_auth;
uint8_t salt[SRTP_AEAD_SALT_LEN];
uint8_t c_salt[SRTP_AEAD_SALT_LEN];
uint8_t *mki_id;
unsigned int mki_size;
srtp_key_limit_ctx_t *limit;
} srtp_session_keys_t;
/*
/*
* an srtp_stream_t has its own SSRC, encryption key, authentication
* key, sequence number, and replay database
*
*
* note that the keys might not actually be unique, in which case the
* srtp_cipher_t and srtp_auth_t pointers will point to the same structures
*/
typedef struct srtp_stream_ctx_t_ {
uint32_t ssrc;
srtp_session_keys_t *session_keys;
unsigned int num_master_keys;
srtp_rdbx_t rtp_rdbx;
srtp_sec_serv_t rtp_services;
srtp_rdb_t rtcp_rdb;
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 */
uint32_t ssrc;
srtp_session_keys_t *session_keys;
unsigned int num_master_keys;
srtp_rdbx_t rtp_rdbx;
srtp_sec_serv_t rtp_services;
srtp_rdb_t rtcp_rdb;
srtp_sec_serv_t rtcp_services;
direction_t direction;
int allow_repeat_tx;
int *enc_xtn_hdr;
int enc_xtn_hdr_count;
uint32_t pending_roc;
/*
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 */
struct srtp_stream_ctx_t_ *stream_template; /* act as template for other streams */
void *user_data; /* user custom data */
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 */
} srtp_ctx_t_;
/*
* srtp_hdr_t represents an RTP or SRTP header. The bit-fields in
* this structure should be declared "unsigned int" instead of
@ -211,18 +206,16 @@ typedef struct {
#endif
typedef struct {
uint16_t profile_specific; /* profile-specific info */
uint16_t length; /* number of 32-bit words in extension */
uint16_t profile_specific; /* profile-specific info */
uint16_t length; /* number of 32-bit words in extension */
} srtp_hdr_xtnd_t;
/*
* srtcp_hdr_t represents a secure rtcp header
*
* in this implementation, an srtcp header is assumed to be 32-bit
* alinged
* aligned
*/
#ifndef WORDS_BIGENDIAN
@ -237,10 +230,10 @@ typedef struct {
} srtcp_hdr_t;
typedef struct {
unsigned int index : 31; /* srtcp packet index in network order! */
unsigned int e : 1; /* encrypted? 1=yes */
/* optional mikey/etc go here */
/* and then the variable-length auth tag */
unsigned int index : 31; /* srtcp packet index in network order! */
unsigned int e : 1; /* encrypted? 1=yes */
/* optional mikey/etc go here */
/* and then the variable-length auth tag */
} srtcp_trailer_t;
#else /* BIG_ENDIAN */
@ -255,31 +248,30 @@ typedef struct {
} srtcp_hdr_t;
typedef struct {
unsigned int e : 1; /* encrypted? 1=yes */
unsigned int index : 31; /* srtcp packet index */
/* optional mikey/etc go here */
/* and then the variable-length auth tag */
unsigned int e : 1; /* encrypted? 1=yes */
unsigned int index : 31; /* srtcp packet index */
/* optional mikey/etc go here */
/* and then the variable-length auth tag */
} srtcp_trailer_t;
#endif
/*
* srtp_handle_event(srtp, srtm, evnt) calls the event handling
* function, if there is one.
*
* This macro is not included in the documentation as it is
* This macro is not included in the documentation as it is
* an internal-only function.
*/
#define srtp_handle_event(srtp, strm, evnt) \
if(srtp_event_handler) { \
srtp_event_data_t data; \
data.session = srtp; \
data.ssrc = ntohl(strm->ssrc); \
data.event = evnt; \
srtp_event_handler(&data); \
}
#define srtp_handle_event(srtp, strm, evnt) \
if (srtp_event_handler) { \
srtp_event_data_t data; \
data.session = srtp; \
data.ssrc = ntohl(strm->ssrc); \
data.event = evnt; \
srtp_event_handler(&data); \
}
#ifdef __cplusplus
}

View File

@ -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 */

View File

@ -1,258 +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 OPENSSL
//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_print(mod_srtp, "EKT not in use", NULL);
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 */
}

File diff suppressed because it is too large Load Diff