From b0169c1c896a882f2b66c007b50360bb42cfd684 Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Thu, 9 Jan 2020 17:17:45 +0400 Subject: [PATCH] [Build-System] Update libsrtp to 2.3.0 --- libs/srtp/Makefile.am | 6 +- libs/srtp/configure.ac | 645 ++++++++++-------- libs/srtp/crypto/Makefile.in | 41 +- libs/srtp/crypto/cipher/aes_gcm_nss.c | 609 +++++++++++++++++ libs/srtp/crypto/cipher/aes_gcm_ossl.c | 17 +- libs/srtp/crypto/cipher/aes_icm_nss.c | 562 +++++++++++++++ libs/srtp/crypto/cipher/aes_icm_ossl.c | 11 +- libs/srtp/crypto/cipher/cipher.c | 57 +- libs/srtp/crypto/cipher/null_cipher.c | 2 +- libs/srtp/crypto/hash/sha1.c | 12 +- .../include/{aes_gcm_ossl.h => aes_gcm.h} | 35 +- .../include/{aes_icm_ossl.h => aes_icm_ext.h} | 22 + libs/srtp/crypto/include/cipher_priv.h | 62 ++ libs/srtp/crypto/include/cipher_types.h | 9 +- libs/srtp/crypto/include/datatypes.h | 6 +- libs/srtp/crypto/include/err.h | 5 + libs/srtp/crypto/kernel/alloc.c | 2 +- libs/srtp/crypto/kernel/crypto_kernel.c | 6 +- libs/srtp/crypto/kernel/err.c | 2 +- libs/srtp/crypto/math/datatypes.c | 4 +- libs/srtp/crypto/math/stat.c | 2 +- libs/srtp/crypto/replay/ut_sim.c | 5 +- libs/srtp/crypto/test/cipher_driver.c | 65 +- libs/srtp/crypto/test/datatypes_driver.c | 26 + libs/srtp/crypto/test/stat_driver.c | 22 +- libs/srtp/include/srtp.h | 18 +- libs/srtp/include/srtp_priv.h | 2 +- libs/srtp/libsrtp.2017.vcxproj | 5 + libs/srtp/srtp/ekt.c | 4 +- libs/srtp/srtp/srtp.c | 135 ++-- libs/srtp/test/getopt_s.c | 3 +- libs/srtp/test/rdbx_driver.c | 9 +- libs/srtp/test/replay_driver.c | 4 +- libs/srtp/test/roc_driver.c | 2 +- libs/srtp/test/rtp.c | 4 +- libs/srtp/test/rtp_decoder.c | 337 +++++++-- libs/srtp/test/rtp_decoder.h | 27 +- libs/srtp/test/rtpw.c | 7 +- libs/srtp/test/rtpw_test.sh | 7 +- libs/srtp/test/rtpw_test_gcm.sh | 7 +- libs/srtp/test/srtp_driver.c | 82 +-- libs/srtp/test/test_srtp.c | 16 +- libs/srtp/test/util.c | 6 +- 43 files changed, 2279 insertions(+), 631 deletions(-) create mode 100644 libs/srtp/crypto/cipher/aes_gcm_nss.c create mode 100644 libs/srtp/crypto/cipher/aes_icm_nss.c rename libs/srtp/crypto/include/{aes_gcm_ossl.h => aes_gcm.h} (80%) rename libs/srtp/crypto/include/{aes_icm_ossl.h => aes_icm_ext.h} (87%) create mode 100644 libs/srtp/crypto/include/cipher_priv.h diff --git a/libs/srtp/Makefile.am b/libs/srtp/Makefile.am index caff627c76..3525e2c48a 100644 --- a/libs/srtp/Makefile.am +++ b/libs/srtp/Makefile.am @@ -17,7 +17,7 @@ libsrtp_la_SOURCES = srtp/srtp.c srtp/ekt.c crypto/cipher/cipher.c crypto/cip crypto/kernel/err.c \ crypto/replay/rdb.c crypto/replay/rdbx.c crypto/replay/ut_sim.c -libsrtp_la_LDFLAGS = -version-info 1:42:1 +libsrtp_la_LDFLAGS = -version-info 2:3:0 EXTRA_DIST= @@ -29,10 +29,6 @@ libsrtp_la_SOURCES += crypto/hash/sha1.c crypto/hash/hmac.c libsrtp_la_SOURCES += crypto/cipher/aes_icm.c crypto/cipher/aes.c endif -if GDOI -libsrtp_la_SOURCES += gdoi/srtp+gdoi.c -endif - library_includedir = $(prefix)/include/srtp library_include_HEADERS = include/srtp.h include/ut_sim.h crypto/include/auth.h \ crypto/include/cipher_types.h \ diff --git a/libs/srtp/configure.ac b/libs/srtp/configure.ac index 288d0e970a..021ceeebc5 100644 --- a/libs/srtp/configure.ac +++ b/libs/srtp/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.59) -AC_INIT(srtp, 1.4.2, mcgrew@cisco.com) +AC_INIT(srtp, 2.3.0, mcgrew@cisco.com) AC_CONFIG_AUX_DIR(build) AM_INIT_AUTOMAKE @@ -11,161 +11,155 @@ LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS" AC_LANG_C # Checks for programs. AC_PROG_CC -AC_PROG_AWK -AC_PROG_MAKE_SET +AC_PROG_CPP +AC_PROG_CXX +AC_ARG_VAR( + [EXTRA_CFLAGS], + [C compiler flags appended to the regular C compiler flags instead of overriding them]) +AM_PROG_AR AC_PROG_INSTALL AC_PROG_LIBTOOL -AX_COMPILER_VENDOR +AC_PROG_SED -# Optimization -AC_ARG_ENABLE(optimization, -[AC_HELP_STRING([--enable-optimization],[Set if you want us to add max optimising compiler flags])],[enable_optimizer="$enableval"],[enable_optimizer="no"]) +dnl Check the byte order +AC_C_BIGENDIAN -if test "${enable_optimizer}" = "yes" ; then - AC_DEFINE([OPTIMZER],[],[Enable Optimization.]) - AX_CC_MAXOPT -fi +AC_CANONICAL_HOST -# Enable debugging -AC_ARG_ENABLE(debug, -[AC_HELP_STRING([--enable-debug],[build with debug information])],[enable_debug="$enable_debug"],[enable_debug="yes"]) - -if test "${enable_debug}" = "yes"; then - AC_DEFINE([DEBUG],[],[Enable extra debugging.]) - AX_CFLAGS_WARN_ALL_ANSI -fi - - -AM_CONDITIONAL([WANT_DEBUG],[test "${enable_debug}" = "yes"]) - -IN_LINE=inline - -case "$host" in - *-solaris2*) - if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then - SOLINK="-Bdynamic -dy -G" - new_AM_CFLAGS="-KPIC -DPIC" - new_AM_LDFLAGS="-R${prefix}/lib" - FUNC_DEF=__func__ - IN_LINE="" - elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then - SOLINK="-Bdynamic -dy -G" - new_AM_CFLAGS="-fPIC -Wall -O4 -fexpensive-optimizations -funroll-loops" - new_AM_LDFLAGS="" - IN_LINE=inline - fi - ;; - *-darwin*) - if test "x${ax_cv_c_compiler_vendor}"="xgnu" ; then - SOLINK="-dynamic -bundle -force-flat-namespace" - new_AM_CFLAGS="-DMACOSX" - new_AM_LDFLAGS="" - fi - ;; - x86_64-*-linux-gnu) - if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then - SOLINK="-Bdynamic -dy -G" - new_AM_CFLAGS="-KPIC -DPIC" - new_AM_LDFLAGS="-R${prefix}/lib" - FUNC_DEF=__func__ - elif test "x${ax_cv_c_compiler_vendor}"="xgnu" ; then - SOLINK="-shared -Xlinker -x" - new_AM_CFLAGS="-fPIC -Wall -O4 -fexpensive-optimizations -funroll-loops" - new_AM_LDFLAGS="" - fi - ;; - i*6-*-linux-gnu) - if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then - SOLINK="-Bdynamic -dy -G" - new_AM_CFLAGS="-KPIC -DPIC" - new_AM_LDFLAGS="-R${prefix}/lib" - FUNC_DEF=__func__ - elif test "x${ax_cv_c_compiler_vendor}"="xgnu" ; then - SOLINK="-shared -Xlinker -x" - new_AM_CFLAGS="-fpic -Wall -O4 -fexpensive-optimizations -funroll-loops" - new_AM_LDFLAGS="" - fi - ;; - i*6*-*-freebsd*) - SOLINK="-shared -Xlinker -x" - new_AM_CFLAGS="-fPIC -Wall -O4 -fexpensive-optimizations -funroll-loops" - new_AM_LDFLAGS="" - ;; - x86_64-*-freebsd*|amd64-*-freebsd*) - SOLINK="-shared -Xlinker -x" - new_AM_CFLAGS="-fPIC -Wall -O4 -fexpensive-optimizations -funroll-loops" - new_AM_LDFLAGS="" - ;; +dnl check host_cpu type, set defines appropriately +case $host_cpu in + i*86 | x86_64 ) + AC_DEFINE([CPU_CISC], [1], [Define if building for a CISC machine (e.g. Intel).]) + AC_DEFINE([HAVE_X86], [1], [Define to use X86 inlined assembly code]) + ;; + * ) + AC_DEFINE([CPU_RISC], [1], [Define if building for a RISC machine (assume slow byte access).]) + ;; esac -# Enable 64 bit build -AC_ARG_ENABLE(64, -[AC_HELP_STRING([--enable-64],[build with 64 bit support])],[enable_64="$enable_64"],[enable_64="no"]) +dnl Check if we are on a Windows platform. +case $host_os in + *cygwin*|*mingw* ) + EXE=.exe + ;; + * ) + EXE="" + ;; +esac +AC_SUBST([EXE]) # define executable suffix; this is needed for `make clean' -if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then - if test "${enable_64}" = "yes"; then - new_AM_CFLAGS="$new_AM_CFLAGS -m64" +dnl Checks for supported compiler flags. +supported_cflags="" +if test "$EMPTY_CFLAGS" = "no"; then + supported_cflags="$CFLAGS" +fi + +dnl For accurate detection, we need warnings as errors. +dnl I.e. Clang will issue a warning about unsupported flags. +dnl For the compilation to fail, those warnings needs to be upgraded to errors. +dnl This will be removed again once the tests are complete (see below). +WERROR="" +for w in -Werror -errwarn; do + if test "x$WERROR" = "x"; then + AC_MSG_CHECKING([whether ${CC-c} accepts $w]) + save_cflags="$CFLAGS" + AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$w"], [CFLAGS="$CFLAGS $w"]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])], + [WERROR="$w" + AC_MSG_RESULT([yes])], + [CFLAGS="$save_cflags" + AC_MSG_RESULT([no])]) + fi +done + +dnl Note that -fPIC is not explicitly added to LDFLAGS. +dnl Since the compiler is used as the link driver, CFLAGS will be part of the +dnl link line as well and the linker will get the flag from there. +dnl Adding it to LDFLAGS explicitly would duplicate the flag on the link line, +dnl but otherwise do no harm. +AC_MSG_CHECKING([whether ${CC-c} accepts -fPIC]) +save_cflags="$CFLAGS" +AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="-fPIC"], [CFLAGS="$CFLAGS -fPIC"]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])], + [AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="-fPIC"], [supported_cflags="$supported_cflags -fPIC"]) + AC_MSG_RESULT([yes])], + [CFLAGS="$save_cflags" + AC_MSG_RESULT([no])]) + +if test "$EMPTY_CFLAGS" = "yes"; then + for f in -Wall -pedantic -Wstrict-prototypes; do + AC_MSG_CHECKING([whether ${CC-c} accepts $f]) + save_cflags="$CFLAGS" + AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$f"], [CFLAGS="$CFLAGS $f"]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])], + [AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"]) + AC_MSG_RESULT([yes])], + [CFLAGS="$save_cflags" + AC_MSG_RESULT([no])]) + done + + OOPT="" + for f in -O4 -O3; do + if test "x$OOPT" = "x"; then + AC_MSG_CHECKING([whether ${CC-c} accepts $f]) + save_cflags="$CFLAGS" + AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$f"], [CFLAGS="$CFLAGS $f"]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])], + [AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"]) + OOPT="$f" + AC_MSG_RESULT([yes])], + [CFLAGS="$save_cflags" + AC_MSG_RESULT([no])]) fi + done + + for f in -fexpensive-optimizations -funroll-loops; do + AC_MSG_CHECKING([whether ${CC-c} accepts $f]) + save_cflags="$CFLAGS" + AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$f"], [CFLAGS="$CFLAGS $f"]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])], + [AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"]) + AC_MSG_RESULT([yes])], + [CFLAGS="$save_cflags" + AC_MSG_RESULT([no])]) + done fi -AC_SUBST(new_AM_CFLAGS) -AC_SUBST(new_AM_LDFLAGS) -AC_SUBST(SOLINK) -if test "x$FUNC_DEF" != "x"; then - AC_DEFINE_UNQUOTED([__FUNCTION__],[$FUNC_DEF],[define it the right way ;)]) -fi -AC_DEFINE_UNQUOTED([inline],[$IN_LINE],[sunpro is bad at inline]) +dnl When turning off warnigns, we're expecting unrecognized command line option errors if they're not +dnl supported. However, the -Wno- form isn't consulted unless a warning is triggered. +dnl At least that's the case for GCC. So to check which warnings we can turn off, we need to check +dnl if they can be turned on, thereby forcing GCC to take the argument into account right away. +for f in -Wno-language-extension-token; do + AC_MSG_CHECKING([whether ${CC-c} accepts $f]) + save_cflags="$CFLAGS" + testf=$(echo "$f" | $SED 's|-Wno-\(.*\)|-W\1|g') + AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$testf"], [CFLAGS="$CFLAGS $testf"]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])], + [AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"]) + AC_MSG_RESULT([yes])], + [CFLAGS="$save_cflags" + AC_MSG_RESULT([no])]) +done - -AC_ARG_ENABLE(kernel-linux, - [AS_HELP_STRING([--enable-kernel-linux], - [build library to run in Linux kernel context])], - [], enable_kernel_linux=no) -AC_MSG_CHECKING(whether to build for Linux kernel context) -if test "$enable_kernel_linux" = "yes"; then - AC_DEFINE(SRTP_KERNEL, 1, - [Define to compile for kernel contexts.]) - AC_DEFINE(SRTP_KERNEL_LINUX, 1, - [Define to compile for Linux kernel context.]) -fi -AC_MSG_RESULT($enable_kernel_linux) - -dnl Check for /dev/urandom -AC_CHECK_FILE(/dev/urandom, DEV_URANDOM=/dev/urandom, - [AC_CHECK_FILE(/dev/random, DEV_URANDOM=/dev/random)]) +dnl Remowing -Werror again +CFLAGS="$supported_cflags" dnl Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(stdlib.h) -AC_CHECK_HEADERS(unistd.h) -AC_CHECK_HEADERS(stdint.h) -AC_CHECK_HEADERS(sys/uio.h) -AC_CHECK_HEADERS(inttypes.h) -AC_CHECK_HEADERS(sys/types.h) -AC_CHECK_HEADERS(machine/types.h) -AC_CHECK_HEADERS(sys/int_types.h) - -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ -#include -#include -]],[[ -uint64_t y = 0x1122334455667788LL; -bswap_64(y); -]])],byteswap_cv_bswap_64_usable=yes,byteswap_cv_bswap_64_usable=no) - -if test "x${byteswap_cv_bswap_64_usable}" = "xyes" ; then -AC_DEFINE([HAVE_BYTESWAP_H],1,[define if you have a usable bswap_64 in byteswap.h]) -fi +AC_CHECK_HEADERS( + [unistd.h byteswap.h stdint.h sys/uio.h inttypes.h sys/types.h machine/types.h sys/int_types.h], + [], [], [AC_INCLUDES_DEFAULT]) dnl socket() and friends -AC_CHECK_HEADERS(sys/socket.h netinet/in.h arpa/inet.h) -AC_CHECK_HEADERS(windows.h, [AC_CHECK_HEADERS(winsock2.h)]) +AC_CHECK_HEADERS([sys/socket.h netinet/in.h arpa/inet.h], [], [], [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS( + [windows.h], + [AC_CHECK_HEADERS([winsock2.h], [], [], [AC_INCLUDES_DEFAULT])], + [], [AC_INCLUDES_DEFAULT]) -AC_CHECK_HEADERS(syslog.h) - -AC_CHECK_TYPES([int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,uint64_t]) -AC_CHECK_SIZEOF(unsigned long) -AC_CHECK_SIZEOF(unsigned long long) +AC_CHECK_TYPES([int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, uint64_t]) +AC_CHECK_SIZEOF([unsigned long]) +AC_CHECK_SIZEOF([unsigned long long]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -173,176 +167,267 @@ AC_C_INLINE AC_TYPE_SIZE_T dnl Checks for library functions. -AC_CHECK_FUNCS(socket inet_aton usleep sigaction) +AC_CHECK_FUNCS([socket inet_aton usleep sigaction]) dnl Find socket function if not found yet. if test "x$ac_cv_func_socket" = "xno"; then - AC_CHECK_LIB(socket, socket) + AC_CHECK_LIB([socket], [socket]) AC_MSG_CHECKING([for socket in -lwsock32]) SAVELIBS="$LIBS" LIBS="$LIBS -lwsock32" - AC_TRY_LINK([ + AC_LINK_IFELSE( + [AC_LANG_SOURCE([ #include -],[ -socket(0, 0, 0); -], - ac_cv_func_socket=yes - AC_MSG_RESULT(yes), - LIBS="$SAVELIBS" - AC_MSG_RESULT(no)) +int main(void) +{ + int fd = socket(0, 0, 0); + if (fd < 0) + return -1; + else + return 0; +} + ])], + [ac_cv_func_socket=yes + AC_MSG_RESULT([yes])], + [LIBS="$SAVELIBS" + AC_MSG_RESULT([no])]) fi -dnl Check the byte order -AC_C_BIGENDIAN - - -dnl check host_cpu type, set defines appropriately -case $host_cpu in - i*86 | x86_64 ) - AC_DEFINE(CPU_CISC, 1, - [Define if building for a CISC machine (e.g. Intel).]) - # Do not enable use of asm for MACOSX - if test "x$new_AM_CFLAGS" != "x-DMACOSX"; then - AC_DEFINE(HAVE_X86, 1, - [Define to use X86 inlined assembly code]) - fi - ;; - * ) - # CPU_RISC is only supported for big endian machines. - if test "$ac_cv_c_bigendian" = "yes"; then - AC_DEFINE(CPU_RISC, 1, - [Define if building for a RISC machine (assume slow byte access).]) - else - AC_DEFINE(CPU_CISC, 1) - fi - ;; -esac - -dnl Check if we're on a Windows platform. -case $host_os in - *cygwin*|*mingw* ) - EXE=.exe;; - * ) EXE="";; -esac - -AC_SUBST(EXE) # define executable suffix; this is needed for `make clean' - -AC_MSG_CHECKING(whether to compile in debugging) -AC_ARG_ENABLE(debug, - [AS_HELP_STRING([--disable-debug], - [do not compile in dynamic debugging system])], - [], enable_debug=yes) -if test "$enable_debug" = "yes"; then - AC_DEFINE(ENABLE_DEBUGGING, 1, - [Define to compile in dynamic debugging system.]) +AC_MSG_CHECKING([whether to enable debug logging in all modules]) +AC_ARG_ENABLE([debug-logging], + [AS_HELP_STRING([--enable-debug-logging], [Enable debug logging in all modules])], + [], enable_debug_logging=no) +if test "$enable_debug_logging" = "yes"; then + AC_DEFINE([ENABLE_DEBUG_LOGGING], [1], [Define to enabled debug logging for all mudules.]) fi -AC_MSG_RESULT($enable_debug) +AC_MSG_RESULT([$enable_debug_logging]) -AC_MSG_CHECKING(whether to use ISMAcryp code) -AC_ARG_ENABLE(generic-aesicm, - [AS_HELP_STRING([--enable-generic-aesicm], - [compile in changes for ISMAcryp])], - [], enable_generic_aesicm=no) -if test "$enable_generic_aesicm" = "yes"; then - AC_DEFINE(GENERIC_AESICM, 1, [Define this to use ISMAcryp code.]) -fi -AC_MSG_RESULT($enable_generic_aesicm) +PKG_PROG_PKG_CONFIG +AS_IF([test "x$PKG_CONFIG" != "x"], [PKG_CONFIG="$PKG_CONFIG --static"]) + +AC_MSG_CHECKING([whether to leverage OpenSSL crypto]) +AC_ARG_ENABLE([openssl], + [AS_HELP_STRING([--enable-openssl], [compile in OpenSSL crypto engine])], + [], [enable_openssl=no]) +AC_MSG_RESULT([$enable_openssl]) + +AC_MSG_CHECKING([whether to leverage NSS crypto]) +AC_ARG_ENABLE([nss], + [AS_HELP_STRING([--enable-nss], [compile in NSS crypto engine])], + [], [enable_nss=no]) +AC_MSG_RESULT([$enable_nss]) -AC_MSG_CHECKING(whether to leverage OpenSSL crypto) -AC_ARG_ENABLE(openssl, - [AS_HELP_STRING([--enable-openssl], - [compile in OpenSSL crypto engine])], - [], enable_openssl=no) if test "$enable_openssl" = "yes"; then - echo $enable_openssl - LDFLAGS="$LDFLAGS $(pkg-config --libs openssl)"; - CFLAGS="$CFLAGS $(pkg-config --cflags openssl)"; + AC_MSG_CHECKING([for user specified OpenSSL directory]) + AC_ARG_WITH([openssl-dir], + [AS_HELP_STRING([--with-openssl-dir], [Location of OpenSSL installation])], + [if test "x$PKG_CONFIG" != "x" && test -f $with_openssl_dir/lib/pkgconfig/libcrypto.pc; then + if test "x$PKG_CONFIG_PATH" = "x"; then + export PKG_CONFIG_PATH="$with_openssl_dir/lib/pkgconfig" + else + export PKG_CONFIG_PATH="$with_openssl_dir/lib/pkgconfig:$PKG_CONFIG_PATH" + fi + AC_MSG_RESULT([$with_openssl_dir]) + elif test -d $with_openssl_dir/lib; then + CFLAGS="$CFLAGS -I$with_openssl_dir/include" + if test "x$LDFLAGS" = "x"; then + LDFLAGS="-L$with_openssl_dir/lib" + else + LDFLAGS="$LDFLAGS -L$with_openssl_dir/lib" + fi + AC_MSG_RESULT([$with_openssl_dir]) + else + AC_MSG_RESULT([invalid]) + AC_MSG_FAILURE([Invalid OpenSSL location: $with_openssl_dir]) + fi], + [AC_MSG_RESULT([no])]) - AC_CHECK_LIB([crypto], [EVP_EncryptInit], [], - [AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])]) - AC_CHECK_LIB([crypto], [EVP_aes_128_ctr], [], - [AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])]) - AC_CHECK_LIB([crypto], [EVP_aes_128_gcm], [], - [AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])]) - AC_DEFINE(OPENSSL, 1, [Define this to use OpenSSL crypto.]) + if test "x$PKG_CONFIG" != "x"; then + PKG_CHECK_MODULES([crypto], [libcrypto >= 1.0.1], + [CFLAGS="$CFLAGS $crypto_CFLAGS" + LIBS="$crypto_LIBS $LIBS"]) + else + AC_CHECK_LIB([dl], [dlopen], [], [AC_MSG_WARN([can't find libdl])]) + AC_CHECK_LIB([z], [inflate], [], [AC_MSG_WARN([can't find libz])]) + fi + + AC_SEARCH_LIBS([EVP_EncryptInit], [crypto], + [], [AC_MSG_FAILURE([can't find openssl >= 1.0.1 crypto lib])]) + AC_SEARCH_LIBS([EVP_aes_128_ctr], [crypto], + [], [AC_MSG_FAILURE([can't find openssl >= 1.0.1 crypto lib])]) + AC_SEARCH_LIBS([EVP_aes_128_gcm], [crypto], + [], [AC_MSG_FAILURE([can't find openssl >= 1.0.1 crypto lib])]) + + AC_DEFINE([GCM], [1], [Define this to use AES-GCM.]) + AC_DEFINE([OPENSSL], [1], [Define this to use OpenSSL crypto.]) AES_ICM_OBJS="crypto/cipher/aes_icm_ossl.o crypto/cipher/aes_gcm_ossl.o" HMAC_OBJS=crypto/hash/hmac_ossl.o - USE_OPENSSL=1 - AC_SUBST(USE_OPENSSL) -else - echo $enable_openssl - AES_ICM_OBJS="crypto/cipher/aes_icm.o crypto/cipher/aes.o crypto/cipher/aes_cbc.o" - AC_MSG_CHECKING(which random device to use) - if test "$enable_kernel_linux" = "yes"; then - AC_MSG_RESULT([Linux kernel builtin]) - else - if test -n "$DEV_URANDOM"; then - AC_DEFINE_UNQUOTED(DEV_URANDOM, "$DEV_URANDOM",[Path to random device]) - AC_MSG_RESULT([$DEV_URANDOM]) - else - AC_MSG_RESULT([standard rand() function...]) - fi + AC_SUBST([USE_EXTERNAL_CRYPTO], [1]) + + AC_MSG_CHECKING([if OPENSSL_cleanse is broken]) + AC_RUN_IFELSE([AC_LANG_PROGRAM([ + #include + #include + ], [ + #define BUFFER_SIZE (16) + char buffer[[BUFFER_SIZE]]; + int i; + for (i = 0; i < BUFFER_SIZE; i++) { + buffer[[i]] = i & 0xff; + } + OPENSSL_cleanse(buffer, BUFFER_SIZE); + for (i = 0; i < BUFFER_SIZE; i++) { + if (buffer[[i]]) { + printf("Buffer contents not zero at position %d (is %d)\n", i, + buffer[[i]]); + return 1; + } + } + ])], [openssl_cleanse_broken=no], [ + openssl_cleanse_broken=yes + AC_DEFINE([OPENSSL_CLEANSE_BROKEN], [1], [Define this if OPENSSL_cleanse is broken.]) + ]) + AC_MSG_RESULT([$openssl_cleanse_broken]) + + AC_MSG_CHECKING([whether to leverage OpenSSL KDF algorithm]) + AC_ARG_ENABLE([openssl-kdf], + [AS_HELP_STRING([--enable-openssl-kdf], [Use OpenSSL KDF algorithm])], + [], [enable_openssl_kdf=no]) + AC_MSG_RESULT([$enable_openssl_kdf]) + if test "$enable_openssl_kdf" = "yes"; then + AC_SEARCH_LIBS([kdf_srtp], [crypto], + [], [AC_MSG_FAILURE([can't find openssl KDF lib])]) + AC_DEFINE([OPENSSL_KDF], [1], [Define this to use OpenSSL KDF for SRTP.]) fi +elif test "$enable_nss" = "yes"; then + AC_MSG_CHECKING([for user specified NSS directory]) + AC_ARG_WITH([nss-dir], + [AS_HELP_STRING([--with-nss-dir], [Location of NSS installation])], + [if test "x$PKG_CONFIG" != "x" && test -f $with_nss_dir/lib/pkgconfig/nss.pc; then + if test "x$PKG_CONFIG_PATH" = "x"; then + export PKG_CONFIG_PATH="$with_nss_dir/lib/pkgconfig" + else + export PKG_CONFIG_PATH="$with_nss_dir/lib/pkgconfig:$PKG_CONFIG_PATH" + fi + AC_MSG_RESULT([$with_nss_dir]) + elif test -d $with_nss_dir/lib; then + CFLAGS="$CFLAGS -I$with_nss_dir/include" + CFLAGS="$CFLAGS -I$with_nss_dir/../public/nss" + if test "x$LDFLAGS" = "x"; then + LDFLAGS="-L$with_nss_dir/lib" + else + LDFLAGS="$LDFLAGS -L$with_nss_dir/lib" + fi + nss_skip_pkg_config=yes + AC_MSG_RESULT([$with_nss_dir]) + else + AC_MSG_RESULT([invalid]) + AC_MSG_FAILURE([Invalid NSS location: $with_nss_dir]) + fi + AC_SUBST([CRYPTO_LIBDIR], [$with_nss_dir/lib])], + [AC_MSG_RESULT([no])]) + + if test "x$PKG_CONFIG" != "x" && test "$nss_skip_pkg_config" != "yes"; then + PKG_CHECK_MODULES([nss], [nss], + [CFLAGS="$CFLAGS $nss_CFLAGS" + LIBS="$nss_LIBS $LIBS"]) + else + AC_CHECK_HEADERS( + [nss.h], + [], [AC_MSG_FAILURE([can't find useable NSS headers])], + [AC_INCLUDES_DEFAULT]) + AC_CHECK_LIB( + [nspr4], [PR_GetError], + [], [AC_MSG_WARN([can't find libnspr4])]) + AC_CHECK_LIB( + [nss3], [NSS_NoDB_Init], + [], [AC_MSG_FAILURE([can't find useable libnss3])]) + fi + + AC_DEFINE([GCM], [1], [Define this to use AES-GCM.]) + AC_DEFINE([NSS], [1], [Define this to use NSS crypto.]) + AES_ICM_OBJS="crypto/cipher/aes_icm_nss.o crypto/cipher/aes_gcm_nss.o" + + # TODO(RLB): Use NSS for HMAC + HMAC_OBJS="crypto/hash/hmac.o crypto/hash/sha1.o" + + # TODO(RLB): Use NSS for KDF + + AC_SUBST([USE_EXTERNAL_CRYPTO], [1]) +else + AES_ICM_OBJS="crypto/cipher/aes_icm.o crypto/cipher/aes.o" HMAC_OBJS="crypto/hash/hmac.o crypto/hash/sha1.o" fi AM_CONDITIONAL([ENABLE_OPENSSL],[test "${enable_openssl}" = "yes"]) -AC_SUBST(AES_ICM_OBJS) -AC_SUBST(HMAC_OBJS) +AC_SUBST([AES_ICM_OBJS]) +AC_SUBST([HMAC_OBJS]) AC_MSG_RESULT($enable_openssl) -AC_MSG_CHECKING(whether to use syslog for error reporting) -AC_ARG_ENABLE(syslog, - [AS_HELP_STRING([--enable-syslog], [use syslog for error reporting])], - [], enable_syslog=no) -if test "$enable_syslog" = "yes"; then - AC_DEFINE(USE_SYSLOG, 1, [Define to use syslog logging.]) +dnl Checking for PCAP + +PCAP_LIB="" +AC_ARG_ENABLE([pcap], AS_HELP_STRING([--disable-pcap], [Build without `pcap' library (-lpcap)])) +AS_IF([test "x$enable_pcap" != "xno"], [ + AC_CHECK_LIB([pcap], [pcap_create], + [PCAP_LIB="-lpcap" + AC_DEFINE([HAVE_PCAP], [1], [Define to 1 if you have the `pcap' library (-lpcap)]) + AC_SUBST([HAVE_PCAP], [1])]) + + AC_CHECK_LIB([wpcap], [pcap_create], + [PCAP_LIB="-lwpcap" + AC_DEFINE([HAVE_PCAP], [1], [Define to 1 if you have the `winpcap' library (-lwpcap)]) + AC_SUBST([HAVE_PCAP], [1])]) +]) +AC_SUBST([PCAP_LIB]) + +AC_MSG_CHECKING([whether to redirect logging to stdout]) +AC_ARG_ENABLE([log-stdout], + [AS_HELP_STRING([--enable-log-stdout], [redirecting logging to stdout])], + [], [enable_log_stdout=no]) +if test "$enable_log_stdout" = "yes"; then + AC_DEFINE([ERR_REPORTING_STDOUT], [1], [Define to redirect logging to stdout.]) fi -AC_MSG_RESULT($enable_syslog) +AC_MSG_RESULT([$enable_log_stdout]) -AC_MSG_CHECKING(whether to use stdout for error reporting) -AC_ARG_ENABLE(stdout, - [AS_HELP_STRING([--disable-stdout], [don't use stdout for error reporting])], - [], enable_stdout=yes) -if test "$enable_stdout" = "yes"; then - AC_DEFINE(ERR_REPORTING_STDOUT, 1, [Define to use logging to stdout.]) -fi -AC_MSG_RESULT($enable_stdout) +AC_MSG_CHECKING([wheather to use a file for logging]) +AC_ARG_WITH([log-file], + [AS_HELP_STRING([--with-log-file], [Use file for logging])], + [AS_CASE([x$with_log_file], + [x], [valid_with_log_file="no"], + [xyes], [valid_with_log_file="no"], + [valid_with_error_file="yes"]) + AS_IF([test "$valid_with_log_file" = "no"], + [AC_MSG_RESULT([invalid]) + AC_MSG_FAILURE([Invalid value for --with-log-file: "$with_log_file"])], + [AC_DEFINE_UNQUOTED([ERR_REPORTING_FILE], ["$with_log_file"], [Logging statments will be writen to this file.]) + AC_MSG_RESULT([using log file: "$with_log_file"])])], + [AC_MSG_RESULT([no])]) -AC_MSG_CHECKING(whether to use /dev/console for error reporting) -AC_ARG_ENABLE(console, - [AS_HELP_STRING([--enable-console], [use /dev/console for error reporting])], - [], enable_console=no) -if test "$enable_console" = "yes"; then - AC_DEFINE(USE_ERR_REPORTING_FILE, 1, [Write errors to this file]) - AC_DEFINE(ERR_REPORTING_FILE, "/dev/console", [Report errors to this file.]) -fi -AC_MSG_RESULT($enable_console) +AS_IF( + [test "$enable_log_stdout" = "yes" && test "x$with_log_file" != "x"], + [AC_MSG_FAILURE([Can only use one of --enable-log-stdout and --with-log-file; they are mutually exclusive])]) -AC_MSG_CHECKING(whether to use GDOI key management) -AC_ARG_ENABLE(gdoi, - [AS_HELP_STRING([--enable-gdoi], [enable GDOI key management])], - [], enable_gdoi=no) -if test "$enable_gdoi" = "yes"; then - AC_DEFINE(SRTP_GDOI, 1, [Define to use GDOI.]) - GDOI_OBJS=gdoi/srtp+gdoi.o - AC_SUBST(GDOI_OBJS) -fi -AC_MSG_RESULT($enable_gdoi) -AM_CONDITIONAL([GDOI],[test "SRTP_GDOI" = "1"]) +dnl Appending EXTRA_CFLAGS, if given +AC_MSG_CHECKING([for extra C compiler flags]) +AS_IF([test "x$EXTRA_CFLAGS" != "x"], + [AS_IF([test "x$CFLAGS" = "x"], + [CFLAGS="$EXTRA_CFLAGS"], [CFLAGS="$CFLAGS $EXTRA_CFLAGS"]) + AC_MSG_RESULT([$EXTRA_CFLAGS])], + [AC_MSG_RESULT(no)]) -AC_CONFIG_HEADERS(crypto/include/config.h:config_in.h) +AC_CONFIG_HEADERS([crypto/include/config.h:config_in.h]) -AC_OUTPUT(Makefile crypto/Makefile doc/Makefile test/Makefile libsrtp2.pc) +AC_CONFIG_FILES([Makefile crypto/Makefile doc/Makefile test/Makefile libsrtp2.pc]) +AC_OUTPUT # This is needed when building outside the source dir. -AS_MKDIR_P(crypto/cipher) -AS_MKDIR_P(crypto/hash) -AS_MKDIR_P(crypto/kernel) -AS_MKDIR_P(crypto/math) -AS_MKDIR_P(crypto/replay) -AS_MKDIR_P(crypto/test) -AS_MKDIR_P(doc) -AS_MKDIR_P(srtp) -AS_MKDIR_P(tables) -AS_MKDIR_P(test) +AS_MKDIR_P([crypto/cipher]) +AS_MKDIR_P([crypto/hash]) +AS_MKDIR_P([crypto/kernel]) +AS_MKDIR_P([crypto/math]) +AS_MKDIR_P([crypto/replay]) +AS_MKDIR_P([crypto/test]) +AS_MKDIR_P([doc]) +AS_MKDIR_P([srtp]) +AS_MKDIR_P([test]) diff --git a/libs/srtp/crypto/Makefile.in b/libs/srtp/crypto/Makefile.in index faaa991a09..44f29ad2cf 100644 --- a/libs/srtp/crypto/Makefile.in +++ b/libs/srtp/crypto/Makefile.in @@ -17,15 +17,34 @@ LIBS = @LIBS@ LDFLAGS = @LDFLAGS@ -L. -L.. COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS) CRYPTOLIB = -lsrtp2 +CRYPTO_LIBDIR = @CRYPTO_LIBDIR@ RANLIB = @RANLIB@ +# Specify how tests should find shared libraries on macOS and Linux +# +# macOS purges DYLD_LIBRARY_PATH when spawning subprocesses, so it's +# not possible to pass this in from the outside; we have to specify +# it for any subprocesses we call. No support for dynamic linked +# tests on Windows. +ifneq ($(strip $(CRYPTO_LIBDIR)),) + ifneq ($(OS),Windows_NT) + UNAME_S = $(shell uname -s) + ifeq ($(UNAME_S),Linux) + FIND_LIBRARIES = LD_LIBRARY_PATH=$(CRYPTO_LIBDIR) + endif + ifeq ($(UNAME_S),Darwin) + FIND_LIBRARIES = DYLD_LIBRARY_PATH=$(CRYPTO_LIBDIR) + endif + endif +endif + # EXE defines the suffix on executables - it's .exe for cygwin, and # null on linux, bsd, and OS X and other OSes. we define this so that # `make clean` will work on the cygwin platform EXE = @EXE@ # Random source. -USE_OPENSSL = @USE_OPENSSL@ +USE_EXTERNAL_CRYPTO = @USE_EXTERNAL_CRYPTO@ ifdef ARCH DEFS += -D$(ARCH)=1 @@ -40,7 +59,7 @@ endif dummy : all runtest # test applications -ifneq (1, $(USE_OPENSSL)) +ifneq (1, $(USE_EXTERNAL_CRYPTO)) AES_CALC = test/aes_calc$(EXE) endif @@ -62,17 +81,17 @@ c256=8ea2b7ca516745bfeafc49904b496089 runtest: $(testapp) - test/env$(EXE) # print out information on the build environment + $(FIND_LIBRARIES) test/env$(EXE) # print out information on the build environment @echo "running crypto test applications..." -ifneq (1, $(USE_OPENSSL)) - test `test/aes_calc $(k128) $(p128)` = $(c128) - test `test/aes_calc $(k256) $(p256)` = $(c256) +ifneq (1, $(USE_EXTERNAL_CRYPTO)) + $(FIND_LIBRARIES) test `test/aes_calc $(k128) $(p128)` = $(c128) + $(FIND_LIBRARIES) test `test/aes_calc $(k256) $(p256)` = $(c256) endif - test/cipher_driver$(EXE) -v >/dev/null - test/datatypes_driver$(EXE) -v >/dev/null - test/stat_driver$(EXE) >/dev/null - test/sha1_driver$(EXE) -v >/dev/null - test/kernel_driver$(EXE) -v >/dev/null + $(FIND_LIBRARIES) test/cipher_driver$(EXE) -v >/dev/null + $(FIND_LIBRARIES) test/datatypes_driver$(EXE) -v >/dev/null + $(FIND_LIBRARIES) test/stat_driver$(EXE) >/dev/null + $(FIND_LIBRARIES) test/sha1_driver$(EXE) -v >/dev/null + $(FIND_LIBRARIES) test/kernel_driver$(EXE) -v >/dev/null @echo "crypto test applications passed." diff --git a/libs/srtp/crypto/cipher/aes_gcm_nss.c b/libs/srtp/crypto/cipher/aes_gcm_nss.c new file mode 100644 index 0000000000..54547cd1c9 --- /dev/null +++ b/libs/srtp/crypto/cipher/aes_gcm_nss.c @@ -0,0 +1,609 @@ +/* + * 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 +#endif + +#include "aes_gcm.h" +#include "alloc.h" +#include "err.h" /* for srtp_debug */ +#include "crypto_types.h" +#include "cipher_types.h" +#include +#include + +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, ¶m, buf, enc_len, + *enc_len + 16, buf, *enc_len); + } else { + rv = PK11_Decrypt(c->key, CKM_AES_GCM, ¶m, 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"; + +/* + * KAT values for AES self-test. These + * values we're derived from independent test code + * using OpenSSL. + */ +/* clang-format off */ +static const uint8_t srtp_aes_gcm_test_case_0_key[SRTP_AES_GCM_128_KEY_LEN_WSALT] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, +}; +/* clang-format on */ + +/* clang-format off */ +static uint8_t srtp_aes_gcm_test_case_0_iv[12] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_gcm_test_case_0_plaintext[60] = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39 +}; + +/* clang-format off */ +static const uint8_t srtp_aes_gcm_test_case_0_aad[20] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_gcm_test_case_0_ciphertext[76] = { + 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, + /* the last 16 bytes are the tag */ + 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, +}; +/* clang-format on */ + +static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_0a = { + SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_gcm_test_case_0_key, /* key */ + srtp_aes_gcm_test_case_0_iv, /* packet index */ + 60, /* octets in plaintext */ + srtp_aes_gcm_test_case_0_plaintext, /* plaintext */ + 68, /* octets in ciphertext */ + srtp_aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */ + 20, /* octets in AAD */ + srtp_aes_gcm_test_case_0_aad, /* AAD */ + GCM_AUTH_TAG_LEN_8, /* */ + NULL /* pointer to next testcase */ +}; + +static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_0 = { + SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_gcm_test_case_0_key, /* key */ + srtp_aes_gcm_test_case_0_iv, /* packet index */ + 60, /* octets in plaintext */ + srtp_aes_gcm_test_case_0_plaintext, /* plaintext */ + 76, /* octets in ciphertext */ + srtp_aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */ + 20, /* octets in AAD */ + srtp_aes_gcm_test_case_0_aad, /* AAD */ + GCM_AUTH_TAG_LEN, /* */ + &srtp_aes_gcm_test_case_0a /* pointer to next testcase */ +}; + +/* clang-format off */ +static const uint8_t srtp_aes_gcm_test_case_1_key[SRTP_AES_GCM_256_KEY_LEN_WSALT] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c, + 0xaf, 0xf5, 0x26, 0x9a, 0x21, 0xd5, 0x14, 0xb2, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, +}; +/* clang-format on */ + +/* clang-format off */ +static uint8_t srtp_aes_gcm_test_case_1_iv[12] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_gcm_test_case_1_plaintext[60] = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39 +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_gcm_test_case_1_aad[20] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_gcm_test_case_1_ciphertext[76] = { + 0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46, + 0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a, + 0x94, 0x82, 0xca, 0xab, 0x3e, 0x39, 0xd7, 0x86, + 0x1b, 0xc7, 0x93, 0xed, 0x75, 0x7f, 0x23, 0x5a, + 0xda, 0xfd, 0xd3, 0xe2, 0x0e, 0x80, 0x87, 0xa9, + 0x6d, 0xd7, 0xe2, 0x6a, 0x7d, 0x5f, 0xb4, 0x80, + 0xef, 0xef, 0xc5, 0x29, 0x12, 0xd1, 0xaa, 0x10, + 0x09, 0xc9, 0x86, 0xc1, + /* the last 16 bytes are the tag */ + 0x45, 0xbc, 0x03, 0xe6, 0xe1, 0xac, 0x0a, 0x9f, + 0x81, 0xcb, 0x8e, 0x5b, 0x46, 0x65, 0x63, 0x1d, +}; +/* clang-format on */ + +static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1a = { + SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_gcm_test_case_1_key, /* key */ + srtp_aes_gcm_test_case_1_iv, /* packet index */ + 60, /* octets in plaintext */ + srtp_aes_gcm_test_case_1_plaintext, /* plaintext */ + 68, /* octets in ciphertext */ + srtp_aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */ + 20, /* octets in AAD */ + srtp_aes_gcm_test_case_1_aad, /* AAD */ + GCM_AUTH_TAG_LEN_8, /* */ + NULL /* pointer to next testcase */ +}; + +static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1 = { + SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_gcm_test_case_1_key, /* key */ + srtp_aes_gcm_test_case_1_iv, /* packet index */ + 60, /* octets in plaintext */ + srtp_aes_gcm_test_case_1_plaintext, /* plaintext */ + 76, /* octets in ciphertext */ + srtp_aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */ + 20, /* octets in AAD */ + srtp_aes_gcm_test_case_1_aad, /* AAD */ + GCM_AUTH_TAG_LEN, /* */ + &srtp_aes_gcm_test_case_1a /* pointer to next testcase */ +}; + +/* + * This is the vector function table for this crypto engine. + */ +/* 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_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_test_case_1, + SRTP_AES_GCM_256 +}; +/* clang-format on */ diff --git a/libs/srtp/crypto/cipher/aes_gcm_ossl.c b/libs/srtp/crypto/cipher/aes_gcm_ossl.c index ef13a78240..90d5e3b4e1 100644 --- a/libs/srtp/crypto/cipher/aes_gcm_ossl.c +++ b/libs/srtp/crypto/cipher/aes_gcm_ossl.c @@ -49,8 +49,7 @@ #endif #include -#include "aes_icm_ossl.h" -#include "aes_gcm_ossl.h" +#include "aes_gcm.h" #include "alloc.h" #include "err.h" /* for srtp_debug */ #include "crypto_types.h" @@ -124,13 +123,13 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc(srtp_cipher_t **c, /* 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; @@ -193,6 +192,7 @@ static srtp_err_status_t srtp_aes_gcm_openssl_context_init(void *cv, break; } + EVP_CIPHER_CTX_cleanup(c->ctx); if (!EVP_CipherInit_ex(c->ctx, evp, NULL, key, NULL, 0)) { return (srtp_err_status_init_fail); } @@ -218,7 +218,7 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_iv( c->dir = direction; debug_print(srtp_mod_aes_gcm, "setting iv: %s", - v128_hex_string((v128_t *)iv)); + srtp_octet_string_hex_string(iv, 12)); if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) { return (srtp_err_status_init_fail); @@ -247,6 +247,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_aad(void *cv, srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; int rv; + debug_print(srtp_mod_aes_gcm, "setting AAD: %s", + srtp_octet_string_hex_string(aad, aad_len)); + /* * Set dummy tag, OpenSSL requires the Tag to be set before * processing AAD @@ -548,7 +551,7 @@ static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1 = { /* * 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, @@ -565,7 +568,7 @@ const srtp_cipher_type_t srtp_aes_gcm_128_openssl = { /* * 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, diff --git a/libs/srtp/crypto/cipher/aes_icm_nss.c b/libs/srtp/crypto/cipher/aes_icm_nss.c new file mode 100644 index 0000000000..d161b8f56c --- /dev/null +++ b/libs/srtp/crypto/cipher/aes_icm_nss.c @@ -0,0 +1,562 @@ +/* + * 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 +#endif + +#include "aes_icm_ext.h" +#include "crypto_types.h" +#include "err.h" /* for srtp_debug */ +#include "alloc.h" +#include "cipher_types.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; + + 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; + + /* 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 *)¶m, + sizeof(CK_AES_CTR_PARAMS) }; + c->ctx = PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, c->key, + ¶mItem); + 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"; + +/* + * KAT values for AES self-test. These + * values came from the legacy libsrtp code. + */ +/* clang-format off */ +static const uint8_t srtp_aes_icm_128_test_case_0_key[SRTP_AES_ICM_128_KEY_LEN_WSALT] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd +}; +/* clang-format on */ + +/* clang-format off */ +static uint8_t srtp_aes_icm_128_test_case_0_nonce[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_icm_128_test_case_0_plaintext[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_icm_128_test_case_0_ciphertext[32] = { + 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80, + 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4, + 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7, + 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab +}; +/* clang-format on */ + +static const srtp_cipher_test_case_t srtp_aes_icm_128_test_case_0 = { + SRTP_AES_ICM_128_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_icm_128_test_case_0_key, /* key */ + srtp_aes_icm_128_test_case_0_nonce, /* packet index */ + 32, /* octets in plaintext */ + srtp_aes_icm_128_test_case_0_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + srtp_aes_icm_128_test_case_0_ciphertext, /* ciphertext */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL /* pointer to next testcase */ +}; + +/* + * KAT values for AES-192-CTR self-test. These + * values came from section 7 of RFC 6188. + */ +/* clang-format off */ +static const uint8_t srtp_aes_icm_192_test_case_0_key[SRTP_AES_ICM_192_KEY_LEN_WSALT] = { + 0xea, 0xb2, 0x34, 0x76, 0x4e, 0x51, 0x7b, 0x2d, + 0x3d, 0x16, 0x0d, 0x58, 0x7d, 0x8c, 0x86, 0x21, + 0x97, 0x40, 0xf6, 0x5f, 0x99, 0xb6, 0xbc, 0xf7, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd +}; +/* clang-format on */ + +/* clang-format off */ +static uint8_t srtp_aes_icm_192_test_case_0_nonce[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_icm_192_test_case_0_plaintext[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_icm_192_test_case_0_ciphertext[32] = { + 0x35, 0x09, 0x6c, 0xba, 0x46, 0x10, 0x02, 0x8d, + 0xc1, 0xb5, 0x75, 0x03, 0x80, 0x4c, 0xe3, 0x7c, + 0x5d, 0xe9, 0x86, 0x29, 0x1d, 0xcc, 0xe1, 0x61, + 0xd5, 0x16, 0x5e, 0xc4, 0x56, 0x8f, 0x5c, 0x9a +}; +/* clang-format on */ + +static const srtp_cipher_test_case_t srtp_aes_icm_192_test_case_0 = { + SRTP_AES_ICM_192_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_icm_192_test_case_0_key, /* key */ + srtp_aes_icm_192_test_case_0_nonce, /* packet index */ + 32, /* octets in plaintext */ + srtp_aes_icm_192_test_case_0_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + srtp_aes_icm_192_test_case_0_ciphertext, /* ciphertext */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL /* pointer to next testcase */ +}; + +/* + * KAT values for AES-256-CTR self-test. These + * values came from section 7 of RFC 6188. + */ +/* clang-format off */ +static const uint8_t srtp_aes_icm_256_test_case_0_key[SRTP_AES_ICM_256_KEY_LEN_WSALT] = { + 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70, + 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92, + 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82, + 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd +}; +/* clang-format on */ + +/* clang-format off */ +static uint8_t srtp_aes_icm_256_test_case_0_nonce[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_icm_256_test_case_0_plaintext[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +/* clang-format on */ + +/* clang-format off */ +static const uint8_t srtp_aes_icm_256_test_case_0_ciphertext[32] = { + 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25, + 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4, + 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6, + 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac +}; +/* clang-format on */ + +static const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0 = { + SRTP_AES_ICM_256_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_icm_256_test_case_0_key, /* key */ + srtp_aes_icm_256_test_case_0_nonce, /* packet index */ + 32, /* octets in plaintext */ + srtp_aes_icm_256_test_case_0_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + srtp_aes_icm_256_test_case_0_ciphertext, /* ciphertext */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL /* pointer to next testcase */ +}; + +/* + * This is the function table for this crypto engine. + * note: the encrypt function is identical to the decrypt function + */ +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 /* */ +}; diff --git a/libs/srtp/crypto/cipher/aes_icm_ossl.c b/libs/srtp/crypto/cipher/aes_icm_ossl.c index b591897623..451cd18c0d 100644 --- a/libs/srtp/crypto/cipher/aes_icm_ossl.c +++ b/libs/srtp/crypto/cipher/aes_icm_ossl.c @@ -53,7 +53,7 @@ #endif #include -#include "aes_icm_ossl.h" +#include "aes_icm_ext.h" #include "crypto_types.h" #include "err.h" /* for srtp_debug */ #include "alloc.h" @@ -78,9 +78,9 @@ srtp_debug_module_t srtp_mod_aes_icm = { * +------+------+------+------+------+------+------+------+ | * | * +---------+ - * | encrypt | - * +---------+ - * | + * | encrypt | + * +---------+ + * | * +------+------+------+------+------+------+------+------+ | * | keystream block |<--+ * +------+------+------+------+------+------+------+------+ @@ -248,6 +248,7 @@ static srtp_err_status_t srtp_aes_icm_openssl_context_init(void *cv, break; } + EVP_CIPHER_CTX_cleanup(c->ctx); if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) { return srtp_err_status_fail; } else { @@ -308,7 +309,7 @@ static srtp_err_status_t srtp_aes_icm_openssl_encrypt(void *cv, } *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; diff --git a/libs/srtp/crypto/cipher/cipher.c b/libs/srtp/crypto/cipher/cipher.c index 19f00abc55..de93bc90d8 100644 --- a/libs/srtp/crypto/cipher/cipher.c +++ b/libs/srtp/crypto/cipher/cipher.c @@ -49,6 +49,7 @@ #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() */ @@ -165,24 +166,11 @@ int srtp_cipher_get_key_length(const srtp_cipher_t *c) } /* - * A trivial platform independent random source. The random - * data is used for some of the cipher self-tests. + * A trivial platform independent random source. + * For use in test only. */ -static srtp_err_status_t srtp_cipher_rand(void *dest, uint32_t len) +void srtp_cipher_rand_for_tests(void *dest, uint32_t len) { -#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; @@ -194,8 +182,17 @@ static srtp_err_status_t srtp_cipher_rand(void *dest, uint32_t len) *dst++ = val & 0xff; len--; } -#endif - return srtp_err_status_ok; +} + +/* + * A trivial platform independent 32 bit random number. + * For use in test only. + */ +uint32_t srtp_cipher_rand_u32_for_tests(void) +{ + uint32_t r; + srtp_cipher_rand_for_tests(&r, sizeof(r)); + return r; } #define SELF_TEST_BUF_OCTETS 128 @@ -246,7 +243,7 @@ srtp_err_status_t srtp_cipher_type_test( /* * 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); @@ -350,7 +347,7 @@ srtp_err_status_t srtp_cipher_type_test( /* * 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); @@ -465,13 +462,9 @@ srtp_err_status_t srtp_cipher_type_test( 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)); @@ -486,18 +479,10 @@ srtp_err_status_t srtp_cipher_type_test( 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); diff --git a/libs/srtp/crypto/cipher/null_cipher.c b/libs/srtp/crypto/cipher/null_cipher.c index 659add0d47..969724611c 100644 --- a/libs/srtp/crypto/cipher/null_cipher.c +++ b/libs/srtp/crypto/cipher/null_cipher.c @@ -97,7 +97,7 @@ 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); + debug_print0(srtp_mod_cipher, "initializing null cipher"); return srtp_err_status_ok; } diff --git a/libs/srtp/crypto/hash/sha1.c b/libs/srtp/crypto/hash/sha1.c index afd6381542..36c049ef81 100644 --- a/libs/srtp/crypto/hash/sha1.c +++ b/libs/srtp/crypto/hash/sha1.c @@ -261,14 +261,13 @@ void srtp_sha1_update(srtp_sha1_ctx_t *ctx, /* 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++) { @@ -391,11 +390,10 @@ void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t *output) 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 */ diff --git a/libs/srtp/crypto/include/aes_gcm_ossl.h b/libs/srtp/crypto/include/aes_gcm.h similarity index 80% rename from libs/srtp/crypto/include/aes_gcm_ossl.h rename to libs/srtp/crypto/include/aes_gcm.h index d5b83eeeb0..4d6031f4bd 100644 --- a/libs/srtp/crypto/include/aes_gcm_ossl.h +++ b/libs/srtp/crypto/include/aes_gcm.h @@ -1,5 +1,5 @@ /* - * aes_gcm_ossl.h + * aes_gcm.h * * Header for AES Galois Counter Mode. * @@ -43,12 +43,15 @@ * */ -#ifndef AES_GCM_OSSL_H -#define AES_GCM_OSSL_H +#ifndef AES_GCM_H +#define AES_GCM_H #include "cipher.h" #include "srtp.h" #include "datatypes.h" + +#ifdef OPENSSL + #include #include @@ -59,4 +62,28 @@ typedef struct { srtp_cipher_direction_t dir; } srtp_aes_gcm_ctx_t; -#endif /* AES_GCM_OSSL_H */ +#endif /* OPENSSL */ + +#ifdef NSS + +#include +#include + +#define MAX_AD_SIZE 2048 + +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; + +#endif /* NSS */ + +#endif /* AES_GCM_H */ diff --git a/libs/srtp/crypto/include/aes_icm_ossl.h b/libs/srtp/crypto/include/aes_icm_ext.h similarity index 87% rename from libs/srtp/crypto/include/aes_icm_ossl.h rename to libs/srtp/crypto/include/aes_icm_ext.h index c4aae376e6..ad306ddca5 100644 --- a/libs/srtp/crypto/include/aes_icm_ossl.h +++ b/libs/srtp/crypto/include/aes_icm_ext.h @@ -48,6 +48,9 @@ #include "cipher.h" #include "datatypes.h" + +#ifdef OPENSSL + #include #include @@ -58,4 +61,23 @@ typedef struct { EVP_CIPHER_CTX *ctx; } srtp_aes_icm_ctx_t; +#endif /* OPENSSL */ + +#ifdef NSS + +#include +#include + +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 */ diff --git a/libs/srtp/crypto/include/cipher_priv.h b/libs/srtp/crypto/include/cipher_priv.h new file mode 100644 index 0000000000..46848ea7c6 --- /dev/null +++ b/libs/srtp/crypto/include/cipher_priv.h @@ -0,0 +1,62 @@ +/* + * + * Copyright(c) 2001-2017 Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SRTP_CIHPER_PRIV_H +#define SRTP_CIHPER_PRIV_H + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 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 */ diff --git a/libs/srtp/crypto/include/cipher_types.h b/libs/srtp/crypto/include/cipher_types.h index a543b5478b..18f0328fbb 100644 --- a/libs/srtp/crypto/include/cipher_types.h +++ b/libs/srtp/crypto/include/cipher_types.h @@ -47,10 +47,10 @@ 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 OPENSSL +#ifdef GCM extern const srtp_cipher_type_t srtp_aes_icm_192; -extern const srtp_cipher_type_t srtp_aes_gcm_128_openssl; -extern const srtp_cipher_type_t srtp_aes_gcm_256_openssl; +extern const srtp_cipher_type_t srtp_aes_gcm_128; +extern const srtp_cipher_type_t srtp_aes_gcm_256; #endif /* @@ -74,6 +74,9 @@ extern srtp_debug_module_t srtp_mod_aes_icm; #ifdef OPENSSL extern srtp_debug_module_t srtp_mod_aes_gcm; #endif +#ifdef NSS +extern srtp_debug_module_t srtp_mod_aes_gcm; +#endif /* debug modules for auth types */ extern srtp_debug_module_t srtp_mod_hmac; diff --git a/libs/srtp/crypto/include/datatypes.h b/libs/srtp/crypto/include/datatypes.h index 182cca25b9..6a588d0e92 100644 --- a/libs/srtp/crypto/include/datatypes.h +++ b/libs/srtp/crypto/include/datatypes.h @@ -241,13 +241,13 @@ void v128_set_bit_to(v128_t *x, int i, int y); #endif /* DATATYPES_USE_MACROS */ /* - * 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 diff --git a/libs/srtp/crypto/include/err.h b/libs/srtp/crypto/include/err.h index 66a1023ec8..326f5e96b7 100644 --- a/libs/srtp/crypto/include/err.h +++ b/libs/srtp/crypto/include/err.h @@ -109,6 +109,8 @@ typedef struct { #ifdef ENABLE_DEBUG_LOGGING +#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) \ @@ -117,6 +119,9 @@ typedef struct { #else +#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) diff --git a/libs/srtp/crypto/kernel/alloc.c b/libs/srtp/crypto/kernel/alloc.c index dbe58266f4..3ebc315259 100644 --- a/libs/srtp/crypto/kernel/alloc.c +++ b/libs/srtp/crypto/kernel/alloc.c @@ -80,7 +80,7 @@ void *srtp_crypto_alloc(size_t size) if (ptr) { debug_print(srtp_mod_alloc, "(location: %p) allocated", ptr); } else { - debug_print(srtp_mod_alloc, "allocation failed (asked for %d bytes)\n", + debug_print(srtp_mod_alloc, "allocation failed (asked for %zu bytes)\n", size); } diff --git a/libs/srtp/crypto/kernel/crypto_kernel.c b/libs/srtp/crypto/kernel/crypto_kernel.c index ab4492e8a6..df6af7da88 100644 --- a/libs/srtp/crypto/kernel/crypto_kernel.c +++ b/libs/srtp/crypto/kernel/crypto_kernel.c @@ -130,18 +130,18 @@ srtp_err_status_t srtp_crypto_kernel_init() if (status) { return status; } -#ifdef OPENSSL +#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, + 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, + status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_256, SRTP_AES_GCM_256); if (status) { return status; diff --git a/libs/srtp/crypto/kernel/err.c b/libs/srtp/crypto/kernel/err.c index f443549e5a..9db5bfb432 100644 --- a/libs/srtp/crypto/kernel/err.c +++ b/libs/srtp/crypto/kernel/err.c @@ -80,6 +80,7 @@ srtp_err_status_t srtp_install_err_report_handler( 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); @@ -88,7 +89,6 @@ 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); diff --git a/libs/srtp/crypto/math/datatypes.c b/libs/srtp/crypto/math/datatypes.c index c0dfece659..001584c1bf 100644 --- a/libs/srtp/crypto/math/datatypes.c +++ b/libs/srtp/crypto/math/datatypes.c @@ -410,7 +410,7 @@ void bitvector_left_shift(bitvector_t *x, int shift) x->word[i] = 0; } -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) { uint8_t *end = b + len; uint8_t accumulator = 0; @@ -436,7 +436,7 @@ void srtp_cleanse(void *s, size_t len) void octet_string_set_to_zero(void *s, size_t len) { -#ifdef OPENSSL +#if defined(OPENSSL) && !defined(OPENSSL_CLEANSE_BROKEN) OPENSSL_cleanse(s, len); #else srtp_cleanse(s, len); diff --git a/libs/srtp/crypto/math/stat.c b/libs/srtp/crypto/math/stat.c index 6dd332b0cf..d30045357b 100644 --- a/libs/srtp/crypto/math/stat.c +++ b/libs/srtp/crypto/math/stat.c @@ -196,7 +196,7 @@ srtp_err_status_t stat_test_runs(uint8_t *data) } if (srtp_mod_stat.on) { - debug_print(srtp_mod_stat, "runs test", NULL); + debug_print0(srtp_mod_stat, "runs test"); for (i = 0; i < 6; i++) debug_print(srtp_mod_stat, " runs[]: %d", runs[i]); for (i = 0; i < 6; i++) diff --git a/libs/srtp/crypto/replay/ut_sim.c b/libs/srtp/crypto/replay/ut_sim.c index c621c0e9f2..2825b68df9 100644 --- a/libs/srtp/crypto/replay/ut_sim.c +++ b/libs/srtp/crypto/replay/ut_sim.c @@ -49,10 +49,13 @@ #endif #include "ut_sim.h" +#include "cipher_priv.h" int ut_compar(const void *a, const void *b) { - return rand() > (RAND_MAX / 2) ? -1 : 1; + uint8_t r; + srtp_cipher_rand_for_tests(&r, sizeof(r)); + return r > (UINT8_MAX / 2) ? -1 : 1; } void ut_init(ut_connection *utc) diff --git a/libs/srtp/crypto/test/cipher_driver.c b/libs/srtp/crypto/test/cipher_driver.c index e28f5f264f..8219a06180 100644 --- a/libs/srtp/crypto/test/cipher_driver.c +++ b/libs/srtp/crypto/test/cipher_driver.c @@ -47,13 +47,13 @@ #include #endif -#include /* for printf() */ -#include /* for rand() */ +#include /* for printf() */ #include "getopt_s.h" #include "cipher.h" -#ifdef OPENSSL -#include "aes_icm_ossl.h" -#include "aes_gcm_ossl.h" +#include "cipher_priv.h" +#ifdef GCM +#include "aes_icm_ext.h" +#include "aes_gcm.h" #else #include "aes_icm.h" #endif @@ -118,10 +118,10 @@ void check_status(srtp_err_status_t s) 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 +#ifdef GCM 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; +extern srtp_cipher_type_t srtp_aes_gcm_128; +extern srtp_cipher_type_t srtp_aes_gcm_256; #endif int main(int argc, char *argv[]) @@ -187,21 +187,19 @@ int main(int argc, char *argv[]) cipher_driver_test_array_throughput( &srtp_aes_icm_256, SRTP_AES_ICM_256_KEY_LEN_WSALT, num_cipher); -#ifdef OPENSSL +#ifdef GCM for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) cipher_driver_test_array_throughput( &srtp_aes_icm_192, SRTP_AES_ICM_192_KEY_LEN_WSALT, num_cipher); for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { - cipher_driver_test_array_throughput(&srtp_aes_gcm_128_openssl, - SRTP_AES_GCM_128_KEY_LEN_WSALT, - num_cipher); + cipher_driver_test_array_throughput( + &srtp_aes_gcm_128, SRTP_AES_GCM_128_KEY_LEN_WSALT, num_cipher); } for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { - cipher_driver_test_array_throughput(&srtp_aes_gcm_256_openssl, - SRTP_AES_GCM_256_KEY_LEN_WSALT, - num_cipher); + cipher_driver_test_array_throughput( + &srtp_aes_gcm_256, SRTP_AES_GCM_256_KEY_LEN_WSALT, num_cipher); } #endif } @@ -210,10 +208,10 @@ int main(int argc, char *argv[]) cipher_driver_self_test(&srtp_null_cipher); cipher_driver_self_test(&srtp_aes_icm_128); cipher_driver_self_test(&srtp_aes_icm_256); -#ifdef OPENSSL +#ifdef GCM cipher_driver_self_test(&srtp_aes_icm_192); - cipher_driver_self_test(&srtp_aes_gcm_128_openssl); - cipher_driver_self_test(&srtp_aes_gcm_256_openssl); + cipher_driver_self_test(&srtp_aes_gcm_128); + cipher_driver_self_test(&srtp_aes_gcm_256); #endif } @@ -277,9 +275,9 @@ int main(int argc, char *argv[]) status = srtp_cipher_dealloc(c); check_status(status); -#ifdef OPENSSL - /* run the throughput test on the aes_gcm_128_openssl cipher */ - status = srtp_cipher_type_alloc(&srtp_aes_gcm_128_openssl, &c, +#ifdef GCM + /* run the throughput test on the aes_gcm_128 cipher */ + status = srtp_cipher_type_alloc(&srtp_aes_gcm_128, &c, SRTP_AES_GCM_128_KEY_LEN_WSALT, 8); if (status) { fprintf(stderr, "error: can't allocate GCM 128 cipher\n"); @@ -291,15 +289,13 @@ int main(int argc, char *argv[]) cipher_driver_test_throughput(c); } - if (do_validation) { - status = cipher_driver_test_buffering(c); - check_status(status); - } + // GCM ciphers don't do buffering; they're "one shot" + status = srtp_cipher_dealloc(c); check_status(status); - /* run the throughput test on the aes_gcm_256_openssl cipher */ - status = srtp_cipher_type_alloc(&srtp_aes_gcm_256_openssl, &c, + /* run the throughput test on the aes_gcm_256 cipher */ + status = srtp_cipher_type_alloc(&srtp_aes_gcm_256, &c, SRTP_AES_GCM_256_KEY_LEN_WSALT, 16); if (status) { fprintf(stderr, "error: can't allocate GCM 256 cipher\n"); @@ -311,10 +307,8 @@ int main(int argc, char *argv[]) cipher_driver_test_throughput(c); } - if (do_validation) { - status = cipher_driver_test_buffering(c); - check_status(status); - } + // GCM ciphers don't do buffering; they're "one shot" + status = srtp_cipher_dealloc(c); check_status(status); #endif @@ -396,7 +390,7 @@ srtp_err_status_t cipher_driver_test_buffering(srtp_cipher_t *c) end = buffer1 + buflen; while (current < end) { /* choose a short length */ - len = rand() & 0x01f; + len = srtp_cipher_rand_u32_for_tests() & 0x01f; /* make sure that len doesn't cause us to overreach the buffer */ if (current + len > end) @@ -479,9 +473,8 @@ srtp_err_status_t cipher_array_alloc_init(srtp_cipher_t ***ca, return status; /* generate random key and initialize cipher */ - for (j = 0; j < klen; j++) - key[j] = (uint8_t)rand(); - for (; j < klen_pad; j++) + srtp_cipher_rand_for_tests(key, klen); + for (j = klen; j < klen_pad; j++) key[j] = 0; status = srtp_cipher_init(*cipher_array, key); if (status) @@ -535,7 +528,7 @@ uint64_t cipher_array_bits_per_second(srtp_cipher_t *cipher_array[], v128_t nonce; clock_t timer; unsigned char *enc_buf; - int cipher_index = rand() % num_cipher; + int cipher_index = srtp_cipher_rand_u32_for_tests() % num_cipher; /* Over-alloc, for NIST CBC padding */ enc_buf = srtp_crypto_alloc(octets_in_buffer + 17); diff --git a/libs/srtp/crypto/test/datatypes_driver.c b/libs/srtp/crypto/test/datatypes_driver.c index 2f78903eb8..96379befe1 100644 --- a/libs/srtp/crypto/test/datatypes_driver.c +++ b/libs/srtp/crypto/test/datatypes_driver.c @@ -60,6 +60,8 @@ void print_string(char *s); void test_bswap(void); +void test_set_to_zero(void); + int main(void) { /* @@ -135,6 +137,7 @@ int main(void) printf(" } \n"); test_bswap(); + test_set_to_zero(); return 0; } @@ -228,3 +231,26 @@ void test_bswap(void) printf("bswapped octet string: %s\n", octet_string_hex_string((uint8_t *)&y, 8)); } + +void test_set_to_zero(void) +{ +#define BUFFER_SIZE (16) + uint8_t buffer[BUFFER_SIZE]; + size_t i; + + for (i = 0; i < BUFFER_SIZE; i++) { + buffer[i] = i & 0xff; + } + printf("Buffer before: %s\n", octet_string_hex_string(buffer, BUFFER_SIZE)); + octet_string_set_to_zero(buffer, BUFFER_SIZE); + printf("Buffer after: %s\n", octet_string_hex_string(buffer, BUFFER_SIZE)); + for (i = 0; i < BUFFER_SIZE; i++) { + if (buffer[i]) { + fprintf(stderr, + "Buffer contents not zero at position %zu (is %d)\n", i, + buffer[i]); + abort(); + } + } +#undef BUFFER_SIZE +} diff --git a/libs/srtp/crypto/test/stat_driver.c b/libs/srtp/crypto/test/stat_driver.c index 4149447f74..9a3d918aa1 100644 --- a/libs/srtp/crypto/test/stat_driver.c +++ b/libs/srtp/crypto/test/stat_driver.c @@ -54,12 +54,7 @@ #include "srtp.h" #include "cipher.h" - -typedef struct { - void *state; -} random_source_t; - -srtp_err_status_t random_source_alloc(void); +#include "cipher_priv.h" void err_check(srtp_err_status_t s) { @@ -76,9 +71,9 @@ int main(int argc, char *argv[]) int i, j; 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_gcm_128_openssl; - extern srtp_cipher_type_t srtp_aes_gcm_256_openssl; +#ifdef GCM + extern srtp_cipher_type_t srtp_aes_gcm_128; + extern srtp_cipher_type_t srtp_aes_gcm_256; #endif srtp_cipher_t *c; /* clang-format off */ @@ -107,8 +102,7 @@ int main(int argc, char *argv[]) printf("poker %d\n", stat_test_poker(buffer)); printf("runs %d\n", stat_test_runs(buffer)); - for (i = 0; i < 2500; i++) - buffer[i] = rand(); + srtp_cipher_rand_for_tests(buffer, 2500); printf("running stat_tests on rand(), expecting success\n"); printf("monobit %d\n", stat_test_monobit(buffer)); printf("poker %d\n", stat_test_poker(buffer)); @@ -180,14 +174,14 @@ int main(int argc, char *argv[]) } } -#ifdef OPENSSL +#ifdef GCM { printf("running stat_tests on AES-128-GCM, expecting success\n"); /* set buffer to cipher output */ for (i = 0; i < 2500; i++) { buffer[i] = 0; } - err_check(srtp_cipher_type_alloc(&srtp_aes_gcm_128_openssl, &c, + err_check(srtp_cipher_type_alloc(&srtp_aes_gcm_128, &c, SRTP_AES_GCM_128_KEY_LEN_WSALT, 8)); err_check(srtp_cipher_init(c, key)); err_check( @@ -219,7 +213,7 @@ int main(int argc, char *argv[]) for (i = 0; i < 2500; i++) { buffer[i] = 0; } - err_check(srtp_cipher_type_alloc(&srtp_aes_gcm_256_openssl, &c, + err_check(srtp_cipher_type_alloc(&srtp_aes_gcm_256, &c, SRTP_AES_GCM_256_KEY_LEN_WSALT, 16)); err_check(srtp_cipher_init(c, key)); err_check( diff --git a/libs/srtp/include/srtp.h b/libs/srtp/include/srtp.h index 1fdd6c3aff..c86b9ee747 100644 --- a/libs/srtp/include/srtp.h +++ b/libs/srtp/include/srtp.h @@ -682,14 +682,14 @@ srtp_err_status_t srtp_update_stream(srtp_t session, * * @param p is a pointer to the policy structure to be set * - * The function call crypto_policy_set_rtp_default(&p) sets the - * crypto_policy_t at location p to the SRTP default policy for RTP + * The function call srtp_crypto_policy_set_rtp_default(&p) sets the + * srtp_crypto_policy_t at location p to the SRTP default policy for RTP * protection, as defined in the specification. This function is a * convenience that helps to avoid dealing directly with the policy * data structure. You are encouraged to initialize policy elements * with this function call. Doing so may allow your code to be * forward compatible with later versions of libSRTP that include more - * elements in the crypto_policy_t datatype. + * elements in the srtp_crypto_policy_t datatype. * * @return void. * @@ -934,7 +934,7 @@ void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p); * @param p is a pointer to the policy structure to be set * * The function call srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(&p) - * sets the crypto_policy_t at location p to use policy + * sets the srtp_crypto_policy_t at location p to use policy * AES_CM_192_HMAC_SHA1_80 as defined in RFC 6188. This policy uses AES-192 * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit * authentication tag. @@ -943,7 +943,7 @@ void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p); * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your * code to be forward compatible with later versions of libSRTP that - * include more elements in the crypto_policy_t datatype. + * include more elements in the srtp_crypto_policy_t datatype. * * @return void. * @@ -958,7 +958,7 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p); * @param p is a pointer to the policy structure to be set * * The function call srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(&p) - * sets the crypto_policy_t at location p to use policy + * sets the srtp_crypto_policy_t at location p to use policy * AES_CM_192_HMAC_SHA1_32 as defined in RFC 6188. This policy uses AES-192 * Counter Mode encryption and HMAC-SHA1 authentication, with an * authentication tag that is only 32 bits long. This length is @@ -970,7 +970,7 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p); * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your * code to be forward compatible with later versions of libSRTP that - * include more elements in the crypto_policy_t datatype. + * include more elements in the srtp_crypto_policy_t datatype. * * @warning This crypto policy is intended for use in SRTP, but not in * SRTCP. It is recommended that a policy that uses longer @@ -989,7 +989,7 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p); * @param p is a pointer to the policy structure to be set * * The function call srtp_crypto_policy_set_aes_cm_192_null_auth(&p) sets - * the crypto_policy_t at location p to use the SRTP default cipher + * the srtp_crypto_policy_t at location p to use the SRTP default cipher * (AES-192 Counter Mode), but to use no authentication method. This * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). @@ -998,7 +998,7 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p); * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your * code to be forward compatible with later versions of libSRTP that - * include more elements in the crypto_policy_t datatype. + * include more elements in the srtp_crypto_policy_t datatype. * * @warning This policy is NOT RECOMMENDED for SRTP unless it is * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see diff --git a/libs/srtp/include/srtp_priv.h b/libs/srtp/include/srtp_priv.h index 661a7f94ab..f89915e09a 100644 --- a/libs/srtp/include/srtp_priv.h +++ b/libs/srtp/include/srtp_priv.h @@ -219,7 +219,7 @@ typedef struct { * 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 diff --git a/libs/srtp/libsrtp.2017.vcxproj b/libs/srtp/libsrtp.2017.vcxproj index db7e71a8e3..e6e06d9a73 100644 --- a/libs/srtp/libsrtp.2017.vcxproj +++ b/libs/srtp/libsrtp.2017.vcxproj @@ -129,6 +129,11 @@ $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ + + + GCM;HAVE_INTTYPES_H;%(PreprocessorDefinitions) + + Creating config.h from config.hw diff --git a/libs/srtp/srtp/ekt.c b/libs/srtp/srtp/ekt.c index b54ecf64eb..24af93bd99 100644 --- a/libs/srtp/srtp/ekt.c +++ b/libs/srtp/srtp/ekt.c @@ -151,7 +151,7 @@ srtp_err_status_t srtp_ekt_stream_init_from_policy( void aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len) { -#ifndef OPENSSL +#ifndef GCM // FIXME: need to get this working through the crypto module interface srtp_aes_expanded_key_t expanded_key; @@ -218,7 +218,7 @@ void srtp_ekt_write_data(srtp_ekt_stream_t ekt, /* if the pointer ekt is NULL, then EKT is not in effect */ if (!ekt) { - debug_print(mod_srtp, "EKT not in use", NULL); + debug_print0(mod_srtp, "EKT not in use"); return; } diff --git a/libs/srtp/srtp/srtp.c b/libs/srtp/srtp/srtp.c index 966757e7ad..1887d7bc82 100644 --- a/libs/srtp/srtp/srtp.c +++ b/libs/srtp/srtp/srtp.c @@ -51,12 +51,13 @@ #include "ekt.h" /* for SRTP Encrypted Key Transport */ #include "alloc.h" /* for srtp_crypto_alloc() */ -#ifdef OPENSSL -#include "aes_gcm_ossl.h" /* for AES GCM mode */ +#ifdef GCM +#include "aes_gcm.h" /* for AES GCM mode */ +#endif + #ifdef OPENSSL_KDF #include -#include "aes_icm_ossl.h" /* for AES GCM mode */ -#endif +#include "aes_icm_ext.h" #endif #include @@ -81,13 +82,14 @@ srtp_debug_module_t mod_srtp = { static srtp_err_status_t srtp_validate_rtp_header(void *rtp_hdr, int *pkt_octet_len) { + srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; + int rtp_header_len; + if (*pkt_octet_len < octets_in_rtp_header) return srtp_err_status_bad_param; - srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; - /* Check RTP header length */ - int rtp_header_len = octets_in_rtp_header + 4 * hdr->cc; + rtp_header_len = octets_in_rtp_header + 4 * hdr->cc; if (hdr->x == 1) rtp_header_len += octets_in_rtp_extn_hdr; @@ -677,6 +679,8 @@ static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, int key_len) { srtp_cipher_type_id_t cipher_id; + srtp_err_status_t stat; + switch (key_len) { case SRTP_AES_ICM_256_KEY_LEN_WSALT: cipher_id = SRTP_AES_ICM_256; @@ -692,7 +696,6 @@ static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, break; } - srtp_err_status_t stat; stat = srtp_crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, key_len, 0); if (stat) return stat; @@ -959,7 +962,7 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, * to generate the salt value */ if (rtp_salt_len > 0) { - debug_print(mod_srtp, "found rtp_salt_len > 0, generating salt", NULL); + debug_print0(mod_srtp, "found rtp_salt_len > 0, generating salt"); /* generate encryption salt, put after encryption key */ stat = srtp_kdf_generate(&kdf, label_rtp_salt, @@ -1067,9 +1070,8 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, * to generate the salt value */ if (rtp_xtn_hdr_salt_len > 0) { - debug_print(mod_srtp, - "found rtp_xtn_hdr_salt_len > 0, generating salt", - NULL); + debug_print0(mod_srtp, + "found rtp_xtn_hdr_salt_len > 0, generating salt"); /* generate encryption salt, put after encryption key */ stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_salt, @@ -1150,8 +1152,7 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, * to generate the salt value */ if (rtcp_salt_len > 0) { - debug_print(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt", - NULL); + debug_print0(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt"); /* generate encryption salt, put after encryption key */ stat = srtp_kdf_generate(&kdf, label_rtcp_salt, @@ -1667,7 +1668,7 @@ static srtp_err_status_t srtp_get_est_pkt_index(srtp_hdr_t *hdr, debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(*est), low32(*est)); #else - debug_print(mod_srtp, "estimated u_packet index: %016llx", *est); + debug_print(mod_srtp, "estimated u_packet index: %016" PRIx64, *est); #endif return result; } @@ -1697,7 +1698,7 @@ static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx, unsigned int mki_size = 0; uint8_t *mki_location = NULL; - debug_print(mod_srtp, "function srtp_protect_aead", NULL); + debug_print0(mod_srtp, "function srtp_protect_aead"); /* * update the key usage limit, and check it to make sure that we @@ -1756,7 +1757,7 @@ static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx, debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est), low32(est)); #else - debug_print(mod_srtp, "estimated packet index: %016llx", est); + debug_print(mod_srtp, "estimated packet index: %016" PRIx64, est); #endif /* @@ -1858,13 +1859,13 @@ static srtp_err_status_t srtp_unprotect_aead(srtp_ctx_t *ctx, unsigned int aad_len; srtp_hdr_xtnd_t *xtn_hdr = NULL; - debug_print(mod_srtp, "function srtp_unprotect_aead", NULL); + debug_print0(mod_srtp, "function srtp_unprotect_aead"); #ifdef NO_64BIT_MATH debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est), low32(est)); #else - debug_print(mod_srtp, "estimated u_packet index: %016llx", est); + debug_print(mod_srtp, "estimated u_packet index: %016" PRIx64, est); #endif /* get tag length from stream */ @@ -2059,7 +2060,7 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, uint8_t *mki_location = NULL; int advance_packet_index = 0; - debug_print(mod_srtp, "function srtp_protect", NULL); + debug_print0(mod_srtp, "function srtp_protect"); /* we assume the hdr is 32-bit aligned to start */ @@ -2230,7 +2231,7 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est), low32(est)); #else - debug_print(mod_srtp, "estimated packet index: %016llx", est); + debug_print(mod_srtp, "estimated packet index: %016" PRIx64, est); #endif /* @@ -2336,7 +2337,7 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, return status; /* run auth func over ROC, put result into auth_tag */ - debug_print(mod_srtp, "estimated packet index: %016llx", est); + debug_print(mod_srtp, "estimated packet index: %016" PRIx64, est); status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, auth_tag); debug_print(mod_srtp, "srtp auth tag: %s", @@ -2389,7 +2390,7 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx, uint32_t roc_to_set = 0; uint16_t seq_to_set = 0; - debug_print(mod_srtp, "function srtp_unprotect", NULL); + debug_print0(mod_srtp, "function srtp_unprotect"); /* we assume the hdr is 32-bit aligned to start */ @@ -2458,7 +2459,7 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx, debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est), low32(est)); #else - debug_print(mod_srtp, "estimated u_packet index: %016llx", est); + debug_print(mod_srtp, "estimated u_packet index: %016" PRIx64, est); #endif /* Determine if MKI is being used and what session keys should be used */ @@ -2614,7 +2615,7 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx, if (status) return srtp_err_status_auth_fail; - if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) + if (srtp_octet_string_is_eq(tmp_tag, auth_tag, tag_len)) return srtp_err_status_auth_fail; } @@ -3285,7 +3286,6 @@ void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p) p->sec_serv = sec_serv_conf; } -#ifdef OPENSSL void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p) { /* @@ -3407,8 +3407,6 @@ void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p) p->sec_serv = sec_serv_conf_and_auth; } -#endif - /* * secure rtcp functions */ @@ -3496,7 +3494,8 @@ static srtp_err_status_t srtp_protect_rtcp_aead( { srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ - uint32_t *trailer; /* pointer to start of trailer */ + uint32_t *trailer_p; /* pointer to start of trailer */ + uint32_t trailer; /* trailer value */ unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ srtp_err_status_t status; @@ -3519,18 +3518,15 @@ static srtp_err_status_t srtp_protect_rtcp_aead( /* NOTE: hdr->length is not usable - it refers to only the first * RTCP report in the compound packet! */ - /* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always - * multiples of 32-bits (RFC 3550 6.1) - */ - trailer = (uint32_t *)((char *)enc_start + enc_octet_len + tag_len); + trailer_p = (uint32_t *)((char *)enc_start + enc_octet_len + tag_len); if (stream->rtcp_services & sec_serv_conf) { - *trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ + trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ } else { enc_start = NULL; enc_octet_len = 0; /* 0 is network-order independant */ - *trailer = 0x00000000; /* set encrypt bit */ + trailer = 0x00000000; /* set encrypt bit */ } mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + tag_len + @@ -3554,9 +3550,11 @@ static srtp_err_status_t srtp_protect_rtcp_aead( return status; } seq_num = srtp_rdb_get_value(&stream->rtcp_rdb); - *trailer |= htonl(seq_num); + trailer |= htonl(seq_num); debug_print(mod_srtp, "srtcp index: %x", seq_num); + memcpy(trailer_p, &trailer, sizeof(trailer)); + /* * Calculate and set the IV */ @@ -3598,7 +3596,7 @@ static srtp_err_status_t srtp_protect_rtcp_aead( /* * Process the sequence# as AAD */ - tseq = *trailer; + tseq = trailer; status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq, sizeof(srtcp_trailer_t)); if (status) { @@ -3667,7 +3665,8 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead( { srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ - uint32_t *trailer; /* pointer to start of trailer */ + uint32_t *trailer_p; /* pointer to start of trailer */ + uint32_t trailer; /* trailer value */ unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ srtp_err_status_t status; @@ -3693,12 +3692,10 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead( */ /* This should point trailer to the word past the end of the normal data. */ /* This would need to be modified for optional mikey data */ - /* - * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always - * multiples of 32-bits (RFC 3550 6.1) - */ - trailer = (uint32_t *)((char *)hdr + *pkt_octet_len - - sizeof(srtcp_trailer_t) - mki_size); + trailer_p = (uint32_t *)((char *)hdr + *pkt_octet_len - + sizeof(srtcp_trailer_t) - mki_size); + memcpy(&trailer, trailer_p, sizeof(trailer)); + /* * We pass the tag down to the cipher when doing GCM mode */ @@ -3707,7 +3704,7 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead( auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len - mki_size - sizeof(srtcp_trailer_t); - if (*((unsigned char *)trailer) & SRTCP_E_BYTE_BIT) { + if (*((unsigned char *)trailer_p) & SRTCP_E_BYTE_BIT) { enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header; } else { enc_octet_len = 0; @@ -3718,7 +3715,7 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead( * check the sequence number for replays */ /* this is easier than dealing with bitfield access */ - seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK; + seq_num = ntohl(trailer) & SRTCP_INDEX_MASK; debug_print(mod_srtp, "srtcp index: %x", seq_num); status = srtp_rdb_check(&stream->rtcp_rdb, seq_num); if (status) { @@ -3768,7 +3765,7 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead( /* * Process the sequence# as AAD */ - tseq = *trailer; + tseq = trailer; status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq, sizeof(srtcp_trailer_t)); if (status) { @@ -3866,7 +3863,8 @@ srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ - uint32_t *trailer; /* pointer to start of trailer */ + uint32_t *trailer_p; /* pointer to start of trailer */ + uint32_t trailer; /* trailer value */ unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ srtp_err_status_t status; @@ -3959,19 +3957,15 @@ srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, * NOTE: hdr->length is not usable - it refers to only the first RTCP report * in the compound packet! */ - /* - * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always - * multiples of 32-bits (RFC 3550 6.1) - */ - trailer = (uint32_t *)((char *)enc_start + enc_octet_len); + trailer_p = (uint32_t *)((char *)enc_start + enc_octet_len); if (stream->rtcp_services & sec_serv_conf) { - *trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ + trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ } else { enc_start = NULL; enc_octet_len = 0; /* 0 is network-order independant */ - *trailer = 0x00000000; /* set encrypt bit */ + trailer = 0x00000000; /* set encrypt bit */ } mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + @@ -3999,9 +3993,11 @@ srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, if (status) return status; seq_num = srtp_rdb_get_value(&stream->rtcp_rdb); - *trailer |= htonl(seq_num); + trailer |= htonl(seq_num); debug_print(mod_srtp, "srtcp index: %x", seq_num); + memcpy(trailer_p, &trailer, sizeof(trailer)); + /* * if we're using rindael counter mode, set nonce and seq */ @@ -4097,7 +4093,8 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ - uint32_t *trailer; /* pointer to start of trailer */ + uint32_t *trailer_p; /* pointer to start of trailer */ + uint32_t trailer; /* trailer value */ unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; @@ -4215,14 +4212,12 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, */ /* This should point trailer to the word past the end of the normal data. */ /* This would need to be modified for optional mikey data */ - /* - * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always - * multiples of 32-bits (RFC 3550 6.1) - */ - trailer = (uint32_t *)((char *)hdr + *pkt_octet_len - - (tag_len + mki_size + sizeof(srtcp_trailer_t))); + trailer_p = (uint32_t *)((char *)hdr + *pkt_octet_len - + (tag_len + mki_size + sizeof(srtcp_trailer_t))); + memcpy(&trailer, trailer_p, sizeof(trailer)); + e_bit_in_packet = - (*((unsigned char *)trailer) & SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT; + (*((unsigned char *)trailer_p) & SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT; if (e_bit_in_packet != sec_serv_confidentiality) { return srtp_err_status_cant_check; } @@ -4266,7 +4261,7 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, * check the sequence number for replays */ /* this is easier than dealing with bitfield access */ - seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK; + seq_num = ntohl(trailer) & SRTCP_INDEX_MASK; debug_print(mod_srtp, "srtcp index: %x", seq_num); status = srtp_rdb_check(&stream->rtcp_rdb, seq_num); if (status) @@ -4315,7 +4310,7 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, /* compare the tag just computed with the one in the packet */ debug_print(mod_srtp, "srtcp tag from packet: %s", srtp_octet_string_hex_string(auth_tag, tag_len)); - if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) + if (srtp_octet_string_is_eq(tmp_tag, auth_tag, tag_len)) return srtp_err_status_auth_fail; /* @@ -4437,7 +4432,7 @@ srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp( case srtp_profile_null_sha1_80: srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); break; -#if defined(OPENSSL) +#ifdef GCM case srtp_profile_aead_aes_128_gcm: srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); break; @@ -4471,7 +4466,7 @@ srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp( case srtp_profile_null_sha1_80: srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); break; -#if defined(OPENSSL) +#ifdef GCM case srtp_profile_aead_aes_128_gcm: srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); break; @@ -4552,10 +4547,10 @@ srtp_err_status_t stream_get_protect_trailer_length(srtp_stream_ctx_t *stream, uint32_t mki_index, uint32_t *length) { - *length = 0; - srtp_session_keys_t *session_key; + *length = 0; + if (use_mki) { if (mki_index >= stream->num_master_keys) { return srtp_err_status_bad_mki; diff --git a/libs/srtp/test/getopt_s.c b/libs/srtp/test/getopt_s.c index ab631878a4..e0bd7f77ed 100644 --- a/libs/srtp/test/getopt_s.c +++ b/libs/srtp/test/getopt_s.c @@ -58,8 +58,9 @@ static int getopt_check_character(char c, const char *string) while (*string != 0) { if (max_string_len == 0) { - return '?'; + return GETOPT_NOT_FOUND; } + max_string_len--; if (*string++ == c) { if (*string == ':') { return GETOPT_FOUND_WITH_ARGUMENT; diff --git a/libs/srtp/test/rdbx_driver.c b/libs/srtp/test/rdbx_driver.c index 609ce9c8e4..df434a0224 100644 --- a/libs/srtp/test/rdbx_driver.c +++ b/libs/srtp/test/rdbx_driver.c @@ -50,6 +50,7 @@ #include "getopt_s.h" /* for local getopt() */ #include "rdbx.h" +#include "cipher_priv.h" #ifdef ROC_TEST #error "srtp_rdbx_t won't work with ROC_TEST - bitmask same size as seq_median" @@ -305,7 +306,7 @@ srtp_err_status_t test_replay_dbx(int num_trials, unsigned long ws) */ printf("\ttesting insertion with large gaps..."); for (idx = 0, ircvd = 0; (int)idx < num_trials; - idx++, ircvd += (1 << (rand() % 12))) { + idx++, ircvd += (1 << (srtp_cipher_rand_u32_for_tests() % 12))) { status = rdbx_check_add(&rdbx, ircvd); if (status) return status; @@ -320,8 +321,7 @@ srtp_err_status_t test_replay_dbx(int num_trials, unsigned long ws) return srtp_err_status_ok; } -#include /* for clock() */ -#include /* for random() */ +#include /* for clock() */ double rdbx_check_adds_per_second(int num_trials, unsigned long ws) { @@ -348,6 +348,9 @@ double rdbx_check_adds_per_second(int num_trials, unsigned long ws) ++failures; } timer = clock() - timer; + if (timer < 1) { + timer = 1; + } printf("number of failures: %d \n", failures); diff --git a/libs/srtp/test/replay_driver.c b/libs/srtp/test/replay_driver.c index a88224684f..e0808b685a 100644 --- a/libs/srtp/test/replay_driver.c +++ b/libs/srtp/test/replay_driver.c @@ -52,6 +52,8 @@ #include "rdb.h" #include "ut_sim.h" +#include "cipher_priv.h" + /* * num_trials defines the number of trials that are used in the * validation functions below @@ -189,7 +191,7 @@ srtp_err_status_t test_rdb_db() /* test insertion with large gaps */ for (idx = 0, ircvd = 0; idx < num_trials; - idx++, ircvd += (1 << (rand() % 10))) { + idx++, ircvd += (1 << (srtp_cipher_rand_u32_for_tests() % 10))) { err = rdb_check_add(&rdb, ircvd); if (err) return err; diff --git a/libs/srtp/test/roc_driver.c b/libs/srtp/test/roc_driver.c index d61ba8ef24..439862039a 100644 --- a/libs/srtp/test/roc_driver.c +++ b/libs/srtp/test/roc_driver.c @@ -97,7 +97,7 @@ srtp_err_status_t roc_test(int num_trials) printf("\n\ttesting sequential insertion..."); for (i = 0; i < 2048; i++) { - delta = srtp_index_guess(&local, &est, (uint16_t)ref); + srtp_index_guess(&local, &est, (uint16_t)ref); #if ROC_VERBOSE printf("%lld, %lld, %d\n", ref, est, i); #endif diff --git a/libs/srtp/test/rtp.c b/libs/srtp/test/rtp.c index f60a9b11b2..70248ee2b5 100644 --- a/libs/srtp/test/rtp.c +++ b/libs/srtp/test/rtp.c @@ -53,6 +53,8 @@ #include #endif +#include "cipher_priv.h" + #define PRINT_DEBUG 0 /* set to 1 to print out debugging data */ #define VERBOSE_DEBUG 0 /* set to 1 to print out more data */ @@ -148,7 +150,7 @@ int rtp_sender_init(rtp_sender_t sender, /* set header values */ sender->message.header.ssrc = htonl(ssrc); sender->message.header.ts = 0; - sender->message.header.seq = (uint16_t)rand(); + sender->message.header.seq = (uint16_t)srtp_cipher_rand_u32_for_tests(); sender->message.header.m = 0; sender->message.header.pt = 0x1; sender->message.header.version = 2; diff --git a/libs/srtp/test/rtp_decoder.c b/libs/srtp/test/rtp_decoder.c index d718a2b3ad..8c89a2c101 100644 --- a/libs/srtp/test/rtp_decoder.c +++ b/libs/srtp/test/rtp_decoder.c @@ -83,23 +83,76 @@ #define MAX_KEY_LEN 96 #define MAX_FILTER 256 +#define MAX_FILE 255 struct srtp_crypto_suite { const char *can_name; + int gcm_on; int key_size; int tag_size; }; static struct srtp_crypto_suite srtp_crypto_suites[] = { - {.can_name = "AES_CM_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4 }, #if 0 - {.can_name = "F8_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4}, + {.can_name = "F8_128_HMAC_SHA1_32", .gcm_on = 0, .key_size = 128, .tag_size = 4}, #endif - {.can_name = "AES_CM_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4 }, - {.can_name = "AES_CM_128_HMAC_SHA1_80", .key_size = 128, .tag_size = 10 }, + {.can_name = "AES_CM_128_HMAC_SHA1_32", + .gcm_on = 0, + .key_size = 128, + .tag_size = 4 }, + {.can_name = "AES_CM_128_HMAC_SHA1_80", + .gcm_on = 0, + .key_size = 128, + .tag_size = 10 }, + {.can_name = "AES_192_CM_HMAC_SHA1_32", + .gcm_on = 0, + .key_size = 192, + .tag_size = 4 }, + {.can_name = "AES_192_CM_HMAC_SHA1_80", + .gcm_on = 0, + .key_size = 192, + .tag_size = 10 }, + {.can_name = "AES_256_CM_HMAC_SHA1_32", + .gcm_on = 0, + .key_size = 256, + .tag_size = 4 }, + {.can_name = "AES_256_CM_HMAC_SHA1_80", + .gcm_on = 0, + .key_size = 256, + .tag_size = 10 }, + {.can_name = "AEAD_AES_128_GCM", + .gcm_on = 1, + .key_size = 128, + .tag_size = 16 }, + {.can_name = "AEAD_AES_256_GCM", + .gcm_on = 1, + .key_size = 256, + .tag_size = 16 }, {.can_name = NULL } }; +void rtp_decoder_srtp_log_handler(srtp_log_level_t level, + const char *msg, + void *data) +{ + char level_char = '?'; + switch (level) { + case srtp_log_level_error: + level_char = 'e'; + break; + case srtp_log_level_warning: + level_char = 'w'; + break; + case srtp_log_level_info: + level_char = 'i'; + break; + case srtp_log_level_debug: + level_char = 'd'; + break; + } + fprintf(stderr, "SRTP-LOG [%c]: %s\n", level_char, msg); +} + int main(int argc, char *argv[]) { char errbuf[PCAP_ERRBUF_SIZE]; @@ -112,15 +165,18 @@ int main(int argc, char *argv[]) int c; struct srtp_crypto_suite scs, *i_scsp; scs.key_size = 128; - scs.tag_size = 8; + scs.tag_size = 0; int gcm_on = 0; char *input_key = NULL; int b64_input = 0; char key[MAX_KEY_LEN]; struct bpf_program fp; char filter_exp[MAX_FILTER] = ""; + char pcap_file[MAX_FILE] = "-"; + int rtp_packet_offset = DEFAULT_RTP_OFFSET; rtp_decoder_t dec; - srtp_policy_t policy; + srtp_policy_t policy = { { 0 } }; + rtp_decoder_mode_t mode = mode_rtp; srtp_err_status_t status; int len; int expected_len; @@ -138,9 +194,15 @@ int main(int argc, char *argv[]) exit(1); } + status = srtp_install_log_handler(rtp_decoder_srtp_log_handler, NULL); + if (status) { + fprintf(stderr, "error: install log handler failed\n"); + exit(1); + } + /* check args */ while (1) { - c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:s:"); + c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:s:m:p:o:"); if (c == -1) { break; } @@ -153,10 +215,12 @@ int main(int argc, char *argv[]) break; case 'e': scs.key_size = atoi(optarg_s); - if (scs.key_size != 128 && scs.key_size != 256) { - fprintf(stderr, - "error: encryption key size must be 128 or 256 (%d)\n", - scs.key_size); + if (scs.key_size != 128 && scs.key_size != 192 && + scs.key_size != 256) { + fprintf( + stderr, + "error: encryption key size must be 128, 192 or 256 (%d)\n", + scs.key_size); exit(1); } input_key = malloc(scs.key_size); @@ -173,7 +237,7 @@ int main(int argc, char *argv[]) sec_servs |= sec_serv_auth; break; case 'd': - status = srtp_crypto_kernel_set_debug_module(optarg_s, 1); + status = srtp_set_debug_module(optarg_s, 1); if (status) { fprintf(stderr, "error: set debug module (%s) failed\n", optarg_s); @@ -207,20 +271,59 @@ int main(int argc, char *argv[]) scs = *i_scsp; input_key = malloc(scs.key_size); sec_servs |= sec_serv_conf | sec_serv_auth; + gcm_on = scs.gcm_on; + break; + case 'm': + if (strcasecmp("rtp", optarg_s) == 0) { + mode = mode_rtp; + } else if (strcasecmp("rtcp", optarg_s) == 0) { + mode = mode_rtcp; + } else if (strcasecmp("rtcp-mux", optarg_s) == 0) { + mode = mode_rtcp_mux; + } else { + fprintf(stderr, "Unknown/unsupported mode %s\n", optarg_s); + exit(1); + } + break; + case 'p': + if (strlen(optarg_s) > MAX_FILE) { + fprintf(stderr, + "error: pcap file path bigger than %d characters\n", + MAX_FILE); + exit(1); + } + strcpy(pcap_file, optarg_s); + break; + case 'o': + rtp_packet_offset = atoi(optarg_s); break; default: usage(argv[0]); } } + if (scs.tag_size == 0) { + if (gcm_on) { + scs.tag_size = 16; + } else { + scs.tag_size = 10; + } + } + if (gcm_on && scs.tag_size != 8 && scs.tag_size != 16) { fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n", scs.tag_size); - // exit(1); + exit(1); + } + + if (!gcm_on && scs.tag_size != 4 && scs.tag_size != 10) { + fprintf(stderr, "error: non GCM tag size must be 4 or 10 (%d)\n", + scs.tag_size); + exit(1); } if (do_list_mods) { - status = srtp_crypto_kernel_list_debug_modules(); + status = srtp_list_debug_modules(); if (status) { fprintf(stderr, "error: list of debug modules failed\n"); exit(1); @@ -266,12 +369,24 @@ int main(int argc, char *argv[]) #ifdef OPENSSL switch (scs.key_size) { case 128: - srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); + if (scs.tag_size == 16) { + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth( + &policy.rtcp); + } else { + srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); + srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); + } break; case 256: - srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); - srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); + if (scs.tag_size == 16) { + srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); + srtp_crypto_policy_set_aes_gcm_256_16_auth( + &policy.rtcp); + } else { + srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); + srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); + } break; } #else @@ -282,12 +397,51 @@ int main(int argc, char *argv[]) } else { switch (scs.key_size) { case 128: - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + if (scs.tag_size == 4) { + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32( + &policy.rtp); + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( + &policy.rtcp); + } else { + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( + &policy.rtp); + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( + &policy.rtcp); + } + break; + case 192: +#ifdef OPENSSL + if (scs.tag_size == 4) { + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32( + &policy.rtp); + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( + &policy.rtcp); + } else { + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( + &policy.rtp); + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( + &policy.rtcp); + } +#else + fprintf(stderr, + "error: AES 192 mode only supported when using the " + "OpenSSL crypto engine.\n"); + return 0; + +#endif break; case 256: - srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + if (scs.tag_size == 4) { + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32( + &policy.rtp); + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( + &policy.rtcp); + } else { + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( + &policy.rtp); + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( + &policy.rtcp); + } break; } } @@ -302,11 +456,26 @@ int main(int argc, char *argv[]) switch (scs.key_size) { case 128: srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80( + &policy.rtcp); + break; + case 192: +#ifdef OPENSSL + srtp_crypto_policy_set_aes_cm_192_null_auth(&policy.rtp); + srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80( + &policy.rtcp); +#else + fprintf(stderr, + "error: AES 192 mode only supported when using the " + "OpenSSL crypto engine.\n"); + return 0; + +#endif break; case 256: srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80( + &policy.rtcp); break; } } @@ -353,7 +522,7 @@ int main(int argc, char *argv[]) policy.rtp.auth_tag_len = scs.tag_size; if (gcm_on && scs.tag_size != 8) { - fprintf(stderr, "setted tag len %d\n", scs.tag_size); + fprintf(stderr, "set tag len %d\n", scs.tag_size); policy.rtp.auth_tag_len = scs.tag_size; } @@ -365,11 +534,7 @@ int main(int argc, char *argv[]) int pad; expected_len = policy.rtp.cipher_key_len * 4 / 3; len = base64_string_to_octet_string(key, &pad, input_key, - expected_len); - if (pad != 0) { - fprintf(stderr, "error: padding in base64 unexpected\n"); - exit(1); - } + strlen(input_key)); } else { expected_len = policy.rtp.cipher_key_len * 2; len = hex_string_to_octet_string(key, input_key, expected_len); @@ -388,17 +553,20 @@ int main(int argc, char *argv[]) exit(1); } + int key_octets = (scs.key_size / 8); + int salt_octets = policy.rtp.cipher_key_len - key_octets; fprintf(stderr, "set master key/salt to %s/", - octet_string_hex_string(key, 16)); - fprintf(stderr, "%s\n", octet_string_hex_string(key + 16, 14)); + octet_string_hex_string(key, key_octets)); + fprintf(stderr, "%s\n", + octet_string_hex_string(key + key_octets, salt_octets)); } else { fprintf(stderr, - "error: neither encryption or authentication were selected"); + "error: neither encryption or authentication were selected\n"); exit(1); } - pcap_handle = pcap_open_offline("-", errbuf); + pcap_handle = pcap_open_offline(pcap_file, errbuf); if (!pcap_handle) { fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf); @@ -421,11 +589,22 @@ int main(int argc, char *argv[]) exit(1); } fprintf(stderr, "Starting decoder\n"); - rtp_decoder_init(dec, policy); + if (rtp_decoder_init(dec, policy, mode, rtp_packet_offset)) { + fprintf(stderr, "error: init failed\n"); + exit(1); + } pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec); - rtp_decoder_deinit_srtp(dec); + if (dec->mode == mode_rtp || dec->mode == mode_rtcp_mux) { + fprintf(stderr, "RTP packets decoded: %d\n", dec->rtp_cnt); + } + if (dec->mode == mode_rtcp || dec->mode == mode_rtcp_mux) { + fprintf(stderr, "RTCP packets decoded: %d\n", dec->rtcp_cnt); + } + fprintf(stderr, "Packet decode errors: %d\n", dec->error_cnt); + + rtp_decoder_deinit(dec); rtp_decoder_dealloc(dec); status = srtp_shutdown(); @@ -442,7 +621,8 @@ void usage(char *string) { fprintf( stderr, - "usage: %s [-d ]* [[-k][-b] [-a][-e]]\n" + "usage: %s [-d ]* [[-k][-b] ] [-a][-t][-e] [-s " + "] [-m ]\n" "or %s -l\n" "where -a use message authentication\n" " -e use encryption (use 128 or 256 for key size)\n" @@ -454,7 +634,10 @@ void usage(char *string) " -f \"\" to filter only the desired SRTP packets\n" " -d turn on debugging for module \n" " -s \"\" to set both key and tag size based\n" - " on RFC4568-style crypto suite specification\n", + " on RFC4568-style crypto suite specification\n" + " -m set the mode to be one of [rtp]|rtcp|rtcp-mux\n" + " -p path to pcap file (defaults to stdin)\n" + " -o byte offset of RTP packet in capture (defaults to 42)\n", string, string); exit(1); } @@ -469,27 +652,34 @@ void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx) free(rtp_ctx); } -srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder, - unsigned int ssrc) +int rtp_decoder_deinit(rtp_decoder_t decoder) { - decoder->policy.ssrc.value = htonl(ssrc); - return srtp_create(&decoder->srtp_ctx, &decoder->policy); + if (decoder->srtp_ctx) { + return srtp_dealloc(decoder->srtp_ctx); + } + return 0; } -int rtp_decoder_deinit_srtp(rtp_decoder_t decoder) +int rtp_decoder_init(rtp_decoder_t dcdr, + srtp_policy_t policy, + rtp_decoder_mode_t mode, + int rtp_packet_offset) { - return srtp_dealloc(decoder->srtp_ctx); -} - -int rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy) -{ - dcdr->rtp_offset = DEFAULT_RTP_OFFSET; + dcdr->rtp_offset = rtp_packet_offset; dcdr->srtp_ctx = NULL; dcdr->start_tv.tv_usec = 0; dcdr->start_tv.tv_sec = 0; dcdr->frame_nr = -1; + dcdr->error_cnt = 0; + dcdr->rtp_cnt = 0; + dcdr->rtcp_cnt = 0; + dcdr->mode = mode; dcdr->policy = policy; - dcdr->policy.ssrc.type = ssrc_specific; + dcdr->policy.ssrc.type = ssrc_any_inbound; + + if (srtp_create(&dcdr->srtp_ctx, &dcdr->policy)) { + return 1; + } return 0; } @@ -516,6 +706,8 @@ void rtp_decoder_handle_pkt(u_char *arg, const u_char *bytes) { rtp_decoder_t dcdr = (rtp_decoder_t)arg; + rtp_msg_t message; + int rtp; int pktsize; struct timeval delta; int octets_recvd; @@ -531,7 +723,7 @@ void rtp_decoder_handle_pkt(u_char *arg, } const void *rtp_packet = bytes + dcdr->rtp_offset; - memcpy((void *)&dcdr->message, rtp_packet, hdr->caplen - dcdr->rtp_offset); + memcpy((void *)&message, rtp_packet, hdr->caplen - dcdr->rtp_offset); pktsize = hdr->caplen - dcdr->rtp_offset; octets_recvd = pktsize; @@ -539,24 +731,43 @@ void rtp_decoder_handle_pkt(u_char *arg, return; } - /* verify rtp header */ - if (dcdr->message.header.version != 2) { - return; - } - if (dcdr->srtp_ctx == NULL) { - status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc); - if (status) { - exit(1); + if (dcdr->mode == mode_rtp) { + rtp = 1; + } else if (dcdr->mode == mode_rtcp) { + rtp = 0; + } else { + rtp = 1; + if (octets_recvd >= 2) { + /* rfc5761 */ + u_char payload_type = *(bytes + dcdr->rtp_offset + 1) & 0x7f; + rtp = payload_type < 64 || payload_type > 95; } } - status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd); - if (status) { - return; + + if (rtp) { + /* verify rtp header */ + if (message.header.version != 2) { + return; + } + + status = srtp_unprotect(dcdr->srtp_ctx, &message, &octets_recvd); + if (status) { + dcdr->error_cnt++; + return; + } + dcdr->rtp_cnt++; + } else { + status = srtp_unprotect_rtcp(dcdr->srtp_ctx, &message, &octets_recvd); + if (status) { + dcdr->error_cnt++; + return; + } + dcdr->rtcp_cnt++; } timersub(&hdr->ts, &dcdr->start_tv, &delta); fprintf(stdout, "%02ld:%02ld.%06ld\n", delta.tv_sec / 60, delta.tv_sec % 60, (long)delta.tv_usec); - hexdump(&dcdr->message, octets_recvd); + hexdump(&message, octets_recvd); } void rtp_print_error(srtp_err_status_t status, char *message) diff --git a/libs/srtp/test/rtp_decoder.h b/libs/srtp/test/rtp_decoder.h index c8c31dd773..27e8880f2c 100644 --- a/libs/srtp/test/rtp_decoder.h +++ b/libs/srtp/test/rtp_decoder.h @@ -52,13 +52,22 @@ #define DEFAULT_RTP_OFFSET 42 +typedef enum { + mode_rtp = 0, + mode_rtcp, + mode_rtcp_mux, +} rtp_decoder_mode_t; + typedef struct rtp_decoder_ctx_t { srtp_policy_t policy; srtp_ctx_t *srtp_ctx; + rtp_decoder_mode_t mode; int rtp_offset; struct timeval start_tv; int frame_nr; - rtp_msg_t message; + int error_cnt; + int rtp_cnt; + int rtcp_cnt; } rtp_decoder_ctx_t; typedef struct rtp_decoder_ctx_t *rtp_decoder_t; @@ -95,11 +104,19 @@ rtp_decoder_t rtp_decoder_alloc(void); void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx); -int rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy); +int rtp_decoder_init(rtp_decoder_t dcdr, + srtp_policy_t policy, + rtp_decoder_mode_t mode, + int rtp_packet_offset); -srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder, - unsigned int ssrc); +int rtp_decoder_deinit(rtp_decoder_t decoder); -int rtp_decoder_deinit_srtp(rtp_decoder_t decoder); +void rtp_decoder_srtp_log_handler(srtp_log_level_t level, + const char *msg, + void *data); + +void rtp_decoder_srtp_log_handler(srtp_log_level_t level, + const char *msg, + void *data); #endif /* RTP_DECODER_H */ diff --git a/libs/srtp/test/rtpw.c b/libs/srtp/test/rtpw.c index 6e7416c7f5..901816e46d 100644 --- a/libs/srtp/test/rtpw.c +++ b/libs/srtp/test/rtpw.c @@ -317,6 +317,7 @@ int main(int argc, char *argv[]) exit(1); } + memset(&name, 0, sizeof(struct sockaddr_in)); name.sin_addr = rcvr_addr; name.sin_family = PF_INET; name.sin_port = htons(port); @@ -364,7 +365,7 @@ int main(int argc, char *argv[]) switch (sec_servs) { case sec_serv_conf_and_auth: if (gcm_on) { -#ifdef OPENSSL +#ifdef GCM switch (key_size) { case 128: srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); @@ -377,7 +378,7 @@ int main(int argc, char *argv[]) } #else printf("error: GCM mode only supported when using the OpenSSL " - "crypto engine.\n"); + "or NSS crypto engine.\n"); return 0; #endif } else { @@ -413,7 +414,7 @@ int main(int argc, char *argv[]) break; case sec_serv_auth: if (gcm_on) { -#ifdef OPENSSL +#ifdef GCM switch (key_size) { case 128: srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp); diff --git a/libs/srtp/test/rtpw_test.sh b/libs/srtp/test/rtpw_test.sh index 238ec93c5d..158a39312d 100755 --- a/libs/srtp/test/rtpw_test.sh +++ b/libs/srtp/test/rtpw_test.sh @@ -41,8 +41,13 @@ case $(uname -s) in *CYGWIN*|*MINGW*) EXE=".exe" ;; - *) + *Linux*) EXE="" + export LD_LIBRARY_PATH=$CRYPTO_LIBDIR + ;; + *Darwin*) + EXE="" + export DYLD_LIBRARY_PATH=$CRYPTO_LIBDIR ;; esac diff --git a/libs/srtp/test/rtpw_test_gcm.sh b/libs/srtp/test/rtpw_test_gcm.sh index 773400562c..644255e1a1 100755 --- a/libs/srtp/test/rtpw_test_gcm.sh +++ b/libs/srtp/test/rtpw_test_gcm.sh @@ -41,8 +41,13 @@ case $(uname -s) in *CYGWIN*|*MINGW*) EXE=".exe" ;; - *) + *Linux*) EXE="" + export LD_LIBRARY_PATH=$CRYPTO_LIBDIR + ;; + *Darwin*) + EXE="" + export DYLD_LIBRARY_PATH=$CRYPTO_LIBDIR ;; esac diff --git a/libs/srtp/test/srtp_driver.c b/libs/srtp/test/srtp_driver.c index 4ea8fe5302..1335540609 100644 --- a/libs/srtp/test/srtp_driver.c +++ b/libs/srtp/test/srtp_driver.c @@ -61,13 +61,13 @@ srtp_err_status_t srtp_validate(void); -#ifdef OPENSSL +#ifdef GCM srtp_err_status_t srtp_validate_gcm(void); #endif srtp_err_status_t srtp_validate_encrypted_extensions_headers(void); -#ifdef OPENSSL +#ifdef GCM srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void); #endif @@ -79,7 +79,7 @@ srtp_err_status_t srtp_dealloc_big_policy(srtp_policy_t *list); srtp_err_status_t srtp_test_empty_payload(void); -#ifdef OPENSSL +#ifdef GCM srtp_err_status_t srtp_test_empty_payload_gcm(void); #endif @@ -422,7 +422,7 @@ int main(int argc, char *argv[]) exit(1); } -#ifdef OPENSSL +#ifdef GCM printf("testing srtp_protect and srtp_unprotect against " "reference packet using GCM\n"); if (srtp_validate_gcm() == srtp_err_status_ok) { @@ -442,7 +442,7 @@ int main(int argc, char *argv[]) exit(1); } -#ifdef OPENSSL +#ifdef GCM printf("testing srtp_protect and srtp_unprotect against " "reference packet with encrypted extension headers (GCM)\n"); if (srtp_validate_encrypted_extensions_headers_gcm() == @@ -478,7 +478,7 @@ int main(int argc, char *argv[]) printf("failed\n"); exit(1); } -#ifdef OPENSSL +#ifdef GCM printf("testing srtp_protect and srtp_unprotect against " "packet with empty payload (GCM)\n"); if (srtp_test_empty_payload_gcm() == srtp_err_status_ok) { @@ -1341,6 +1341,8 @@ srtp_err_status_t srtcp_test(const srtp_policy_t *policy, int mki_index) */ rcvr_policy = (srtp_policy_t *)malloc(sizeof(srtp_policy_t)); if (rcvr_policy == NULL) { + free(hdr); + free(hdr2); return srtp_err_status_alloc_fail; } memcpy(rcvr_policy, policy, sizeof(srtp_policy_t)); @@ -1606,6 +1608,9 @@ double mips_estimate(int num_trials, int *ignore) sum += i; } t = clock() - t; + if (t < 1) { + t = 1; + } /* printf("%d\n", sum); */ *ignore = sum; @@ -1702,7 +1707,7 @@ srtp_err_status_t srtp_validate() debug_print(mod_driver, "ciphertext reference:\n %s", octet_string_hex_string(srtp_ciphertext, len)); - if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) { + if (srtp_octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) { return srtp_err_status_fail; } @@ -1720,7 +1725,7 @@ srtp_err_status_t srtp_validate() debug_print(mod_driver, "srtcp ciphertext reference:\n %s", octet_string_hex_string(srtcp_ciphertext, len)); - if (octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) { + if (srtp_octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) { return srtp_err_status_fail; } @@ -1742,7 +1747,7 @@ srtp_err_status_t srtp_validate() return status; } - if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) { + if (srtp_octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) { return srtp_err_status_fail; } @@ -1755,7 +1760,7 @@ srtp_err_status_t srtp_validate() return status; } - if (octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) { + if (srtp_octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) { return srtp_err_status_fail; } @@ -1772,7 +1777,7 @@ srtp_err_status_t srtp_validate() return srtp_err_status_ok; } -#ifdef OPENSSL +#ifdef GCM /* * srtp_validate_gcm() verifies the correctness of libsrtp by comparing * an computed packet against the known ciphertext for the plaintext. @@ -1870,7 +1875,7 @@ srtp_err_status_t srtp_validate_gcm() debug_print(mod_driver, "srtp ciphertext reference:\n %s", octet_string_hex_string(srtp_ciphertext, len)); - if (octet_string_is_eq(rtp_plaintext, srtp_ciphertext, len)) { + if (srtp_octet_string_is_eq(rtp_plaintext, srtp_ciphertext, len)) { return srtp_err_status_fail; } @@ -1888,7 +1893,7 @@ srtp_err_status_t srtp_validate_gcm() debug_print(mod_driver, "srtcp ciphertext reference:\n %s", octet_string_hex_string(srtcp_ciphertext, len)); - if (octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) { + if (srtp_octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) { return srtp_err_status_fail; } @@ -1911,7 +1916,7 @@ srtp_err_status_t srtp_validate_gcm() return status; } - if (octet_string_is_eq(srtp_ciphertext, rtp_plaintext_ref, len)) { + if (srtp_octet_string_is_eq(srtp_ciphertext, rtp_plaintext_ref, len)) { return srtp_err_status_fail; } @@ -1924,7 +1929,7 @@ srtp_err_status_t srtp_validate_gcm() return status; } - if (octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) { + if (srtp_octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) { return srtp_err_status_fail; } @@ -2027,7 +2032,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers() debug_print(mod_driver, "ciphertext reference:\n %s", srtp_octet_string_hex_string(srtp_ciphertext, len)); - if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) + if (srtp_octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) return srtp_err_status_fail; /* @@ -2049,7 +2054,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers() return srtp_err_status_fail; } - if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) + if (srtp_octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) return srtp_err_status_fail; status = srtp_dealloc(srtp_snd); @@ -2063,7 +2068,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers() return srtp_err_status_ok; } -#ifdef OPENSSL +#ifdef GCM /* * Headers of test vectors taken from RFC 6904, Appendix A @@ -2148,7 +2153,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm() debug_print(mod_driver, "ciphertext reference:\n %s", srtp_octet_string_hex_string(srtp_ciphertext, len)); - if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) + if (srtp_octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) return srtp_err_status_fail; /* @@ -2170,7 +2175,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm() return srtp_err_status_fail; } - if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) + if (srtp_octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) return srtp_err_status_fail; status = srtp_dealloc(srtp_snd); @@ -2264,7 +2269,7 @@ srtp_err_status_t srtp_validate_aes_256() debug_print(mod_driver, "ciphertext reference:\n %s", octet_string_hex_string(srtp_ciphertext, len)); - if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) { + if (srtp_octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) { return srtp_err_status_fail; } @@ -2286,7 +2291,7 @@ srtp_err_status_t srtp_validate_aes_256() return status; } - if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) { + if (srtp_octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) { return srtp_err_status_fail; } @@ -2424,7 +2429,7 @@ srtp_err_status_t srtp_test_empty_payload() return srtp_err_status_ok; } -#ifdef OPENSSL +#ifdef GCM srtp_err_status_t srtp_test_empty_payload_gcm() { srtp_t srtp_snd, srtp_recv; @@ -2499,7 +2504,7 @@ srtp_err_status_t srtp_test_empty_payload_gcm() return srtp_err_status_ok; } -#endif // OPENSSL +#endif // GCM srtp_err_status_t srtp_test_remove_stream() { @@ -2783,10 +2788,10 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams( srtp_policy_t policy; srtp_policy_t policy_mki; -#ifdef OPENSSL +#ifdef GCM srtp_policy_t policy_aes_gcm; srtp_policy_t policy_aes_gcm_mki; -#endif // OPENSSL +#endif // GCM memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_rtp_default(&policy.rtp); @@ -2810,7 +2815,7 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams( policy_mki.keys = test_keys; policy_mki.num_master_keys = 2; -#ifdef OPENSSL +#ifdef GCM memset(&policy_aes_gcm, 0, sizeof(policy_aes_gcm)); srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtp); srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtcp); @@ -2832,7 +2837,7 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams( policy_aes_gcm_mki.key = NULL; policy_aes_gcm_mki.keys = test_keys; policy_aes_gcm_mki.num_master_keys = 2; -#endif +#endif // GCM /* create a send ctx with defualt profile and test_key */ status = srtp_create(srtp_send, &policy); @@ -2843,7 +2848,7 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams( if (status) return status; -#ifdef OPENSSL +#ifdef GCM status = srtp_create(srtp_send_aes_gcm, &policy_aes_gcm); if (status) return status; @@ -2851,7 +2856,7 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams( status = srtp_create(srtp_send_aes_gcm_mki, &policy_aes_gcm_mki); if (status) return status; -#endif // OPENSSL +#endif // GCM return srtp_err_status_ok; } @@ -2884,7 +2889,7 @@ srtp_err_status_t srtp_test_protect_trailer_length() if (length != 14) return srtp_err_status_fail; -#ifdef OPENSSL +#ifdef GCM status = srtp_get_protect_trailer_length(srtp_send_aes_gcm, 0, 0, &length); if (status) return status; @@ -2901,11 +2906,11 @@ srtp_err_status_t srtp_test_protect_trailer_length() /* TAG Length: 16 bytes + MKI length: 4 bytes*/ if (length != 20) return srtp_err_status_fail; -#endif // OPENSSL +#endif // GCM srtp_dealloc(srtp_send); srtp_dealloc(srtp_send_mki); -#ifdef OPENSSL +#ifdef GCM srtp_dealloc(srtp_send_aes_gcm); srtp_dealloc(srtp_send_aes_gcm_mki); #endif @@ -2941,7 +2946,7 @@ srtp_err_status_t srtp_test_protect_rtcp_trailer_length() if (length != 18) return srtp_err_status_fail; -#ifdef OPENSSL +#ifdef GCM status = srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm, 0, 0, &length); if (status) @@ -2959,11 +2964,11 @@ srtp_err_status_t srtp_test_protect_rtcp_trailer_length() /* TAG Length: 16 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/ if (length != 24) return srtp_err_status_fail; -#endif // OPENSSL +#endif // GCM srtp_dealloc(srtp_send); srtp_dealloc(srtp_send_mki); -#ifdef OPENSSL +#ifdef GCM srtp_dealloc(srtp_send_aes_gcm); srtp_dealloc(srtp_send_aes_gcm_mki); #endif @@ -3088,6 +3093,7 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets, if (status) { return status; } + seq++; ts++; } @@ -3500,7 +3506,7 @@ const srtp_policy_t hmac_only_policy = { NULL }; -#ifdef OPENSSL +#ifdef GCM const srtp_policy_t aes128_gcm_8_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ { @@ -3786,7 +3792,7 @@ const srtp_policy_t *policy_array[] = { &hmac_only_policy, &aes_only_policy, &default_policy, -#ifdef OPENSSL +#ifdef GCM &aes128_gcm_8_policy, &aes128_gcm_8_cauth_policy, &aes256_gcm_8_policy, diff --git a/libs/srtp/test/test_srtp.c b/libs/srtp/test/test_srtp.c index cdc9b5d5b7..0cea1f3c37 100644 --- a/libs/srtp/test/test_srtp.c +++ b/libs/srtp/test/test_srtp.c @@ -43,16 +43,16 @@ * */ -/* - * Test specific. - */ -#include "cutest.h" - /* * libSRTP specific. */ #include "../srtp/srtp.c" // Get access to static functions +/* + * Test specific. + */ +#include "cutest.h" + /* * Standard library. */ @@ -152,14 +152,15 @@ void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number() srtp_session_keys_t session_keys; srtcp_hdr_t header; v128_t output_iv[SAMPLE_COUNT]; - memset(&output_iv, 0, SAMPLE_COUNT * sizeof(v128_t)); uint32_t sequence_num[SAMPLE_COUNT]; + v128_t final_iv[SAMPLE_COUNT]; + size_t i = 0; + memset(&output_iv, 0, SAMPLE_COUNT * sizeof(v128_t)); sequence_num[0] = 0xFF; sequence_num[1] = 0xFF00; sequence_num[2] = 0xFF0000; // Postconditions - v128_t final_iv[SAMPLE_COUNT]; memset(&final_iv, 0, SAMPLE_COUNT * sizeof(v128_t)); final_iv[0].v8[11] = 0xFF; final_iv[1].v8[10] = 0xFF; @@ -170,7 +171,6 @@ void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number() memset(&header, 0, sizeof(srtcp_hdr_t)); // When - size_t i = 0; for (i = 0; i < SAMPLE_COUNT; i++) { TEST_CHECK(srtp_calc_aead_iv_srtcp(&session_keys, &output_iv[i], sequence_num[i], diff --git a/libs/srtp/test/util.c b/libs/srtp/test/util.c index eb203f4c4a..2abc28e7f9 100644 --- a/libs/srtp/test/util.c +++ b/libs/srtp/test/util.c @@ -42,12 +42,14 @@ * */ +#include "config.h" #include "util.h" #include #include -char bit_string[MAX_PRINT_STRING_LEN]; +/* include space for null terminator */ +char bit_string[MAX_PRINT_STRING_LEN + 1]; static inline int hex_char_to_nibble(uint8_t c) { @@ -151,7 +153,7 @@ char *octet_string_hex_string(const void *s, int length) /* truncate string if it would be too long */ if (length > MAX_PRINT_STRING_LEN) { - length = MAX_PRINT_STRING_LEN - 1; + length = MAX_PRINT_STRING_LEN; } for (i = 0; i < length; i += 2) {