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=
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 \
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
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"])
-
-if test "${enable_optimizer}" = "yes" ; then
- AC_DEFINE([OPTIMZER],[],[Enable Optimization.])
- AX_CC_MAXOPT
-fi
-
-# 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
+dnl Check the byte order
+AC_C_BIGENDIAN
+AC_CANONICAL_HOST
-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"
- fi
+dnl Checks for supported compiler flags.
+supported_cflags=""
+if test "$EMPTY_CFLAGS" = "no"; then
+ supported_cflags="$CFLAGS"
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])
-
-
-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.])
+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_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 When turning off warnigns, we're expecting unrecognized command line option errors if they're not
+dnl supported. However, the -Wno-<warning> 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
+
+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 <inttypes.h>
-#include <byteswap.h>
-]],[[
-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(syslog.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_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
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 <winsock2.h>
-],[
-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
+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_logging])
+PKG_PROG_PKG_CONFIG
+AS_IF([test "x$PKG_CONFIG" != "x"], [PKG_CONFIG="$PKG_CONFIG --static"])
-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 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 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.])
-fi
-AC_MSG_RESULT($enable_debug)
-
-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)
+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_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.])
+ 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])])
+
+ 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])
+ AC_SUBST([USE_EXTERNAL_CRYPTO], [1])
+
+ AC_MSG_CHECKING([if OPENSSL_cleanse is broken])
+ AC_RUN_IFELSE([AC_LANG_PROGRAM([
+ #include <stdio.h>
+ #include <openssl/crypto.h>
+ ], [
+ #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
- 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_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_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(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)
-
-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"])
-
-AC_CONFIG_HEADERS(crypto/include/config.h:config_in.h)
-
-AC_OUTPUT(Makefile crypto/Makefile doc/Makefile test/Makefile libsrtp2.pc)
+AC_MSG_RESULT([$enable_log_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])])
+
+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])])
+
+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_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])
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
dummy : all runtest
# test applications
-ifneq (1, $(USE_OPENSSL))
+ifneq (1, $(USE_EXTERNAL_CRYPTO))
AES_CALC = test/aes_calc$(EXE)
endif
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."
--- /dev/null
+/*
+ * aes_gcm_nss.c
+ *
+ * AES Galois Counter Mode
+ *
+ * Richard L. Barnes
+ * Cisco Systems, Inc.
+ *
+ */
+
+/*
+ *
+ * Copyright (c) 2013-2017, Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "aes_gcm.h"
+#include "alloc.h"
+#include "err.h" /* for srtp_debug */
+#include "crypto_types.h"
+#include "cipher_types.h"
+#include <secerr.h>
+#include <nspr.h>
+
+srtp_debug_module_t srtp_mod_aes_gcm = {
+ 0, /* debugging is off by default */
+ "aes gcm nss" /* printable module name */
+};
+
+/*
+ * For now we only support 8 and 16 octet tags. The spec allows for
+ * optional 12 byte tag, which may be supported in the future.
+ */
+#define GCM_IV_LEN 12
+#define GCM_AUTH_TAG_LEN 16
+#define GCM_AUTH_TAG_LEN_8 8
+
+/*
+ * This function allocates a new instance of this crypto engine.
+ * The key_len parameter should be one of 28 or 44 for
+ * AES-128-GCM or AES-256-GCM respectively. Note that the
+ * key length includes the 14 byte salt value that is used when
+ * initializing the KDF.
+ */
+static srtp_err_status_t srtp_aes_gcm_nss_alloc(srtp_cipher_t **c,
+ int key_len,
+ int tlen)
+{
+ srtp_aes_gcm_ctx_t *gcm;
+ NSSInitContext *nss;
+
+ debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %d",
+ key_len);
+ debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %d", tlen);
+
+ /*
+ * Verify the key_len is valid for one of: AES-128/256
+ */
+ if (key_len != SRTP_AES_GCM_128_KEY_LEN_WSALT &&
+ key_len != SRTP_AES_GCM_256_KEY_LEN_WSALT) {
+ return (srtp_err_status_bad_param);
+ }
+
+ if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
+ return (srtp_err_status_bad_param);
+ }
+
+ /* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
+ nss = NSS_InitContext("", "", "", "", NULL,
+ NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
+ NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
+ NSS_INIT_OPTIMIZESPACE);
+ if (!nss) {
+ return (srtp_err_status_cipher_fail);
+ }
+
+ /* allocate memory a cipher of type aes_gcm */
+ *c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
+ if (*c == NULL) {
+ NSS_ShutdownContext(nss);
+ return (srtp_err_status_alloc_fail);
+ }
+
+ gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
+ if (gcm == NULL) {
+ NSS_ShutdownContext(nss);
+ srtp_crypto_free(*c);
+ *c = NULL;
+ return (srtp_err_status_alloc_fail);
+ }
+
+ gcm->nss = nss;
+
+ /* set pointers */
+ (*c)->state = gcm;
+
+ /* setup cipher attributes */
+ switch (key_len) {
+ case SRTP_AES_GCM_128_KEY_LEN_WSALT:
+ (*c)->type = &srtp_aes_gcm_128;
+ (*c)->algorithm = SRTP_AES_GCM_128;
+ gcm->key_size = SRTP_AES_128_KEY_LEN;
+ gcm->tag_size = tlen;
+ gcm->params.ulTagBits = 8 * tlen;
+ break;
+ case SRTP_AES_GCM_256_KEY_LEN_WSALT:
+ (*c)->type = &srtp_aes_gcm_256;
+ (*c)->algorithm = SRTP_AES_GCM_256;
+ gcm->key_size = SRTP_AES_256_KEY_LEN;
+ gcm->tag_size = tlen;
+ gcm->params.ulTagBits = 8 * tlen;
+ break;
+ default:
+ /* this should never hit, but to be sure... */
+ return (srtp_err_status_bad_param);
+ }
+
+ /* set key size and tag size*/
+ (*c)->key_len = key_len;
+
+ return (srtp_err_status_ok);
+}
+
+/*
+ * This function deallocates a GCM session
+ */
+static srtp_err_status_t srtp_aes_gcm_nss_dealloc(srtp_cipher_t *c)
+{
+ srtp_aes_gcm_ctx_t *ctx;
+
+ ctx = (srtp_aes_gcm_ctx_t *)c->state;
+ if (ctx) {
+ /* release NSS resources */
+ if (ctx->key) {
+ PK11_FreeSymKey(ctx->key);
+ }
+
+ if (ctx->nss) {
+ NSS_ShutdownContext(ctx->nss);
+ ctx->nss = NULL;
+ }
+
+ /* zeroize the key material */
+ octet_string_set_to_zero(ctx, sizeof(srtp_aes_gcm_ctx_t));
+ srtp_crypto_free(ctx);
+ }
+
+ /* free memory */
+ srtp_crypto_free(c);
+
+ return (srtp_err_status_ok);
+}
+
+/*
+ * aes_gcm_nss_context_init(...) initializes the aes_gcm_context
+ * using the value in key[].
+ *
+ * the key is the secret key
+ */
+static srtp_err_status_t srtp_aes_gcm_nss_context_init(void *cv,
+ const uint8_t *key)
+{
+ srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
+
+ c->dir = srtp_direction_any;
+
+ debug_print(srtp_mod_aes_gcm, "key: %s",
+ srtp_octet_string_hex_string(key, c->key_size));
+
+ if (c->key) {
+ PK11_FreeSymKey(c->key);
+ c->key = NULL;
+ }
+
+ PK11SlotInfo *slot = PK11_GetBestSlot(CKM_AES_GCM, NULL);
+ if (!slot) {
+ return (srtp_err_status_cipher_fail);
+ }
+
+ SECItem key_item = { siBuffer, (unsigned char *)key, c->key_size };
+ c->key = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
+ CKA_ENCRYPT, &key_item, NULL);
+ PK11_FreeSlot(slot);
+
+ if (!c->key) {
+ return (srtp_err_status_cipher_fail);
+ }
+
+ return (srtp_err_status_ok);
+}
+
+/*
+ * aes_gcm_nss_set_iv(c, iv) sets the counter value to the exor of iv with
+ * the offset
+ */
+static srtp_err_status_t srtp_aes_gcm_nss_set_iv(
+ void *cv,
+ uint8_t *iv,
+ srtp_cipher_direction_t direction)
+{
+ srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
+
+ if (direction != srtp_direction_encrypt &&
+ direction != srtp_direction_decrypt) {
+ return (srtp_err_status_bad_param);
+ }
+ c->dir = direction;
+
+ debug_print(srtp_mod_aes_gcm, "setting iv: %s",
+ srtp_octet_string_hex_string(iv, GCM_IV_LEN));
+
+ memcpy(c->iv, iv, GCM_IV_LEN);
+
+ return (srtp_err_status_ok);
+}
+
+/*
+ * This function processes the AAD
+ *
+ * Parameters:
+ * c Crypto context
+ * aad Additional data to process for AEAD cipher suites
+ * aad_len length of aad buffer
+ */
+static srtp_err_status_t srtp_aes_gcm_nss_set_aad(void *cv,
+ const uint8_t *aad,
+ uint32_t aad_len)
+{
+ srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
+
+ debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
+ srtp_octet_string_hex_string(aad, aad_len));
+
+ if (aad_len + c->aad_size > MAX_AD_SIZE) {
+ return srtp_err_status_bad_param;
+ }
+
+ memcpy(c->aad + c->aad_size, aad, aad_len);
+ c->aad_size += aad_len;
+
+ return (srtp_err_status_ok);
+}
+
+static srtp_err_status_t srtp_aes_gcm_nss_do_crypto(void *cv,
+ int encrypt,
+ unsigned char *buf,
+ unsigned int *enc_len)
+{
+ srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
+
+ c->params.pIv = c->iv;
+ c->params.ulIvLen = GCM_IV_LEN;
+ c->params.pAAD = c->aad;
+ c->params.ulAADLen = c->aad_size;
+
+ // Reset AAD
+ c->aad_size = 0;
+
+ int rv;
+ SECItem param = { siBuffer, (unsigned char *)&c->params,
+ sizeof(CK_GCM_PARAMS) };
+ if (encrypt) {
+ rv = PK11_Encrypt(c->key, CKM_AES_GCM, ¶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 */
#endif
#include <openssl/evp.h>
-#include "aes_icm_ossl.h"
-#include "aes_gcm_ossl.h"
+#include "aes_gcm.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "crypto_types.h"
/* 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;
break;
}
+ EVP_CIPHER_CTX_cleanup(c->ctx);
if (!EVP_CipherInit_ex(c->ctx, evp, NULL, key, NULL, 0)) {
return (srtp_err_status_init_fail);
}
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);
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
/*
* 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,
/*
* 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,
--- /dev/null
+/*
+ * aes_icm_nss.c
+ *
+ * AES Integer Counter Mode
+ *
+ * Richard L. Barnes
+ * Cisco Systems, Inc.
+ */
+
+/*
+ *
+ * Copyright (c) 2013-2017, Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "aes_icm_ext.h"
+#include "crypto_types.h"
+#include "err.h" /* for srtp_debug */
+#include "alloc.h"
+#include "cipher_types.h"
+
+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 /* */
+};
#endif
#include <openssl/evp.h>
-#include "aes_icm_ossl.h"
+#include "aes_icm_ext.h"
#include "crypto_types.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h"
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
- * | encrypt |
- * +---------+
- * |
+ * | encrypt |
+ * +---------+
+ * |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
break;
}
+ EVP_CIPHER_CTX_cleanup(c->ctx);
if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) {
return srtp_err_status_fail;
} else {
}
*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;
#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() */
}
/*
- * 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;
*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
/*
* 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);
/*
* 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);
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));
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);
{
/* 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;
}
/* 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++) {
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 */
/*
- * aes_gcm_ossl.h
+ * aes_gcm.h
*
* Header for AES Galois Counter Mode.
*
*
*/
-#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 <openssl/evp.h>
#include <openssl/aes.h>
srtp_cipher_direction_t dir;
} srtp_aes_gcm_ctx_t;
-#endif /* AES_GCM_OSSL_H */
+#endif /* OPENSSL */
+
+#ifdef NSS
+
+#include <nss.h>
+#include <pk11pub.h>
+
+#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 */
#include "cipher.h"
#include "datatypes.h"
+
+#ifdef OPENSSL
+
#include <openssl/evp.h>
#include <openssl/aes.h>
EVP_CIPHER_CTX *ctx;
} srtp_aes_icm_ctx_t;
+#endif /* OPENSSL */
+
+#ifdef NSS
+
+#include <nss.h>
+#include <pk11pub.h>
+
+typedef struct {
+ v128_t counter;
+ v128_t offset;
+ int key_size;
+ uint8_t iv[16];
+ NSSInitContext *nss;
+ PK11SymKey *key;
+ PK11Context *ctx;
+} srtp_aes_icm_ctx_t;
+
+#endif /* NSS */
+
#endif /* AES_ICM_H */
--- /dev/null
+/*
+ *
+ * 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 */
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
/*
#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;
#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
#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) \
#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)
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);
}
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;
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);
}
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);
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;
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);
}
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++)
#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)
#include <config.h>
#endif
-#include <stdio.h> /* for printf() */
-#include <stdlib.h> /* for rand() */
+#include <stdio.h> /* 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
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[])
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
}
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
}
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");
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");
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
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)
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)
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);
void test_bswap(void);
+void test_set_to_zero(void);
+
int main(void)
{
/*
printf(" } \n");
test_bswap();
+ test_set_to_zero();
return 0;
}
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
+}
#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)
{
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 */
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));
}
}
-#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(
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(
*
* @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.
*
* @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.
* 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.
*
* @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
* 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
* @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).
* 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
* 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
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|x64'">$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <PreprocessorDefinitions>GCM;HAVE_INTTYPES_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PreBuildEvent>
<Message>Creating config.h from config.hw</Message>
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;
/* 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;
}
#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 <openssl/kdf.h>
-#include "aes_icm_ossl.h" /* for AES GCM mode */
-#endif
+#include "aes_icm_ext.h"
#endif
#include <limits.h>
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;
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;
break;
}
- srtp_err_status_t stat;
stat = srtp_crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, key_len, 0);
if (stat)
return stat;
* 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,
* 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,
* 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,
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;
}
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
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
/*
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 */
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 */
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
/*
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",
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 */
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 */
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;
}
p->sec_serv = sec_serv_conf;
}
-#ifdef OPENSSL
void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p)
{
/*
p->sec_serv = sec_serv_conf_and_auth;
}
-#endif
-
/*
* secure rtcp functions
*/
{
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;
/* 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 +
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
*/
/*
* 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) {
{
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;
*/
/* 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
*/
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;
* 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) {
/*
* 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) {
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;
* 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 +
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
*/
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];
*/
/* 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;
}
* 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)
/* 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;
/*
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;
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;
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;
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;
#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"
*/
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;
return srtp_err_status_ok;
}
-#include <time.h> /* for clock() */
-#include <stdlib.h> /* for random() */
+#include <time.h> /* for clock() */
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);
#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
/* 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;
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
#include <sys/socket.h>
#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 */
/* 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;
#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];
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;
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;
}
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);
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);
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);
#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
} 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;
}
}
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;
}
}
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;
}
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);
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);
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();
{
fprintf(
stderr,
- "usage: %s [-d <debug>]* [[-k][-b] <key> [-a][-e]]\n"
+ "usage: %s [-d <debug>]* [[-k][-b] <key>] [-a][-t][-e] [-s "
+ "<srtp-crypto-suite>] [-m <mode>]\n"
"or %s -l\n"
"where -a use message authentication\n"
" -e <key size> use encryption (use 128 or 256 for key size)\n"
" -f \"<pcap filter>\" to filter only the desired SRTP packets\n"
" -d <debug> turn on debugging for module <debug>\n"
" -s \"<srtp-crypto-suite>\" to set both key and tag size based\n"
- " on RFC4568-style crypto suite specification\n",
+ " on RFC4568-style crypto suite specification\n"
+ " -m <mode> set the mode to be one of [rtp]|rtcp|rtcp-mux\n"
+ " -p <pcap file> path to pcap file (defaults to stdin)\n"
+ " -o byte offset of RTP packet in capture (defaults to 42)\n",
string, string);
exit(1);
}
free(rtp_ctx);
}
-srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder,
- unsigned int ssrc)
-{
- decoder->policy.ssrc.value = htonl(ssrc);
- return srtp_create(&decoder->srtp_ctx, &decoder->policy);
-}
-
-int rtp_decoder_deinit_srtp(rtp_decoder_t decoder)
+int rtp_decoder_deinit(rtp_decoder_t decoder)
{
- return srtp_dealloc(decoder->srtp_ctx);
+ if (decoder->srtp_ctx) {
+ return srtp_dealloc(decoder->srtp_ctx);
+ }
+ return 0;
}
-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)
{
- 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;
}
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;
}
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;
return;
}
- /* verify rtp header */
- if (dcdr->message.header.version != 2) {
- return;
+ 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;
+ }
}
- if (dcdr->srtp_ctx == NULL) {
- status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc);
+
+ if (rtp) {
+ /* verify rtp header */
+ if (message.header.version != 2) {
+ return;
+ }
+
+ status = srtp_unprotect(dcdr->srtp_ctx, &message, &octets_recvd);
if (status) {
- exit(1);
+ dcdr->error_cnt++;
+ return;
}
- }
- status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd);
- if (status) {
- 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)
#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;
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);
+
+int rtp_decoder_deinit(rtp_decoder_t decoder);
-srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder,
- unsigned int ssrc);
+void rtp_decoder_srtp_log_handler(srtp_log_level_t level,
+ const char *msg,
+ void *data);
-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);
#endif /* RTP_DECODER_H */
exit(1);
}
+ memset(&name, 0, sizeof(struct sockaddr_in));
name.sin_addr = rcvr_addr;
name.sin_family = PF_INET;
name.sin_port = htons(port);
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);
}
#else
printf("error: GCM mode only supported when using the OpenSSL "
- "crypto engine.\n");
+ "or NSS crypto engine.\n");
return 0;
#endif
} else {
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);
*CYGWIN*|*MINGW*)
EXE=".exe"
;;
- *)
+ *Linux*)
EXE=""
+ export LD_LIBRARY_PATH=$CRYPTO_LIBDIR
+ ;;
+ *Darwin*)
+ EXE=""
+ export DYLD_LIBRARY_PATH=$CRYPTO_LIBDIR
;;
esac
*CYGWIN*|*MINGW*)
EXE=".exe"
;;
- *)
+ *Linux*)
EXE=""
+ export LD_LIBRARY_PATH=$CRYPTO_LIBDIR
+ ;;
+ *Darwin*)
+ EXE=""
+ export DYLD_LIBRARY_PATH=$CRYPTO_LIBDIR
;;
esac
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
srtp_err_status_t srtp_test_empty_payload(void);
-#ifdef OPENSSL
+#ifdef GCM
srtp_err_status_t srtp_test_empty_payload_gcm(void);
#endif
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) {
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() ==
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) {
*/
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));
sum += i;
}
t = clock() - t;
+ if (t < 1) {
+ t = 1;
+ }
/* printf("%d\n", sum); */
*ignore = sum;
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;
}
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;
}
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;
}
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;
}
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.
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;
}
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;
}
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;
}
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;
}
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;
/*
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);
return srtp_err_status_ok;
}
-#ifdef OPENSSL
+#ifdef GCM
/*
* Headers of test vectors taken from RFC 6904, Appendix A
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;
/*
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);
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;
}
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;
}
return srtp_err_status_ok;
}
-#ifdef OPENSSL
+#ifdef GCM
srtp_err_status_t srtp_test_empty_payload_gcm()
{
srtp_t srtp_snd, srtp_recv;
return srtp_err_status_ok;
}
-#endif // OPENSSL
+#endif // GCM
srtp_err_status_t srtp_test_remove_stream()
{
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);
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);
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);
if (status)
return status;
-#ifdef OPENSSL
+#ifdef GCM
status = srtp_create(srtp_send_aes_gcm, &policy_aes_gcm);
if (status)
return status;
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;
}
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;
/* 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
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)
/* 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
if (status) {
return status;
}
+
seq++;
ts++;
}
NULL
};
-#ifdef OPENSSL
+#ifdef GCM
const srtp_policy_t aes128_gcm_8_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{
&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,
*/
/*
- * Test specific.
+ * libSRTP specific.
*/
-#include "cutest.h"
+#include "../srtp/srtp.c" // Get access to static functions
/*
- * libSRTP specific.
+ * Test specific.
*/
-#include "../srtp/srtp.c" // Get access to static functions
+#include "cutest.h"
/*
* Standard library.
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;
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],
*
*/
+#include "config.h"
#include "util.h"
#include <string.h>
#include <stdint.h>
-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)
{
/* 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) {