[Build-System] Update libsrtp to 2.3.0

This commit is contained in:
Andrey Volk 2020-01-09 17:17:45 +04:00
parent 1f268e0292
commit b0169c1c89
43 changed files with 2279 additions and 631 deletions

View File

@ -17,7 +17,7 @@ libsrtp_la_SOURCES = srtp/srtp.c srtp/ekt.c crypto/cipher/cipher.c crypto/cip
crypto/kernel/err.c \ crypto/kernel/err.c \
crypto/replay/rdb.c crypto/replay/rdbx.c crypto/replay/ut_sim.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= EXTRA_DIST=
@ -29,10 +29,6 @@ libsrtp_la_SOURCES += crypto/hash/sha1.c crypto/hash/hmac.c
libsrtp_la_SOURCES += crypto/cipher/aes_icm.c crypto/cipher/aes.c libsrtp_la_SOURCES += crypto/cipher/aes_icm.c crypto/cipher/aes.c
endif endif
if GDOI
libsrtp_la_SOURCES += gdoi/srtp+gdoi.c
endif
library_includedir = $(prefix)/include/srtp library_includedir = $(prefix)/include/srtp
library_include_HEADERS = include/srtp.h include/ut_sim.h crypto/include/auth.h \ library_include_HEADERS = include/srtp.h include/ut_sim.h crypto/include/auth.h \
crypto/include/cipher_types.h \ crypto/include/cipher_types.h \

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.59) 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) AC_CONFIG_AUX_DIR(build)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
@ -11,161 +11,155 @@ LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
AC_LANG_C AC_LANG_C
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AC_PROG_AWK AC_PROG_CPP
AC_PROG_MAKE_SET 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_INSTALL
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
AX_COMPILER_VENDOR AC_PROG_SED
# Optimization dnl Check the byte order
AC_ARG_ENABLE(optimization, AC_C_BIGENDIAN
[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_CANONICAL_HOST
AC_DEFINE([OPTIMZER],[],[Enable Optimization.])
AX_CC_MAXOPT
fi
# Enable debugging dnl check host_cpu type, set defines appropriately
AC_ARG_ENABLE(debug, case $host_cpu in
[AC_HELP_STRING([--enable-debug],[build with debug information])],[enable_debug="$enable_debug"],[enable_debug="yes"]) i*86 | x86_64 )
AC_DEFINE([CPU_CISC], [1], [Define if building for a CISC machine (e.g. Intel).])
if test "${enable_debug}" = "yes"; then AC_DEFINE([HAVE_X86], [1], [Define to use X86 inlined assembly code])
AC_DEFINE([DEBUG],[],[Enable extra debugging.]) ;;
AX_CFLAGS_WARN_ALL_ANSI * )
fi AC_DEFINE([CPU_RISC], [1], [Define if building for a RISC machine (assume slow byte access).])
;;
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=""
;;
esac esac
# Enable 64 bit build dnl Check if we are on a Windows platform.
AC_ARG_ENABLE(64, case $host_os in
[AC_HELP_STRING([--enable-64],[build with 64 bit support])],[enable_64="$enable_64"],[enable_64="no"]) *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 dnl Checks for supported compiler flags.
if test "${enable_64}" = "yes"; then supported_cflags=""
new_AM_CFLAGS="$new_AM_CFLAGS -m64" if test "$EMPTY_CFLAGS" = "no"; then
supported_cflags="$CFLAGS"
fi
dnl For accurate detection, we need warnings as errors.
dnl I.e. Clang will issue a warning about unsupported flags.
dnl For the compilation to fail, those warnings needs to be upgraded to errors.
dnl This will be removed again once the tests are complete (see below).
WERROR=""
for w in -Werror -errwarn; do
if test "x$WERROR" = "x"; then
AC_MSG_CHECKING([whether ${CC-c} accepts $w])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$w"], [CFLAGS="$CFLAGS $w"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[WERROR="$w"
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
fi
done
dnl Note that -fPIC is not explicitly added to LDFLAGS.
dnl Since the compiler is used as the link driver, CFLAGS will be part of the
dnl link line as well and the linker will get the flag from there.
dnl Adding it to LDFLAGS explicitly would duplicate the flag on the link line,
dnl but otherwise do no harm.
AC_MSG_CHECKING([whether ${CC-c} accepts -fPIC])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="-fPIC"], [CFLAGS="$CFLAGS -fPIC"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="-fPIC"], [supported_cflags="$supported_cflags -fPIC"])
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
if test "$EMPTY_CFLAGS" = "yes"; then
for f in -Wall -pedantic -Wstrict-prototypes; do
AC_MSG_CHECKING([whether ${CC-c} accepts $f])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$f"], [CFLAGS="$CFLAGS $f"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"])
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
done
OOPT=""
for f in -O4 -O3; do
if test "x$OOPT" = "x"; then
AC_MSG_CHECKING([whether ${CC-c} accepts $f])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$f"], [CFLAGS="$CFLAGS $f"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"])
OOPT="$f"
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
fi 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 fi
AC_SUBST(new_AM_CFLAGS) dnl When turning off warnigns, we're expecting unrecognized command line option errors if they're not
AC_SUBST(new_AM_LDFLAGS) dnl supported. However, the -Wno-<warning> form isn't consulted unless a warning is triggered.
AC_SUBST(SOLINK) dnl At least that's the case for GCC. So to check which warnings we can turn off, we need to check
if test "x$FUNC_DEF" != "x"; then dnl if they can be turned on, thereby forcing GCC to take the argument into account right away.
AC_DEFINE_UNQUOTED([__FUNCTION__],[$FUNC_DEF],[define it the right way ;)]) for f in -Wno-language-extension-token; do
fi AC_MSG_CHECKING([whether ${CC-c} accepts $f])
AC_DEFINE_UNQUOTED([inline],[$IN_LINE],[sunpro is bad at inline]) 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
AC_ARG_ENABLE(kernel-linux, CFLAGS="$supported_cflags"
[AS_HELP_STRING([--enable-kernel-linux],
[build library to run in Linux kernel context])],
[], enable_kernel_linux=no)
AC_MSG_CHECKING(whether to build for Linux kernel context)
if test "$enable_kernel_linux" = "yes"; then
AC_DEFINE(SRTP_KERNEL, 1,
[Define to compile for kernel contexts.])
AC_DEFINE(SRTP_KERNEL_LINUX, 1,
[Define to compile for Linux kernel context.])
fi
AC_MSG_RESULT($enable_kernel_linux)
dnl Check for /dev/urandom
AC_CHECK_FILE(/dev/urandom, DEV_URANDOM=/dev/urandom,
[AC_CHECK_FILE(/dev/random, DEV_URANDOM=/dev/random)])
dnl Checks for header files. dnl Checks for header files.
AC_HEADER_STDC AC_HEADER_STDC
AC_CHECK_HEADERS(stdlib.h) AC_CHECK_HEADERS(
AC_CHECK_HEADERS(unistd.h) [unistd.h byteswap.h stdint.h sys/uio.h inttypes.h sys/types.h machine/types.h sys/int_types.h],
AC_CHECK_HEADERS(stdint.h) [], [], [AC_INCLUDES_DEFAULT])
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
dnl socket() and friends dnl socket() and friends
AC_CHECK_HEADERS(sys/socket.h netinet/in.h arpa/inet.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_CHECK_HEADERS(
[windows.h],
[AC_CHECK_HEADERS([winsock2.h], [], [], [AC_INCLUDES_DEFAULT])],
[], [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS(syslog.h) AC_CHECK_TYPES([int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, uint64_t])
AC_CHECK_SIZEOF([unsigned long])
AC_CHECK_TYPES([int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,uint64_t]) AC_CHECK_SIZEOF([unsigned long long])
AC_CHECK_SIZEOF(unsigned long)
AC_CHECK_SIZEOF(unsigned long long)
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST AC_C_CONST
@ -173,176 +167,267 @@ AC_C_INLINE
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
dnl Checks for library functions. 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. dnl Find socket function if not found yet.
if test "x$ac_cv_func_socket" = "xno"; then 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]) AC_MSG_CHECKING([for socket in -lwsock32])
SAVELIBS="$LIBS" SAVELIBS="$LIBS"
LIBS="$LIBS -lwsock32" LIBS="$LIBS -lwsock32"
AC_TRY_LINK([ AC_LINK_IFELSE(
[AC_LANG_SOURCE([
#include <winsock2.h> #include <winsock2.h>
],[ int main(void)
socket(0, 0, 0); {
], int fd = socket(0, 0, 0);
ac_cv_func_socket=yes if (fd < 0)
AC_MSG_RESULT(yes), return -1;
LIBS="$SAVELIBS" else
AC_MSG_RESULT(no)) return 0;
}
])],
[ac_cv_func_socket=yes
AC_MSG_RESULT([yes])],
[LIBS="$SAVELIBS"
AC_MSG_RESULT([no])])
fi fi
dnl Check the byte order AC_MSG_CHECKING([whether to enable debug logging in all modules])
AC_C_BIGENDIAN AC_ARG_ENABLE([debug-logging],
[AS_HELP_STRING([--enable-debug-logging], [Enable debug logging in all modules])],
[], enable_debug_logging=no)
dnl check host_cpu type, set defines appropriately if test "$enable_debug_logging" = "yes"; then
case $host_cpu in AC_DEFINE([ENABLE_DEBUG_LOGGING], [1], [Define to enabled debug logging for all mudules.])
i*86 | x86_64 )
AC_DEFINE(CPU_CISC, 1,
[Define if building for a CISC machine (e.g. Intel).])
# Do not enable use of asm for MACOSX
if test "x$new_AM_CFLAGS" != "x-DMACOSX"; then
AC_DEFINE(HAVE_X86, 1,
[Define to use X86 inlined assembly code])
fi
;;
* )
# CPU_RISC is only supported for big endian machines.
if test "$ac_cv_c_bigendian" = "yes"; then
AC_DEFINE(CPU_RISC, 1,
[Define if building for a RISC machine (assume slow byte access).])
else
AC_DEFINE(CPU_CISC, 1)
fi
;;
esac
dnl Check if we're on a Windows platform.
case $host_os in
*cygwin*|*mingw* )
EXE=.exe;;
* ) EXE="";;
esac
AC_SUBST(EXE) # define executable suffix; this is needed for `make clean'
AC_MSG_CHECKING(whether to compile in debugging)
AC_ARG_ENABLE(debug,
[AS_HELP_STRING([--disable-debug],
[do not compile in dynamic debugging system])],
[], enable_debug=yes)
if test "$enable_debug" = "yes"; then
AC_DEFINE(ENABLE_DEBUGGING, 1,
[Define to compile in dynamic debugging system.])
fi fi
AC_MSG_RESULT($enable_debug) AC_MSG_RESULT([$enable_debug_logging])
AC_MSG_CHECKING(whether to use ISMAcryp code) PKG_PROG_PKG_CONFIG
AC_ARG_ENABLE(generic-aesicm, AS_IF([test "x$PKG_CONFIG" != "x"], [PKG_CONFIG="$PKG_CONFIG --static"])
[AS_HELP_STRING([--enable-generic-aesicm],
[compile in changes for ISMAcryp])], AC_MSG_CHECKING([whether to leverage OpenSSL crypto])
[], enable_generic_aesicm=no) AC_ARG_ENABLE([openssl],
if test "$enable_generic_aesicm" = "yes"; then [AS_HELP_STRING([--enable-openssl], [compile in OpenSSL crypto engine])],
AC_DEFINE(GENERIC_AESICM, 1, [Define this to use ISMAcryp code.]) [], [enable_openssl=no])
fi AC_MSG_RESULT([$enable_openssl])
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 if test "$enable_openssl" = "yes"; then
echo $enable_openssl AC_MSG_CHECKING([for user specified OpenSSL directory])
LDFLAGS="$LDFLAGS $(pkg-config --libs openssl)"; AC_ARG_WITH([openssl-dir],
CFLAGS="$CFLAGS $(pkg-config --cflags openssl)"; [AS_HELP_STRING([--with-openssl-dir], [Location of OpenSSL installation])],
[if test "x$PKG_CONFIG" != "x" && test -f $with_openssl_dir/lib/pkgconfig/libcrypto.pc; then
if test "x$PKG_CONFIG_PATH" = "x"; then
export PKG_CONFIG_PATH="$with_openssl_dir/lib/pkgconfig"
else
export PKG_CONFIG_PATH="$with_openssl_dir/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
AC_MSG_RESULT([$with_openssl_dir])
elif test -d $with_openssl_dir/lib; then
CFLAGS="$CFLAGS -I$with_openssl_dir/include"
if test "x$LDFLAGS" = "x"; then
LDFLAGS="-L$with_openssl_dir/lib"
else
LDFLAGS="$LDFLAGS -L$with_openssl_dir/lib"
fi
AC_MSG_RESULT([$with_openssl_dir])
else
AC_MSG_RESULT([invalid])
AC_MSG_FAILURE([Invalid OpenSSL location: $with_openssl_dir])
fi],
[AC_MSG_RESULT([no])])
AC_CHECK_LIB([crypto], [EVP_EncryptInit], [], if test "x$PKG_CONFIG" != "x"; then
[AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])]) PKG_CHECK_MODULES([crypto], [libcrypto >= 1.0.1],
AC_CHECK_LIB([crypto], [EVP_aes_128_ctr], [], [CFLAGS="$CFLAGS $crypto_CFLAGS"
[AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])]) LIBS="$crypto_LIBS $LIBS"])
AC_CHECK_LIB([crypto], [EVP_aes_128_gcm], [], else
[AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])]) AC_CHECK_LIB([dl], [dlopen], [], [AC_MSG_WARN([can't find libdl])])
AC_DEFINE(OPENSSL, 1, [Define this to use OpenSSL crypto.]) 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" AES_ICM_OBJS="crypto/cipher/aes_icm_ossl.o crypto/cipher/aes_gcm_ossl.o"
HMAC_OBJS=crypto/hash/hmac_ossl.o HMAC_OBJS=crypto/hash/hmac_ossl.o
USE_OPENSSL=1 AC_SUBST([USE_EXTERNAL_CRYPTO], [1])
AC_SUBST(USE_OPENSSL)
else AC_MSG_CHECKING([if OPENSSL_cleanse is broken])
echo $enable_openssl AC_RUN_IFELSE([AC_LANG_PROGRAM([
AES_ICM_OBJS="crypto/cipher/aes_icm.o crypto/cipher/aes.o crypto/cipher/aes_cbc.o" #include <stdio.h>
AC_MSG_CHECKING(which random device to use) #include <openssl/crypto.h>
if test "$enable_kernel_linux" = "yes"; then ], [
AC_MSG_RESULT([Linux kernel builtin]) #define BUFFER_SIZE (16)
else char buffer[[BUFFER_SIZE]];
if test -n "$DEV_URANDOM"; then int i;
AC_DEFINE_UNQUOTED(DEV_URANDOM, "$DEV_URANDOM",[Path to random device]) for (i = 0; i < BUFFER_SIZE; i++) {
AC_MSG_RESULT([$DEV_URANDOM]) buffer[[i]] = i & 0xff;
else }
AC_MSG_RESULT([standard rand() function...]) OPENSSL_cleanse(buffer, BUFFER_SIZE);
fi 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 fi
elif test "$enable_nss" = "yes"; then
AC_MSG_CHECKING([for user specified NSS directory])
AC_ARG_WITH([nss-dir],
[AS_HELP_STRING([--with-nss-dir], [Location of NSS installation])],
[if test "x$PKG_CONFIG" != "x" && test -f $with_nss_dir/lib/pkgconfig/nss.pc; then
if test "x$PKG_CONFIG_PATH" = "x"; then
export PKG_CONFIG_PATH="$with_nss_dir/lib/pkgconfig"
else
export PKG_CONFIG_PATH="$with_nss_dir/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
AC_MSG_RESULT([$with_nss_dir])
elif test -d $with_nss_dir/lib; then
CFLAGS="$CFLAGS -I$with_nss_dir/include"
CFLAGS="$CFLAGS -I$with_nss_dir/../public/nss"
if test "x$LDFLAGS" = "x"; then
LDFLAGS="-L$with_nss_dir/lib"
else
LDFLAGS="$LDFLAGS -L$with_nss_dir/lib"
fi
nss_skip_pkg_config=yes
AC_MSG_RESULT([$with_nss_dir])
else
AC_MSG_RESULT([invalid])
AC_MSG_FAILURE([Invalid NSS location: $with_nss_dir])
fi
AC_SUBST([CRYPTO_LIBDIR], [$with_nss_dir/lib])],
[AC_MSG_RESULT([no])])
if test "x$PKG_CONFIG" != "x" && test "$nss_skip_pkg_config" != "yes"; then
PKG_CHECK_MODULES([nss], [nss],
[CFLAGS="$CFLAGS $nss_CFLAGS"
LIBS="$nss_LIBS $LIBS"])
else
AC_CHECK_HEADERS(
[nss.h],
[], [AC_MSG_FAILURE([can't find useable NSS headers])],
[AC_INCLUDES_DEFAULT])
AC_CHECK_LIB(
[nspr4], [PR_GetError],
[], [AC_MSG_WARN([can't find libnspr4])])
AC_CHECK_LIB(
[nss3], [NSS_NoDB_Init],
[], [AC_MSG_FAILURE([can't find useable libnss3])])
fi
AC_DEFINE([GCM], [1], [Define this to use AES-GCM.])
AC_DEFINE([NSS], [1], [Define this to use NSS crypto.])
AES_ICM_OBJS="crypto/cipher/aes_icm_nss.o crypto/cipher/aes_gcm_nss.o"
# TODO(RLB): Use NSS for HMAC
HMAC_OBJS="crypto/hash/hmac.o crypto/hash/sha1.o"
# TODO(RLB): Use NSS for KDF
AC_SUBST([USE_EXTERNAL_CRYPTO], [1])
else
AES_ICM_OBJS="crypto/cipher/aes_icm.o crypto/cipher/aes.o"
HMAC_OBJS="crypto/hash/hmac.o crypto/hash/sha1.o" HMAC_OBJS="crypto/hash/hmac.o crypto/hash/sha1.o"
fi fi
AM_CONDITIONAL([ENABLE_OPENSSL],[test "${enable_openssl}" = "yes"]) AM_CONDITIONAL([ENABLE_OPENSSL],[test "${enable_openssl}" = "yes"])
AC_SUBST(AES_ICM_OBJS) AC_SUBST([AES_ICM_OBJS])
AC_SUBST(HMAC_OBJS) AC_SUBST([HMAC_OBJS])
AC_MSG_RESULT($enable_openssl) AC_MSG_RESULT($enable_openssl)
AC_MSG_CHECKING(whether to use syslog for error reporting) dnl Checking for PCAP
AC_ARG_ENABLE(syslog,
[AS_HELP_STRING([--enable-syslog], [use syslog for error reporting])], PCAP_LIB=""
[], enable_syslog=no) AC_ARG_ENABLE([pcap], AS_HELP_STRING([--disable-pcap], [Build without `pcap' library (-lpcap)]))
if test "$enable_syslog" = "yes"; then AS_IF([test "x$enable_pcap" != "xno"], [
AC_DEFINE(USE_SYSLOG, 1, [Define to use syslog logging.]) 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 fi
AC_MSG_RESULT($enable_syslog) AC_MSG_RESULT([$enable_log_stdout])
AC_MSG_CHECKING(whether to use stdout for error reporting) AC_MSG_CHECKING([wheather to use a file for logging])
AC_ARG_ENABLE(stdout, AC_ARG_WITH([log-file],
[AS_HELP_STRING([--disable-stdout], [don't use stdout for error reporting])], [AS_HELP_STRING([--with-log-file], [Use file for logging])],
[], enable_stdout=yes) [AS_CASE([x$with_log_file],
if test "$enable_stdout" = "yes"; then [x], [valid_with_log_file="no"],
AC_DEFINE(ERR_REPORTING_STDOUT, 1, [Define to use logging to stdout.]) [xyes], [valid_with_log_file="no"],
fi [valid_with_error_file="yes"])
AC_MSG_RESULT($enable_stdout) AS_IF([test "$valid_with_log_file" = "no"],
[AC_MSG_RESULT([invalid])
AC_MSG_FAILURE([Invalid value for --with-log-file: "$with_log_file"])],
[AC_DEFINE_UNQUOTED([ERR_REPORTING_FILE], ["$with_log_file"], [Logging statments will be writen to this file.])
AC_MSG_RESULT([using log file: "$with_log_file"])])],
[AC_MSG_RESULT([no])])
AC_MSG_CHECKING(whether to use /dev/console for error reporting) AS_IF(
AC_ARG_ENABLE(console, [test "$enable_log_stdout" = "yes" && test "x$with_log_file" != "x"],
[AS_HELP_STRING([--enable-console], [use /dev/console for error reporting])], [AC_MSG_FAILURE([Can only use one of --enable-log-stdout and --with-log-file; they are mutually exclusive])])
[], 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) dnl Appending EXTRA_CFLAGS, if given
AC_ARG_ENABLE(gdoi, AC_MSG_CHECKING([for extra C compiler flags])
[AS_HELP_STRING([--enable-gdoi], [enable GDOI key management])], AS_IF([test "x$EXTRA_CFLAGS" != "x"],
[], enable_gdoi=no) [AS_IF([test "x$CFLAGS" = "x"],
if test "$enable_gdoi" = "yes"; then [CFLAGS="$EXTRA_CFLAGS"], [CFLAGS="$CFLAGS $EXTRA_CFLAGS"])
AC_DEFINE(SRTP_GDOI, 1, [Define to use GDOI.]) AC_MSG_RESULT([$EXTRA_CFLAGS])],
GDOI_OBJS=gdoi/srtp+gdoi.o [AC_MSG_RESULT(no)])
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_CONFIG_HEADERS([crypto/include/config.h:config_in.h])
AC_OUTPUT(Makefile crypto/Makefile doc/Makefile test/Makefile libsrtp2.pc) AC_CONFIG_FILES([Makefile crypto/Makefile doc/Makefile test/Makefile libsrtp2.pc])
AC_OUTPUT
# This is needed when building outside the source dir. # This is needed when building outside the source dir.
AS_MKDIR_P(crypto/cipher) AS_MKDIR_P([crypto/cipher])
AS_MKDIR_P(crypto/hash) AS_MKDIR_P([crypto/hash])
AS_MKDIR_P(crypto/kernel) AS_MKDIR_P([crypto/kernel])
AS_MKDIR_P(crypto/math) AS_MKDIR_P([crypto/math])
AS_MKDIR_P(crypto/replay) AS_MKDIR_P([crypto/replay])
AS_MKDIR_P(crypto/test) AS_MKDIR_P([crypto/test])
AS_MKDIR_P(doc) AS_MKDIR_P([doc])
AS_MKDIR_P(srtp) AS_MKDIR_P([srtp])
AS_MKDIR_P(tables) AS_MKDIR_P([test])
AS_MKDIR_P(test)

View File

@ -17,15 +17,34 @@ LIBS = @LIBS@
LDFLAGS = @LDFLAGS@ -L. -L.. LDFLAGS = @LDFLAGS@ -L. -L..
COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS) COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS)
CRYPTOLIB = -lsrtp2 CRYPTOLIB = -lsrtp2
CRYPTO_LIBDIR = @CRYPTO_LIBDIR@
RANLIB = @RANLIB@ 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 # 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 # null on linux, bsd, and OS X and other OSes. we define this so that
# `make clean` will work on the cygwin platform # `make clean` will work on the cygwin platform
EXE = @EXE@ EXE = @EXE@
# Random source. # Random source.
USE_OPENSSL = @USE_OPENSSL@ USE_EXTERNAL_CRYPTO = @USE_EXTERNAL_CRYPTO@
ifdef ARCH ifdef ARCH
DEFS += -D$(ARCH)=1 DEFS += -D$(ARCH)=1
@ -40,7 +59,7 @@ endif
dummy : all runtest dummy : all runtest
# test applications # test applications
ifneq (1, $(USE_OPENSSL)) ifneq (1, $(USE_EXTERNAL_CRYPTO))
AES_CALC = test/aes_calc$(EXE) AES_CALC = test/aes_calc$(EXE)
endif endif
@ -62,17 +81,17 @@ c256=8ea2b7ca516745bfeafc49904b496089
runtest: $(testapp) 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..." @echo "running crypto test applications..."
ifneq (1, $(USE_OPENSSL)) ifneq (1, $(USE_EXTERNAL_CRYPTO))
test `test/aes_calc $(k128) $(p128)` = $(c128) $(FIND_LIBRARIES) test `test/aes_calc $(k128) $(p128)` = $(c128)
test `test/aes_calc $(k256) $(p256)` = $(c256) $(FIND_LIBRARIES) test `test/aes_calc $(k256) $(p256)` = $(c256)
endif endif
test/cipher_driver$(EXE) -v >/dev/null $(FIND_LIBRARIES) test/cipher_driver$(EXE) -v >/dev/null
test/datatypes_driver$(EXE) -v >/dev/null $(FIND_LIBRARIES) test/datatypes_driver$(EXE) -v >/dev/null
test/stat_driver$(EXE) >/dev/null $(FIND_LIBRARIES) test/stat_driver$(EXE) >/dev/null
test/sha1_driver$(EXE) -v >/dev/null $(FIND_LIBRARIES) test/sha1_driver$(EXE) -v >/dev/null
test/kernel_driver$(EXE) -v >/dev/null $(FIND_LIBRARIES) test/kernel_driver$(EXE) -v >/dev/null
@echo "crypto test applications passed." @echo "crypto test applications passed."

View File

@ -0,0 +1,609 @@
/*
* aes_gcm_nss.c
*
* AES Galois Counter Mode
*
* Richard L. Barnes
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <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, &param, buf, enc_len,
*enc_len + 16, buf, *enc_len);
} else {
rv = PK11_Decrypt(c->key, CKM_AES_GCM, &param, buf, enc_len, *enc_len,
buf, *enc_len);
}
srtp_err_status_t status = (srtp_err_status_ok);
if (rv != SECSuccess) {
status = (srtp_err_status_cipher_fail);
}
return status;
}
/*
* This function encrypts a buffer using AES GCM mode
*
* XXX(rlb@ipv.sx): We're required to break off and cache the tag
* here, because the get_tag() method is separate and the tests expect
* encrypt() not to change the size of the plaintext. It might be
* good to update the calling API so that this is cleaner.
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
// When we get a non-NULL buffer, we know that the caller is
// prepared to also take the tag. When we get a NULL buffer,
// even though there's no data, we need to give NSS a buffer
// where it can write the tag. We can't just use c->tag because
// memcpy has undefined behavior on overlapping ranges.
unsigned char tagbuf[16];
unsigned char *non_null_buf = buf;
if (!non_null_buf && (*enc_len == 0)) {
non_null_buf = tagbuf;
} else if (!non_null_buf) {
return srtp_err_status_bad_param;
}
srtp_err_status_t status =
srtp_aes_gcm_nss_do_crypto(cv, 1, non_null_buf, enc_len);
if (status != srtp_err_status_ok) {
return status;
}
memcpy(c->tag, non_null_buf + (*enc_len - c->tag_size), c->tag_size);
*enc_len -= c->tag_size;
return srtp_err_status_ok;
}
/*
* This function calculates and returns the GCM tag for a given context.
* This should be called after encrypting the data. The *len value
* is increased by the tag size. The caller must ensure that *buf has
* enough room to accept the appended tag.
*
* Parameters:
* c Crypto context
* buf data to encrypt
* len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_get_tag(void *cv,
uint8_t *buf,
uint32_t *len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
*len = c->tag_size;
memcpy(buf, c->tag, c->tag_size);
return (srtp_err_status_ok);
}
/*
* This function decrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_decrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_err_status_t status = srtp_aes_gcm_nss_do_crypto(cv, 0, buf, enc_len);
if (status != srtp_err_status_ok) {
int err = PR_GetError();
if (err == SEC_ERROR_BAD_DATA) {
status = srtp_err_status_auth_fail;
}
}
return status;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_gcm_128_nss_description[] = "AES-128 GCM using NSS";
static const char srtp_aes_gcm_256_nss_description[] = "AES-256 GCM using NSS";
/*
* 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 */

View File

@ -49,8 +49,7 @@
#endif #endif
#include <openssl/evp.h> #include <openssl/evp.h>
#include "aes_icm_ossl.h" #include "aes_gcm.h"
#include "aes_gcm_ossl.h"
#include "alloc.h" #include "alloc.h"
#include "err.h" /* for srtp_debug */ #include "err.h" /* for srtp_debug */
#include "crypto_types.h" #include "crypto_types.h"
@ -124,13 +123,13 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc(srtp_cipher_t **c,
/* setup cipher attributes */ /* setup cipher attributes */
switch (key_len) { switch (key_len) {
case SRTP_AES_GCM_128_KEY_LEN_WSALT: 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; (*c)->algorithm = SRTP_AES_GCM_128;
gcm->key_size = SRTP_AES_128_KEY_LEN; gcm->key_size = SRTP_AES_128_KEY_LEN;
gcm->tag_len = tlen; gcm->tag_len = tlen;
break; break;
case SRTP_AES_GCM_256_KEY_LEN_WSALT: 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; (*c)->algorithm = SRTP_AES_GCM_256;
gcm->key_size = SRTP_AES_256_KEY_LEN; gcm->key_size = SRTP_AES_256_KEY_LEN;
gcm->tag_len = tlen; gcm->tag_len = tlen;
@ -193,6 +192,7 @@ static srtp_err_status_t srtp_aes_gcm_openssl_context_init(void *cv,
break; break;
} }
EVP_CIPHER_CTX_cleanup(c->ctx);
if (!EVP_CipherInit_ex(c->ctx, evp, NULL, key, NULL, 0)) { if (!EVP_CipherInit_ex(c->ctx, evp, NULL, key, NULL, 0)) {
return (srtp_err_status_init_fail); return (srtp_err_status_init_fail);
} }
@ -218,7 +218,7 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_iv(
c->dir = direction; c->dir = direction;
debug_print(srtp_mod_aes_gcm, "setting iv: %s", 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)) { if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) {
return (srtp_err_status_init_fail); return (srtp_err_status_init_fail);
@ -247,6 +247,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_aad(void *cv,
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int rv; 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 * Set dummy tag, OpenSSL requires the Tag to be set before
* processing AAD * processing AAD
@ -548,7 +551,7 @@ static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1 = {
/* /*
* This is the vector function table for this crypto engine. * 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_alloc,
srtp_aes_gcm_openssl_dealloc, srtp_aes_gcm_openssl_dealloc,
srtp_aes_gcm_openssl_context_init, srtp_aes_gcm_openssl_context_init,
@ -565,7 +568,7 @@ const srtp_cipher_type_t srtp_aes_gcm_128_openssl = {
/* /*
* This is the vector function table for this crypto engine. * 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_alloc,
srtp_aes_gcm_openssl_dealloc, srtp_aes_gcm_openssl_dealloc,
srtp_aes_gcm_openssl_context_init, srtp_aes_gcm_openssl_context_init,

View File

@ -0,0 +1,562 @@
/*
* aes_icm_nss.c
*
* AES Integer Counter Mode
*
* Richard L. Barnes
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <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 *)&param,
sizeof(CK_AES_CTR_PARAMS) };
c->ctx = PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, c->key,
&paramItem);
if (!c->ctx) {
return srtp_err_status_cipher_fail;
}
return srtp_err_status_ok;
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_icm_nss_encrypt(void *cv,
unsigned char *buf,
unsigned int *enc_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
if (!c->ctx) {
return srtp_err_status_bad_param;
}
int rv =
PK11_CipherOp(c->ctx, buf, (int *)enc_len, *enc_len, buf, *enc_len);
srtp_err_status_t status = (srtp_err_status_ok);
if (rv != SECSuccess) {
status = (srtp_err_status_cipher_fail);
}
return status;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_icm_128_nss_description[] =
"AES-128 counter mode using NSS";
static const char srtp_aes_icm_192_nss_description[] =
"AES-192 counter mode using NSS";
static const char srtp_aes_icm_256_nss_description[] =
"AES-256 counter mode using NSS";
/*
* 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 /* */
};

View File

@ -53,7 +53,7 @@
#endif #endif
#include <openssl/evp.h> #include <openssl/evp.h>
#include "aes_icm_ossl.h" #include "aes_icm_ext.h"
#include "crypto_types.h" #include "crypto_types.h"
#include "err.h" /* for srtp_debug */ #include "err.h" /* for srtp_debug */
#include "alloc.h" #include "alloc.h"
@ -78,9 +78,9 @@ srtp_debug_module_t srtp_mod_aes_icm = {
* +------+------+------+------+------+------+------+------+ | * +------+------+------+------+------+------+------+------+ |
* | * |
* +---------+ * +---------+
* | encrypt | * | encrypt |
* +---------+ * +---------+
* | * |
* +------+------+------+------+------+------+------+------+ | * +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+ * | keystream block |<--+
* +------+------+------+------+------+------+------+------+ * +------+------+------+------+------+------+------+------+
@ -248,6 +248,7 @@ static srtp_err_status_t srtp_aes_icm_openssl_context_init(void *cv,
break; break;
} }
EVP_CIPHER_CTX_cleanup(c->ctx);
if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) { if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) {
return srtp_err_status_fail; return srtp_err_status_fail;
} else { } else {
@ -308,7 +309,7 @@ static srtp_err_status_t srtp_aes_icm_openssl_encrypt(void *cv,
} }
*enc_len = len; *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; return srtp_err_status_cipher_fail;
} }
*enc_len += len; *enc_len += len;

View File

@ -49,6 +49,7 @@
#endif #endif
#include "cipher.h" #include "cipher.h"
#include "cipher_priv.h"
#include "crypto_types.h" #include "crypto_types.h"
#include "err.h" /* for srtp_debug */ #include "err.h" /* for srtp_debug */
#include "alloc.h" /* for crypto_alloc(), crypto_free() */ #include "alloc.h" /* for crypto_alloc(), crypto_free() */
@ -165,24 +166,11 @@ int srtp_cipher_get_key_length(const srtp_cipher_t *c)
} }
/* /*
* A trivial platform independent random source. The random * A trivial platform independent random source.
* data is used for some of the cipher self-tests. * 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 */ /* Generic C-library (rand()) version */
/* This is a random source of last resort */ /* This is a random source of last resort */
uint8_t *dst = (uint8_t *)dest; uint8_t *dst = (uint8_t *)dest;
@ -194,8 +182,17 @@ static srtp_err_status_t srtp_cipher_rand(void *dest, uint32_t len)
*dst++ = val & 0xff; *dst++ = val & 0xff;
len--; 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 #define SELF_TEST_BUF_OCTETS 128
@ -246,7 +243,7 @@ srtp_err_status_t srtp_cipher_type_test(
/* /*
* test the encrypt function * test the encrypt function
*/ */
debug_print(srtp_mod_cipher, "testing encryption", NULL); debug_print0(srtp_mod_cipher, "testing encryption");
/* initialize cipher */ /* initialize cipher */
status = srtp_cipher_init(c, test_case->key); status = srtp_cipher_init(c, test_case->key);
@ -350,7 +347,7 @@ srtp_err_status_t srtp_cipher_type_test(
/* /*
* test the decrypt function * test the decrypt function
*/ */
debug_print(srtp_mod_cipher, "testing decryption", NULL); debug_print0(srtp_mod_cipher, "testing decryption");
/* re-initialize cipher for decryption */ /* re-initialize cipher for decryption */
status = srtp_cipher_init(c, test_case->key); status = srtp_cipher_init(c, test_case->key);
@ -465,13 +462,9 @@ srtp_err_status_t srtp_cipher_type_test(
uint8_t iv[MAX_KEY_LEN]; uint8_t iv[MAX_KEY_LEN];
/* choose a length at random (leaving room for IV and padding) */ /* 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); debug_print(srtp_mod_cipher, "random plaintext length %d\n", length);
status = srtp_cipher_rand(buffer, length); srtp_cipher_rand_for_tests(buffer, length);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "plaintext: %s", debug_print(srtp_mod_cipher, "plaintext: %s",
srtp_octet_string_hex_string(buffer, length)); srtp_octet_string_hex_string(buffer, length));
@ -486,18 +479,10 @@ srtp_err_status_t srtp_cipher_type_test(
srtp_cipher_dealloc(c); srtp_cipher_dealloc(c);
return srtp_err_status_cant_check; return srtp_err_status_cant_check;
} }
status = srtp_cipher_rand(key, test_case->key_length_octets); srtp_cipher_rand_for_tests(key, test_case->key_length_octets);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
/* chose a random initialization vector */ /* chose a random initialization vector */
status = srtp_cipher_rand(iv, MAX_KEY_LEN); srtp_cipher_rand_for_tests(iv, MAX_KEY_LEN);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
/* initialize cipher */ /* initialize cipher */
status = srtp_cipher_init(c, key); status = srtp_cipher_init(c, key);

View File

@ -97,7 +97,7 @@ static srtp_err_status_t srtp_null_cipher_init(void *cv, const uint8_t *key)
{ {
/* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ /* 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; return srtp_err_status_ok;
} }

View File

@ -261,14 +261,13 @@ void srtp_sha1_update(srtp_sha1_ctx_t *ctx,
/* process a whole block */ /* process a whole block */
debug_print(srtp_mod_sha1, "(update) running srtp_sha1_core()", debug_print0(srtp_mod_sha1, "(update) running srtp_sha1_core()");
NULL);
srtp_sha1_core(ctx->M, ctx->H); srtp_sha1_core(ctx->M, ctx->H);
} else { } else {
debug_print(srtp_mod_sha1, "(update) not running srtp_sha1_core()", debug_print0(srtp_mod_sha1,
NULL); "(update) not running srtp_sha1_core()");
for (i = ctx->octets_in_buffer; for (i = ctx->octets_in_buffer;
i < (ctx->octets_in_buffer + octets_in_msg); i++) { i < (ctx->octets_in_buffer + octets_in_msg); i++) {
@ -391,11 +390,10 @@ void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t *output)
ctx->H[4] += E; 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) { if (ctx->octets_in_buffer >= 56) {
debug_print(srtp_mod_sha1, "(final) running srtp_sha1_core() again", debug_print0(srtp_mod_sha1, "(final) running srtp_sha1_core() again");
NULL);
/* we need to do one final run of the compression algo */ /* we need to do one final run of the compression algo */

View File

@ -1,5 +1,5 @@
/* /*
* aes_gcm_ossl.h * aes_gcm.h
* *
* Header for AES Galois Counter Mode. * Header for AES Galois Counter Mode.
* *
@ -43,12 +43,15 @@
* *
*/ */
#ifndef AES_GCM_OSSL_H #ifndef AES_GCM_H
#define AES_GCM_OSSL_H #define AES_GCM_H
#include "cipher.h" #include "cipher.h"
#include "srtp.h" #include "srtp.h"
#include "datatypes.h" #include "datatypes.h"
#ifdef OPENSSL
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/aes.h> #include <openssl/aes.h>
@ -59,4 +62,28 @@ typedef struct {
srtp_cipher_direction_t dir; srtp_cipher_direction_t dir;
} srtp_aes_gcm_ctx_t; } 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 */

View File

@ -48,6 +48,9 @@
#include "cipher.h" #include "cipher.h"
#include "datatypes.h" #include "datatypes.h"
#ifdef OPENSSL
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/aes.h> #include <openssl/aes.h>
@ -58,4 +61,23 @@ typedef struct {
EVP_CIPHER_CTX *ctx; EVP_CIPHER_CTX *ctx;
} srtp_aes_icm_ctx_t; } 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 */ #endif /* AES_ICM_H */

View File

@ -0,0 +1,62 @@
/*
*
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef SRTP_CIHPER_PRIV_H
#define SRTP_CIHPER_PRIV_H
#include "cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* A trivial platform independent random source.
* For use in test only.
*/
void srtp_cipher_rand_for_tests(void *dest, uint32_t len);
/*
* A trivial platform independent 32 bit random number.
* For use in test only.
*/
uint32_t srtp_cipher_rand_u32_for_tests(void);
#ifdef __cplusplus
}
#endif
#endif /* SRTP_CIPHER_PRIV_H */

View File

@ -47,10 +47,10 @@
extern const srtp_cipher_type_t srtp_null_cipher; 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_128;
extern const srtp_cipher_type_t srtp_aes_icm_256; 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_icm_192;
extern const srtp_cipher_type_t srtp_aes_gcm_128_openssl; extern const srtp_cipher_type_t srtp_aes_gcm_128;
extern const srtp_cipher_type_t srtp_aes_gcm_256_openssl; extern const srtp_cipher_type_t srtp_aes_gcm_256;
#endif #endif
/* /*
@ -74,6 +74,9 @@ extern srtp_debug_module_t srtp_mod_aes_icm;
#ifdef OPENSSL #ifdef OPENSSL
extern srtp_debug_module_t srtp_mod_aes_gcm; extern srtp_debug_module_t srtp_mod_aes_gcm;
#endif #endif
#ifdef NSS
extern srtp_debug_module_t srtp_mod_aes_gcm;
#endif
/* debug modules for auth types */ /* debug modules for auth types */
extern srtp_debug_module_t srtp_mod_hmac; extern srtp_debug_module_t srtp_mod_hmac;

View File

@ -241,13 +241,13 @@ void v128_set_bit_to(v128_t *x, int i, int y);
#endif /* DATATYPES_USE_MACROS */ #endif /* DATATYPES_USE_MACROS */
/* /*
* octet_string_is_eq(a, b, len) returns 1 if the length len strings a * srtp_octet_string_is_eq(a, b, len) returns 1 if the length len strings
* and b are not equal. It returns 0 otherwise. The running time of the * 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.) * comparison depends only on len, making this safe to use for (e.g.)
* verifying authentication tags. * 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 * A portable way to zero out memory as recommended by

View File

@ -109,6 +109,8 @@ typedef struct {
#ifdef ENABLE_DEBUG_LOGGING #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) \ #define debug_print(mod, format, arg) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg) srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg)
#define debug_print2(mod, format, arg1, arg2) \ #define debug_print2(mod, format, arg1, arg2) \
@ -117,6 +119,9 @@ typedef struct {
#else #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) \ #define debug_print(mod, format, arg) \
if (mod.on) \ if (mod.on) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg) srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg)

View File

@ -80,7 +80,7 @@ void *srtp_crypto_alloc(size_t size)
if (ptr) { if (ptr) {
debug_print(srtp_mod_alloc, "(location: %p) allocated", ptr); debug_print(srtp_mod_alloc, "(location: %p) allocated", ptr);
} else { } 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); size);
} }

View File

@ -130,18 +130,18 @@ srtp_err_status_t srtp_crypto_kernel_init()
if (status) { if (status) {
return status; return status;
} }
#ifdef OPENSSL #ifdef GCM
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_192, status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_192,
SRTP_AES_ICM_192); SRTP_AES_ICM_192);
if (status) { if (status) {
return 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); SRTP_AES_GCM_128);
if (status) { if (status) {
return 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); SRTP_AES_GCM_256);
if (status) { if (status) {
return status; return status;

View File

@ -80,6 +80,7 @@ srtp_err_status_t srtp_install_err_report_handler(
void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...) void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...)
{ {
char msg[512];
va_list args; va_list args;
if (srtp_err_file != NULL) { if (srtp_err_file != NULL) {
va_start(args, format); va_start(args, format);
@ -88,7 +89,6 @@ void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...)
} }
if (srtp_err_report_handler != NULL) { if (srtp_err_report_handler != NULL) {
va_start(args, format); va_start(args, format);
char msg[512];
if (vsnprintf(msg, sizeof(msg), format, args) > 0) { if (vsnprintf(msg, sizeof(msg), format, args) > 0) {
/* strip trailing \n, callback should not have one */ /* strip trailing \n, callback should not have one */
size_t l = strlen(msg); size_t l = strlen(msg);

View File

@ -410,7 +410,7 @@ void bitvector_left_shift(bitvector_t *x, int shift)
x->word[i] = 0; 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 *end = b + len;
uint8_t accumulator = 0; uint8_t accumulator = 0;
@ -436,7 +436,7 @@ void srtp_cleanse(void *s, size_t len)
void octet_string_set_to_zero(void *s, size_t len) void octet_string_set_to_zero(void *s, size_t len)
{ {
#ifdef OPENSSL #if defined(OPENSSL) && !defined(OPENSSL_CLEANSE_BROKEN)
OPENSSL_cleanse(s, len); OPENSSL_cleanse(s, len);
#else #else
srtp_cleanse(s, len); srtp_cleanse(s, len);

View File

@ -196,7 +196,7 @@ srtp_err_status_t stat_test_runs(uint8_t *data)
} }
if (srtp_mod_stat.on) { 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++) for (i = 0; i < 6; i++)
debug_print(srtp_mod_stat, " runs[]: %d", runs[i]); debug_print(srtp_mod_stat, " runs[]: %d", runs[i]);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)

View File

@ -49,10 +49,13 @@
#endif #endif
#include "ut_sim.h" #include "ut_sim.h"
#include "cipher_priv.h"
int ut_compar(const void *a, const void *b) 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) void ut_init(ut_connection *utc)

View File

@ -47,13 +47,13 @@
#include <config.h> #include <config.h>
#endif #endif
#include <stdio.h> /* for printf() */ #include <stdio.h> /* for printf() */
#include <stdlib.h> /* for rand() */
#include "getopt_s.h" #include "getopt_s.h"
#include "cipher.h" #include "cipher.h"
#ifdef OPENSSL #include "cipher_priv.h"
#include "aes_icm_ossl.h" #ifdef GCM
#include "aes_gcm_ossl.h" #include "aes_icm_ext.h"
#include "aes_gcm.h"
#else #else
#include "aes_icm.h" #include "aes_icm.h"
#endif #endif
@ -118,10 +118,10 @@ void check_status(srtp_err_status_t s)
extern srtp_cipher_type_t srtp_null_cipher; extern srtp_cipher_type_t srtp_null_cipher;
extern srtp_cipher_type_t srtp_aes_icm_128; extern srtp_cipher_type_t srtp_aes_icm_128;
extern srtp_cipher_type_t srtp_aes_icm_256; 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_icm_192;
extern srtp_cipher_type_t srtp_aes_gcm_128_openssl; extern srtp_cipher_type_t srtp_aes_gcm_128;
extern srtp_cipher_type_t srtp_aes_gcm_256_openssl; extern srtp_cipher_type_t srtp_aes_gcm_256;
#endif #endif
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -187,21 +187,19 @@ int main(int argc, char *argv[])
cipher_driver_test_array_throughput( cipher_driver_test_array_throughput(
&srtp_aes_icm_256, SRTP_AES_ICM_256_KEY_LEN_WSALT, num_cipher); &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) for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8)
cipher_driver_test_array_throughput( cipher_driver_test_array_throughput(
&srtp_aes_icm_192, SRTP_AES_ICM_192_KEY_LEN_WSALT, num_cipher); &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) { for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) {
cipher_driver_test_array_throughput(&srtp_aes_gcm_128_openssl, cipher_driver_test_array_throughput(
SRTP_AES_GCM_128_KEY_LEN_WSALT, &srtp_aes_gcm_128, SRTP_AES_GCM_128_KEY_LEN_WSALT, num_cipher);
num_cipher);
} }
for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) {
cipher_driver_test_array_throughput(&srtp_aes_gcm_256_openssl, cipher_driver_test_array_throughput(
SRTP_AES_GCM_256_KEY_LEN_WSALT, &srtp_aes_gcm_256, SRTP_AES_GCM_256_KEY_LEN_WSALT, num_cipher);
num_cipher);
} }
#endif #endif
} }
@ -210,10 +208,10 @@ int main(int argc, char *argv[])
cipher_driver_self_test(&srtp_null_cipher); cipher_driver_self_test(&srtp_null_cipher);
cipher_driver_self_test(&srtp_aes_icm_128); cipher_driver_self_test(&srtp_aes_icm_128);
cipher_driver_self_test(&srtp_aes_icm_256); 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_icm_192);
cipher_driver_self_test(&srtp_aes_gcm_128_openssl); cipher_driver_self_test(&srtp_aes_gcm_128);
cipher_driver_self_test(&srtp_aes_gcm_256_openssl); cipher_driver_self_test(&srtp_aes_gcm_256);
#endif #endif
} }
@ -277,9 +275,9 @@ int main(int argc, char *argv[])
status = srtp_cipher_dealloc(c); status = srtp_cipher_dealloc(c);
check_status(status); check_status(status);
#ifdef OPENSSL #ifdef GCM
/* run the throughput test on the aes_gcm_128_openssl cipher */ /* run the throughput test on the aes_gcm_128 cipher */
status = srtp_cipher_type_alloc(&srtp_aes_gcm_128_openssl, &c, status = srtp_cipher_type_alloc(&srtp_aes_gcm_128, &c,
SRTP_AES_GCM_128_KEY_LEN_WSALT, 8); SRTP_AES_GCM_128_KEY_LEN_WSALT, 8);
if (status) { if (status) {
fprintf(stderr, "error: can't allocate GCM 128 cipher\n"); fprintf(stderr, "error: can't allocate GCM 128 cipher\n");
@ -291,15 +289,13 @@ int main(int argc, char *argv[])
cipher_driver_test_throughput(c); cipher_driver_test_throughput(c);
} }
if (do_validation) { // GCM ciphers don't do buffering; they're "one shot"
status = cipher_driver_test_buffering(c);
check_status(status);
}
status = srtp_cipher_dealloc(c); status = srtp_cipher_dealloc(c);
check_status(status); check_status(status);
/* run the throughput test on the aes_gcm_256_openssl cipher */ /* run the throughput test on the aes_gcm_256 cipher */
status = srtp_cipher_type_alloc(&srtp_aes_gcm_256_openssl, &c, status = srtp_cipher_type_alloc(&srtp_aes_gcm_256, &c,
SRTP_AES_GCM_256_KEY_LEN_WSALT, 16); SRTP_AES_GCM_256_KEY_LEN_WSALT, 16);
if (status) { if (status) {
fprintf(stderr, "error: can't allocate GCM 256 cipher\n"); fprintf(stderr, "error: can't allocate GCM 256 cipher\n");
@ -311,10 +307,8 @@ int main(int argc, char *argv[])
cipher_driver_test_throughput(c); cipher_driver_test_throughput(c);
} }
if (do_validation) { // GCM ciphers don't do buffering; they're "one shot"
status = cipher_driver_test_buffering(c);
check_status(status);
}
status = srtp_cipher_dealloc(c); status = srtp_cipher_dealloc(c);
check_status(status); check_status(status);
#endif #endif
@ -396,7 +390,7 @@ srtp_err_status_t cipher_driver_test_buffering(srtp_cipher_t *c)
end = buffer1 + buflen; end = buffer1 + buflen;
while (current < end) { while (current < end) {
/* choose a short length */ /* 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 */ /* make sure that len doesn't cause us to overreach the buffer */
if (current + len > end) if (current + len > end)
@ -479,9 +473,8 @@ srtp_err_status_t cipher_array_alloc_init(srtp_cipher_t ***ca,
return status; return status;
/* generate random key and initialize cipher */ /* generate random key and initialize cipher */
for (j = 0; j < klen; j++) srtp_cipher_rand_for_tests(key, klen);
key[j] = (uint8_t)rand(); for (j = klen; j < klen_pad; j++)
for (; j < klen_pad; j++)
key[j] = 0; key[j] = 0;
status = srtp_cipher_init(*cipher_array, key); status = srtp_cipher_init(*cipher_array, key);
if (status) if (status)
@ -535,7 +528,7 @@ uint64_t cipher_array_bits_per_second(srtp_cipher_t *cipher_array[],
v128_t nonce; v128_t nonce;
clock_t timer; clock_t timer;
unsigned char *enc_buf; 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 */ /* Over-alloc, for NIST CBC padding */
enc_buf = srtp_crypto_alloc(octets_in_buffer + 17); enc_buf = srtp_crypto_alloc(octets_in_buffer + 17);

View File

@ -60,6 +60,8 @@ void print_string(char *s);
void test_bswap(void); void test_bswap(void);
void test_set_to_zero(void);
int main(void) int main(void)
{ {
/* /*
@ -135,6 +137,7 @@ int main(void)
printf(" } \n"); printf(" } \n");
test_bswap(); test_bswap();
test_set_to_zero();
return 0; return 0;
} }
@ -228,3 +231,26 @@ void test_bswap(void)
printf("bswapped octet string: %s\n", printf("bswapped octet string: %s\n",
octet_string_hex_string((uint8_t *)&y, 8)); 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
}

View File

@ -54,12 +54,7 @@
#include "srtp.h" #include "srtp.h"
#include "cipher.h" #include "cipher.h"
#include "cipher_priv.h"
typedef struct {
void *state;
} random_source_t;
srtp_err_status_t random_source_alloc(void);
void err_check(srtp_err_status_t s) void err_check(srtp_err_status_t s)
{ {
@ -76,9 +71,9 @@ int main(int argc, char *argv[])
int i, j; int i, j;
extern srtp_cipher_type_t srtp_aes_icm_128; extern srtp_cipher_type_t srtp_aes_icm_128;
extern srtp_cipher_type_t srtp_aes_icm_256; extern srtp_cipher_type_t srtp_aes_icm_256;
#ifdef OPENSSL #ifdef GCM
extern srtp_cipher_type_t srtp_aes_gcm_128_openssl; extern srtp_cipher_type_t srtp_aes_gcm_128;
extern srtp_cipher_type_t srtp_aes_gcm_256_openssl; extern srtp_cipher_type_t srtp_aes_gcm_256;
#endif #endif
srtp_cipher_t *c; srtp_cipher_t *c;
/* clang-format off */ /* clang-format off */
@ -107,8 +102,7 @@ int main(int argc, char *argv[])
printf("poker %d\n", stat_test_poker(buffer)); printf("poker %d\n", stat_test_poker(buffer));
printf("runs %d\n", stat_test_runs(buffer)); printf("runs %d\n", stat_test_runs(buffer));
for (i = 0; i < 2500; i++) srtp_cipher_rand_for_tests(buffer, 2500);
buffer[i] = rand();
printf("running stat_tests on rand(), expecting success\n"); printf("running stat_tests on rand(), expecting success\n");
printf("monobit %d\n", stat_test_monobit(buffer)); printf("monobit %d\n", stat_test_monobit(buffer));
printf("poker %d\n", stat_test_poker(buffer)); printf("poker %d\n", stat_test_poker(buffer));
@ -180,14 +174,14 @@ int main(int argc, char *argv[])
} }
} }
#ifdef OPENSSL #ifdef GCM
{ {
printf("running stat_tests on AES-128-GCM, expecting success\n"); printf("running stat_tests on AES-128-GCM, expecting success\n");
/* set buffer to cipher output */ /* set buffer to cipher output */
for (i = 0; i < 2500; i++) { for (i = 0; i < 2500; i++) {
buffer[i] = 0; 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)); SRTP_AES_GCM_128_KEY_LEN_WSALT, 8));
err_check(srtp_cipher_init(c, key)); err_check(srtp_cipher_init(c, key));
err_check( err_check(
@ -219,7 +213,7 @@ int main(int argc, char *argv[])
for (i = 0; i < 2500; i++) { for (i = 0; i < 2500; i++) {
buffer[i] = 0; 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)); SRTP_AES_GCM_256_KEY_LEN_WSALT, 16));
err_check(srtp_cipher_init(c, key)); err_check(srtp_cipher_init(c, key));
err_check( err_check(

View File

@ -682,14 +682,14 @@ srtp_err_status_t srtp_update_stream(srtp_t session,
* *
* @param p is a pointer to the policy structure to be set * @param p is a pointer to the policy structure to be set
* *
* The function call crypto_policy_set_rtp_default(&p) sets the * The function call srtp_crypto_policy_set_rtp_default(&p) sets the
* crypto_policy_t at location p to the SRTP default policy for RTP * srtp_crypto_policy_t at location p to the SRTP default policy for RTP
* protection, as defined in the specification. This function is a * protection, as defined in the specification. This function is a
* convenience that helps to avoid dealing directly with the policy * convenience that helps to avoid dealing directly with the policy
* data structure. You are encouraged to initialize policy elements * data structure. You are encouraged to initialize policy elements
* with this function call. Doing so may allow your code to be * with this function call. Doing so may allow your code to be
* forward compatible with later versions of libSRTP that include more * 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. * @return void.
* *
@ -934,7 +934,7 @@ void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p);
* @param p is a pointer to the policy structure to be set * @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) * 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 * 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 * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit
* authentication tag. * authentication tag.
@ -943,7 +943,7 @@ void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p);
* with the policy data structure. You are encouraged to initialize * with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your * policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that * 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. * @return void.
* *
@ -958,7 +958,7 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p);
* @param p is a pointer to the policy structure to be set * @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) * 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 * 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 * Counter Mode encryption and HMAC-SHA1 authentication, with an
* authentication tag that is only 32 bits long. This length is * authentication tag that is only 32 bits long. This length is
@ -970,7 +970,7 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p);
* with the policy data structure. You are encouraged to initialize * with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your * policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that * 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 * @warning This crypto policy is intended for use in SRTP, but not in
* SRTCP. It is recommended that a policy that uses longer * SRTCP. It is recommended that a policy that uses longer
@ -989,7 +989,7 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p);
* @param p is a pointer to the policy structure to be set * @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 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 * (AES-192 Counter Mode), but to use no authentication method. This
* policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5
* of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt).
@ -998,7 +998,7 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p);
* with the policy data structure. You are encouraged to initialize * with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your * policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that * 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 * @warning This policy is NOT RECOMMENDED for SRTP unless it is
* unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see

View File

@ -219,7 +219,7 @@ typedef struct {
* srtcp_hdr_t represents a secure rtcp header * srtcp_hdr_t represents a secure rtcp header
* *
* in this implementation, an srtcp header is assumed to be 32-bit * in this implementation, an srtcp header is assumed to be 32-bit
* alinged * aligned
*/ */
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN

View File

@ -129,6 +129,11 @@
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|x64'">$(Platform)\$(Configuration)\</IntDir> <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|x64'">$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>GCM;HAVE_INTTYPES_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PreBuildEvent> <PreBuildEvent>
<Message>Creating config.h from config.hw</Message> <Message>Creating config.h from config.hw</Message>

View File

@ -151,7 +151,7 @@ srtp_err_status_t srtp_ekt_stream_init_from_policy(
void aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len) 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 // FIXME: need to get this working through the crypto module interface
srtp_aes_expanded_key_t expanded_key; srtp_aes_expanded_key_t expanded_key;
@ -218,7 +218,7 @@ void srtp_ekt_write_data(srtp_ekt_stream_t ekt,
/* if the pointer ekt is NULL, then EKT is not in effect */ /* if the pointer ekt is NULL, then EKT is not in effect */
if (!ekt) { if (!ekt) {
debug_print(mod_srtp, "EKT not in use", NULL); debug_print0(mod_srtp, "EKT not in use");
return; return;
} }

View File

@ -51,12 +51,13 @@
#include "ekt.h" /* for SRTP Encrypted Key Transport */ #include "ekt.h" /* for SRTP Encrypted Key Transport */
#include "alloc.h" /* for srtp_crypto_alloc() */ #include "alloc.h" /* for srtp_crypto_alloc() */
#ifdef OPENSSL #ifdef GCM
#include "aes_gcm_ossl.h" /* for AES GCM mode */ #include "aes_gcm.h" /* for AES GCM mode */
#endif
#ifdef OPENSSL_KDF #ifdef OPENSSL_KDF
#include <openssl/kdf.h> #include <openssl/kdf.h>
#include "aes_icm_ossl.h" /* for AES GCM mode */ #include "aes_icm_ext.h"
#endif
#endif #endif
#include <limits.h> #include <limits.h>
@ -81,13 +82,14 @@ srtp_debug_module_t mod_srtp = {
static srtp_err_status_t srtp_validate_rtp_header(void *rtp_hdr, static srtp_err_status_t srtp_validate_rtp_header(void *rtp_hdr,
int *pkt_octet_len) 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) if (*pkt_octet_len < octets_in_rtp_header)
return srtp_err_status_bad_param; return srtp_err_status_bad_param;
srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
/* Check RTP header length */ /* 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) if (hdr->x == 1)
rtp_header_len += octets_in_rtp_extn_hdr; rtp_header_len += octets_in_rtp_extn_hdr;
@ -677,6 +679,8 @@ static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf,
int key_len) int key_len)
{ {
srtp_cipher_type_id_t cipher_id; srtp_cipher_type_id_t cipher_id;
srtp_err_status_t stat;
switch (key_len) { switch (key_len) {
case SRTP_AES_ICM_256_KEY_LEN_WSALT: case SRTP_AES_ICM_256_KEY_LEN_WSALT:
cipher_id = SRTP_AES_ICM_256; cipher_id = SRTP_AES_ICM_256;
@ -692,7 +696,6 @@ static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf,
break; break;
} }
srtp_err_status_t stat;
stat = srtp_crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, key_len, 0); stat = srtp_crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, key_len, 0);
if (stat) if (stat)
return stat; return stat;
@ -959,7 +962,7 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp,
* to generate the salt value * to generate the salt value
*/ */
if (rtp_salt_len > 0) { 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 */ /* generate encryption salt, put after encryption key */
stat = srtp_kdf_generate(&kdf, label_rtp_salt, stat = srtp_kdf_generate(&kdf, label_rtp_salt,
@ -1067,9 +1070,8 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp,
* to generate the salt value * to generate the salt value
*/ */
if (rtp_xtn_hdr_salt_len > 0) { if (rtp_xtn_hdr_salt_len > 0) {
debug_print(mod_srtp, debug_print0(mod_srtp,
"found rtp_xtn_hdr_salt_len > 0, generating salt", "found rtp_xtn_hdr_salt_len > 0, generating salt");
NULL);
/* generate encryption salt, put after encryption key */ /* generate encryption salt, put after encryption key */
stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_salt, stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_salt,
@ -1150,8 +1152,7 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp,
* to generate the salt value * to generate the salt value
*/ */
if (rtcp_salt_len > 0) { if (rtcp_salt_len > 0) {
debug_print(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt", debug_print0(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt");
NULL);
/* generate encryption salt, put after encryption key */ /* generate encryption salt, put after encryption key */
stat = srtp_kdf_generate(&kdf, label_rtcp_salt, stat = srtp_kdf_generate(&kdf, label_rtcp_salt,
@ -1667,7 +1668,7 @@ static srtp_err_status_t srtp_get_est_pkt_index(srtp_hdr_t *hdr,
debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(*est), debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(*est),
low32(*est)); low32(*est));
#else #else
debug_print(mod_srtp, "estimated u_packet index: %016llx", *est); debug_print(mod_srtp, "estimated u_packet index: %016" PRIx64, *est);
#endif #endif
return result; return result;
} }
@ -1697,7 +1698,7 @@ static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx,
unsigned int mki_size = 0; unsigned int mki_size = 0;
uint8_t *mki_location = NULL; 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 * update the key usage limit, and check it to make sure that we
@ -1756,7 +1757,7 @@ static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx,
debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est), debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est),
low32(est)); low32(est));
#else #else
debug_print(mod_srtp, "estimated packet index: %016llx", est); debug_print(mod_srtp, "estimated packet index: %016" PRIx64, est);
#endif #endif
/* /*
@ -1858,13 +1859,13 @@ static srtp_err_status_t srtp_unprotect_aead(srtp_ctx_t *ctx,
unsigned int aad_len; unsigned int aad_len;
srtp_hdr_xtnd_t *xtn_hdr = NULL; 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 #ifdef NO_64BIT_MATH
debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est), debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),
low32(est)); low32(est));
#else #else
debug_print(mod_srtp, "estimated u_packet index: %016llx", est); debug_print(mod_srtp, "estimated u_packet index: %016" PRIx64, est);
#endif #endif
/* get tag length from stream */ /* get tag length from stream */
@ -2059,7 +2060,7 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
uint8_t *mki_location = NULL; uint8_t *mki_location = NULL;
int advance_packet_index = 0; 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 */ /* we assume the hdr is 32-bit aligned to start */
@ -2230,7 +2231,7 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est), debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est),
low32(est)); low32(est));
#else #else
debug_print(mod_srtp, "estimated packet index: %016llx", est); debug_print(mod_srtp, "estimated packet index: %016" PRIx64, est);
#endif #endif
/* /*
@ -2336,7 +2337,7 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
return status; return status;
/* run auth func over ROC, put result into auth_tag */ /* 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, status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4,
auth_tag); auth_tag);
debug_print(mod_srtp, "srtp auth tag: %s", debug_print(mod_srtp, "srtp auth tag: %s",
@ -2389,7 +2390,7 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx,
uint32_t roc_to_set = 0; uint32_t roc_to_set = 0;
uint16_t seq_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 */ /* we assume the hdr is 32-bit aligned to start */
@ -2458,7 +2459,7 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx,
debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est), debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),
low32(est)); low32(est));
#else #else
debug_print(mod_srtp, "estimated u_packet index: %016llx", est); debug_print(mod_srtp, "estimated u_packet index: %016" PRIx64, est);
#endif #endif
/* Determine if MKI is being used and what session keys should be used */ /* Determine if MKI is being used and what session keys should be used */
@ -2614,7 +2615,7 @@ srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx,
if (status) if (status)
return srtp_err_status_auth_fail; 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; return srtp_err_status_auth_fail;
} }
@ -3285,7 +3286,6 @@ void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p)
p->sec_serv = sec_serv_conf; p->sec_serv = sec_serv_conf;
} }
#ifdef OPENSSL
void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p) void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p)
{ {
/* /*
@ -3407,8 +3407,6 @@ void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p)
p->sec_serv = sec_serv_conf_and_auth; p->sec_serv = sec_serv_conf_and_auth;
} }
#endif
/* /*
* secure rtcp functions * secure rtcp functions
*/ */
@ -3496,7 +3494,8 @@ static srtp_err_status_t srtp_protect_rtcp_aead(
{ {
srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
uint32_t *enc_start; /* pointer to start of encrypted portion */ 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 */ 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 *auth_tag = NULL; /* location of auth_tag within packet */
srtp_err_status_t status; srtp_err_status_t status;
@ -3519,18 +3518,15 @@ static srtp_err_status_t srtp_protect_rtcp_aead(
/* NOTE: hdr->length is not usable - it refers to only the first /* NOTE: hdr->length is not usable - it refers to only the first
* RTCP report in the compound packet! * RTCP report in the compound packet!
*/ */
/* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always trailer_p = (uint32_t *)((char *)enc_start + enc_octet_len + tag_len);
* multiples of 32-bits (RFC 3550 6.1)
*/
trailer = (uint32_t *)((char *)enc_start + enc_octet_len + tag_len);
if (stream->rtcp_services & sec_serv_conf) { if (stream->rtcp_services & sec_serv_conf) {
*trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
} else { } else {
enc_start = NULL; enc_start = NULL;
enc_octet_len = 0; enc_octet_len = 0;
/* 0 is network-order independant */ /* 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 + mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + tag_len +
@ -3554,9 +3550,11 @@ static srtp_err_status_t srtp_protect_rtcp_aead(
return status; return status;
} }
seq_num = srtp_rdb_get_value(&stream->rtcp_rdb); 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); debug_print(mod_srtp, "srtcp index: %x", seq_num);
memcpy(trailer_p, &trailer, sizeof(trailer));
/* /*
* Calculate and set the IV * Calculate and set the IV
*/ */
@ -3598,7 +3596,7 @@ static srtp_err_status_t srtp_protect_rtcp_aead(
/* /*
* Process the sequence# as AAD * Process the sequence# as AAD
*/ */
tseq = *trailer; tseq = trailer;
status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq, status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq,
sizeof(srtcp_trailer_t)); sizeof(srtcp_trailer_t));
if (status) { if (status) {
@ -3667,7 +3665,8 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead(
{ {
srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
uint32_t *enc_start; /* pointer to start of encrypted portion */ 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 */ 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 *auth_tag = NULL; /* location of auth_tag within packet */
srtp_err_status_t status; srtp_err_status_t status;
@ -3693,12 +3692,10 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead(
*/ */
/* This should point trailer to the word past the end of the normal data. */ /* This should point trailer to the word past the end of the normal data. */
/* This would need to be modified for optional mikey data */ /* This would need to be modified for optional mikey data */
/* trailer_p = (uint32_t *)((char *)hdr + *pkt_octet_len -
* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always sizeof(srtcp_trailer_t) - mki_size);
* multiples of 32-bits (RFC 3550 6.1) memcpy(&trailer, trailer_p, sizeof(trailer));
*/
trailer = (uint32_t *)((char *)hdr + *pkt_octet_len -
sizeof(srtcp_trailer_t) - mki_size);
/* /*
* We pass the tag down to the cipher when doing GCM mode * We pass the tag down to the cipher when doing GCM mode
*/ */
@ -3707,7 +3704,7 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead(
auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len - mki_size - auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len - mki_size -
sizeof(srtcp_trailer_t); 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; enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;
} else { } else {
enc_octet_len = 0; enc_octet_len = 0;
@ -3718,7 +3715,7 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead(
* check the sequence number for replays * check the sequence number for replays
*/ */
/* this is easier than dealing with bitfield access */ /* 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); debug_print(mod_srtp, "srtcp index: %x", seq_num);
status = srtp_rdb_check(&stream->rtcp_rdb, seq_num); status = srtp_rdb_check(&stream->rtcp_rdb, seq_num);
if (status) { if (status) {
@ -3768,7 +3765,7 @@ static srtp_err_status_t srtp_unprotect_rtcp_aead(
/* /*
* Process the sequence# as AAD * Process the sequence# as AAD
*/ */
tseq = *trailer; tseq = trailer;
status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq, status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq,
sizeof(srtcp_trailer_t)); sizeof(srtcp_trailer_t));
if (status) { if (status) {
@ -3866,7 +3863,8 @@ srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx,
srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *enc_start; /* pointer to start of encrypted portion */
uint32_t *auth_start; /* pointer to start of auth. 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 */ 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 *auth_tag = NULL; /* location of auth_tag within packet */
srtp_err_status_t status; srtp_err_status_t status;
@ -3959,19 +3957,15 @@ srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx,
* NOTE: hdr->length is not usable - it refers to only the first RTCP report * NOTE: hdr->length is not usable - it refers to only the first RTCP report
* in the compound packet! * in the compound packet!
*/ */
/* trailer_p = (uint32_t *)((char *)enc_start + enc_octet_len);
* 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);
if (stream->rtcp_services & sec_serv_conf) { if (stream->rtcp_services & sec_serv_conf) {
*trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
} else { } else {
enc_start = NULL; enc_start = NULL;
enc_octet_len = 0; enc_octet_len = 0;
/* 0 is network-order independant */ /* 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 + mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len +
@ -3999,9 +3993,11 @@ srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx,
if (status) if (status)
return status; return status;
seq_num = srtp_rdb_get_value(&stream->rtcp_rdb); 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); 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 * if we're using rindael counter mode, set nonce and seq
*/ */
@ -4097,7 +4093,8 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx,
srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *enc_start; /* pointer to start of encrypted portion */
uint32_t *auth_start; /* pointer to start of auth. 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 */ 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 *auth_tag = NULL; /* location of auth_tag within packet */
uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
@ -4215,14 +4212,12 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx,
*/ */
/* This should point trailer to the word past the end of the normal data. */ /* This should point trailer to the word past the end of the normal data. */
/* This would need to be modified for optional mikey data */ /* This would need to be modified for optional mikey data */
/* trailer_p = (uint32_t *)((char *)hdr + *pkt_octet_len -
* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always (tag_len + mki_size + sizeof(srtcp_trailer_t)));
* multiples of 32-bits (RFC 3550 6.1) memcpy(&trailer, trailer_p, sizeof(trailer));
*/
trailer = (uint32_t *)((char *)hdr + *pkt_octet_len -
(tag_len + mki_size + sizeof(srtcp_trailer_t)));
e_bit_in_packet = 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) { if (e_bit_in_packet != sec_serv_confidentiality) {
return srtp_err_status_cant_check; return srtp_err_status_cant_check;
} }
@ -4266,7 +4261,7 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx,
* check the sequence number for replays * check the sequence number for replays
*/ */
/* this is easier than dealing with bitfield access */ /* 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); debug_print(mod_srtp, "srtcp index: %x", seq_num);
status = srtp_rdb_check(&stream->rtcp_rdb, seq_num); status = srtp_rdb_check(&stream->rtcp_rdb, seq_num);
if (status) if (status)
@ -4315,7 +4310,7 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx,
/* compare the tag just computed with the one in the packet */ /* compare the tag just computed with the one in the packet */
debug_print(mod_srtp, "srtcp tag from packet: %s", debug_print(mod_srtp, "srtcp tag from packet: %s",
srtp_octet_string_hex_string(auth_tag, tag_len)); 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; return srtp_err_status_auth_fail;
/* /*
@ -4437,7 +4432,7 @@ srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp(
case srtp_profile_null_sha1_80: case srtp_profile_null_sha1_80:
srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy);
break; break;
#if defined(OPENSSL) #ifdef GCM
case srtp_profile_aead_aes_128_gcm: case srtp_profile_aead_aes_128_gcm:
srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); srtp_crypto_policy_set_aes_gcm_128_16_auth(policy);
break; break;
@ -4471,7 +4466,7 @@ srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp(
case srtp_profile_null_sha1_80: case srtp_profile_null_sha1_80:
srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy);
break; break;
#if defined(OPENSSL) #ifdef GCM
case srtp_profile_aead_aes_128_gcm: case srtp_profile_aead_aes_128_gcm:
srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); srtp_crypto_policy_set_aes_gcm_128_16_auth(policy);
break; break;
@ -4552,10 +4547,10 @@ srtp_err_status_t stream_get_protect_trailer_length(srtp_stream_ctx_t *stream,
uint32_t mki_index, uint32_t mki_index,
uint32_t *length) uint32_t *length)
{ {
*length = 0;
srtp_session_keys_t *session_key; srtp_session_keys_t *session_key;
*length = 0;
if (use_mki) { if (use_mki) {
if (mki_index >= stream->num_master_keys) { if (mki_index >= stream->num_master_keys) {
return srtp_err_status_bad_mki; return srtp_err_status_bad_mki;

View File

@ -58,8 +58,9 @@ static int getopt_check_character(char c, const char *string)
while (*string != 0) { while (*string != 0) {
if (max_string_len == 0) { if (max_string_len == 0) {
return '?'; return GETOPT_NOT_FOUND;
} }
max_string_len--;
if (*string++ == c) { if (*string++ == c) {
if (*string == ':') { if (*string == ':') {
return GETOPT_FOUND_WITH_ARGUMENT; return GETOPT_FOUND_WITH_ARGUMENT;

View File

@ -50,6 +50,7 @@
#include "getopt_s.h" /* for local getopt() */ #include "getopt_s.h" /* for local getopt() */
#include "rdbx.h" #include "rdbx.h"
#include "cipher_priv.h"
#ifdef ROC_TEST #ifdef ROC_TEST
#error "srtp_rdbx_t won't work with ROC_TEST - bitmask same size as seq_median" #error "srtp_rdbx_t won't work with ROC_TEST - bitmask same size as seq_median"
@ -305,7 +306,7 @@ srtp_err_status_t test_replay_dbx(int num_trials, unsigned long ws)
*/ */
printf("\ttesting insertion with large gaps..."); printf("\ttesting insertion with large gaps...");
for (idx = 0, ircvd = 0; (int)idx < num_trials; 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); status = rdbx_check_add(&rdbx, ircvd);
if (status) if (status)
return status; return status;
@ -320,8 +321,7 @@ srtp_err_status_t test_replay_dbx(int num_trials, unsigned long ws)
return srtp_err_status_ok; return srtp_err_status_ok;
} }
#include <time.h> /* for clock() */ #include <time.h> /* for clock() */
#include <stdlib.h> /* for random() */
double rdbx_check_adds_per_second(int num_trials, unsigned long ws) double rdbx_check_adds_per_second(int num_trials, unsigned long ws)
{ {
@ -348,6 +348,9 @@ double rdbx_check_adds_per_second(int num_trials, unsigned long ws)
++failures; ++failures;
} }
timer = clock() - timer; timer = clock() - timer;
if (timer < 1) {
timer = 1;
}
printf("number of failures: %d \n", failures); printf("number of failures: %d \n", failures);

View File

@ -52,6 +52,8 @@
#include "rdb.h" #include "rdb.h"
#include "ut_sim.h" #include "ut_sim.h"
#include "cipher_priv.h"
/* /*
* num_trials defines the number of trials that are used in the * num_trials defines the number of trials that are used in the
* validation functions below * validation functions below
@ -189,7 +191,7 @@ srtp_err_status_t test_rdb_db()
/* test insertion with large gaps */ /* test insertion with large gaps */
for (idx = 0, ircvd = 0; idx < num_trials; 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); err = rdb_check_add(&rdb, ircvd);
if (err) if (err)
return err; return err;

View File

@ -97,7 +97,7 @@ srtp_err_status_t roc_test(int num_trials)
printf("\n\ttesting sequential insertion..."); printf("\n\ttesting sequential insertion...");
for (i = 0; i < 2048; i++) { 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 #if ROC_VERBOSE
printf("%lld, %lld, %d\n", ref, est, i); printf("%lld, %lld, %d\n", ref, est, i);
#endif #endif

View File

@ -53,6 +53,8 @@
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#include "cipher_priv.h"
#define PRINT_DEBUG 0 /* set to 1 to print out debugging data */ #define PRINT_DEBUG 0 /* set to 1 to print out debugging data */
#define VERBOSE_DEBUG 0 /* set to 1 to print out more data */ #define VERBOSE_DEBUG 0 /* set to 1 to print out more data */
@ -148,7 +150,7 @@ int rtp_sender_init(rtp_sender_t sender,
/* set header values */ /* set header values */
sender->message.header.ssrc = htonl(ssrc); sender->message.header.ssrc = htonl(ssrc);
sender->message.header.ts = 0; 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.m = 0;
sender->message.header.pt = 0x1; sender->message.header.pt = 0x1;
sender->message.header.version = 2; sender->message.header.version = 2;

View File

@ -83,23 +83,76 @@
#define MAX_KEY_LEN 96 #define MAX_KEY_LEN 96
#define MAX_FILTER 256 #define MAX_FILTER 256
#define MAX_FILE 255
struct srtp_crypto_suite { struct srtp_crypto_suite {
const char *can_name; const char *can_name;
int gcm_on;
int key_size; int key_size;
int tag_size; int tag_size;
}; };
static struct srtp_crypto_suite srtp_crypto_suites[] = { static struct srtp_crypto_suite srtp_crypto_suites[] = {
{.can_name = "AES_CM_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4 },
#if 0 #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 #endif
{.can_name = "AES_CM_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4 }, {.can_name = "AES_CM_128_HMAC_SHA1_32",
{.can_name = "AES_CM_128_HMAC_SHA1_80", .key_size = 128, .tag_size = 10 }, .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 } {.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[]) int main(int argc, char *argv[])
{ {
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
@ -112,15 +165,18 @@ int main(int argc, char *argv[])
int c; int c;
struct srtp_crypto_suite scs, *i_scsp; struct srtp_crypto_suite scs, *i_scsp;
scs.key_size = 128; scs.key_size = 128;
scs.tag_size = 8; scs.tag_size = 0;
int gcm_on = 0; int gcm_on = 0;
char *input_key = NULL; char *input_key = NULL;
int b64_input = 0; int b64_input = 0;
char key[MAX_KEY_LEN]; char key[MAX_KEY_LEN];
struct bpf_program fp; struct bpf_program fp;
char filter_exp[MAX_FILTER] = ""; char filter_exp[MAX_FILTER] = "";
char pcap_file[MAX_FILE] = "-";
int rtp_packet_offset = DEFAULT_RTP_OFFSET;
rtp_decoder_t dec; 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; srtp_err_status_t status;
int len; int len;
int expected_len; int expected_len;
@ -138,9 +194,15 @@ int main(int argc, char *argv[])
exit(1); 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 */ /* check args */
while (1) { 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) { if (c == -1) {
break; break;
} }
@ -153,10 +215,12 @@ int main(int argc, char *argv[])
break; break;
case 'e': case 'e':
scs.key_size = atoi(optarg_s); scs.key_size = atoi(optarg_s);
if (scs.key_size != 128 && scs.key_size != 256) { if (scs.key_size != 128 && scs.key_size != 192 &&
fprintf(stderr, scs.key_size != 256) {
"error: encryption key size must be 128 or 256 (%d)\n", fprintf(
scs.key_size); stderr,
"error: encryption key size must be 128, 192 or 256 (%d)\n",
scs.key_size);
exit(1); exit(1);
} }
input_key = malloc(scs.key_size); input_key = malloc(scs.key_size);
@ -173,7 +237,7 @@ int main(int argc, char *argv[])
sec_servs |= sec_serv_auth; sec_servs |= sec_serv_auth;
break; break;
case 'd': case 'd':
status = srtp_crypto_kernel_set_debug_module(optarg_s, 1); status = srtp_set_debug_module(optarg_s, 1);
if (status) { if (status) {
fprintf(stderr, "error: set debug module (%s) failed\n", fprintf(stderr, "error: set debug module (%s) failed\n",
optarg_s); optarg_s);
@ -207,20 +271,59 @@ int main(int argc, char *argv[])
scs = *i_scsp; scs = *i_scsp;
input_key = malloc(scs.key_size); input_key = malloc(scs.key_size);
sec_servs |= sec_serv_conf | sec_serv_auth; 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; break;
default: default:
usage(argv[0]); 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) { if (gcm_on && scs.tag_size != 8 && scs.tag_size != 16) {
fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n", fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n",
scs.tag_size); 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) { if (do_list_mods) {
status = srtp_crypto_kernel_list_debug_modules(); status = srtp_list_debug_modules();
if (status) { if (status) {
fprintf(stderr, "error: list of debug modules failed\n"); fprintf(stderr, "error: list of debug modules failed\n");
exit(1); exit(1);
@ -266,12 +369,24 @@ int main(int argc, char *argv[])
#ifdef OPENSSL #ifdef OPENSSL
switch (scs.key_size) { switch (scs.key_size) {
case 128: case 128:
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); if (scs.tag_size == 16) {
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); 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; break;
case 256: case 256:
srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); if (scs.tag_size == 16) {
srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); 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; break;
} }
#else #else
@ -282,12 +397,51 @@ int main(int argc, char *argv[])
} else { } else {
switch (scs.key_size) { switch (scs.key_size) {
case 128: case 128:
srtp_crypto_policy_set_rtp_default(&policy.rtp); if (scs.tag_size == 4) {
srtp_crypto_policy_set_rtcp_default(&policy.rtcp); 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; break;
case 256: case 256:
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); if (scs.tag_size == 4) {
srtp_crypto_policy_set_rtcp_default(&policy.rtcp); 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; break;
} }
} }
@ -302,11 +456,26 @@ int main(int argc, char *argv[])
switch (scs.key_size) { switch (scs.key_size) {
case 128: case 128:
srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); 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; break;
case 256: case 256:
srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); 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; break;
} }
} }
@ -353,7 +522,7 @@ int main(int argc, char *argv[])
policy.rtp.auth_tag_len = scs.tag_size; policy.rtp.auth_tag_len = scs.tag_size;
if (gcm_on && scs.tag_size != 8) { 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; policy.rtp.auth_tag_len = scs.tag_size;
} }
@ -365,11 +534,7 @@ int main(int argc, char *argv[])
int pad; int pad;
expected_len = policy.rtp.cipher_key_len * 4 / 3; expected_len = policy.rtp.cipher_key_len * 4 / 3;
len = base64_string_to_octet_string(key, &pad, input_key, len = base64_string_to_octet_string(key, &pad, input_key,
expected_len); strlen(input_key));
if (pad != 0) {
fprintf(stderr, "error: padding in base64 unexpected\n");
exit(1);
}
} else { } else {
expected_len = policy.rtp.cipher_key_len * 2; expected_len = policy.rtp.cipher_key_len * 2;
len = hex_string_to_octet_string(key, input_key, expected_len); len = hex_string_to_octet_string(key, input_key, expected_len);
@ -388,17 +553,20 @@ int main(int argc, char *argv[])
exit(1); 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/", fprintf(stderr, "set master key/salt to %s/",
octet_string_hex_string(key, 16)); octet_string_hex_string(key, key_octets));
fprintf(stderr, "%s\n", octet_string_hex_string(key + 16, 14)); fprintf(stderr, "%s\n",
octet_string_hex_string(key + key_octets, salt_octets));
} else { } else {
fprintf(stderr, fprintf(stderr,
"error: neither encryption or authentication were selected"); "error: neither encryption or authentication were selected\n");
exit(1); exit(1);
} }
pcap_handle = pcap_open_offline("-", errbuf); pcap_handle = pcap_open_offline(pcap_file, errbuf);
if (!pcap_handle) { if (!pcap_handle) {
fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf); fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf);
@ -421,11 +589,22 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
fprintf(stderr, "Starting decoder\n"); 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); 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); rtp_decoder_dealloc(dec);
status = srtp_shutdown(); status = srtp_shutdown();
@ -442,7 +621,8 @@ void usage(char *string)
{ {
fprintf( fprintf(
stderr, 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" "or %s -l\n"
"where -a use message authentication\n" "where -a use message authentication\n"
" -e <key size> use encryption (use 128 or 256 for key size)\n" " -e <key size> use encryption (use 128 or 256 for key size)\n"
@ -454,7 +634,10 @@ void usage(char *string)
" -f \"<pcap filter>\" to filter only the desired SRTP packets\n" " -f \"<pcap filter>\" to filter only the desired SRTP packets\n"
" -d <debug> turn on debugging for module <debug>\n" " -d <debug> turn on debugging for module <debug>\n"
" -s \"<srtp-crypto-suite>\" to set both key and tag size based\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); string, string);
exit(1); exit(1);
} }
@ -469,27 +652,34 @@ void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx)
free(rtp_ctx); free(rtp_ctx);
} }
srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder, int rtp_decoder_deinit(rtp_decoder_t decoder)
unsigned int ssrc)
{ {
decoder->policy.ssrc.value = htonl(ssrc); if (decoder->srtp_ctx) {
return srtp_create(&decoder->srtp_ctx, &decoder->policy); return srtp_dealloc(decoder->srtp_ctx);
}
return 0;
} }
int rtp_decoder_deinit_srtp(rtp_decoder_t decoder) int rtp_decoder_init(rtp_decoder_t dcdr,
srtp_policy_t policy,
rtp_decoder_mode_t mode,
int rtp_packet_offset)
{ {
return srtp_dealloc(decoder->srtp_ctx); dcdr->rtp_offset = rtp_packet_offset;
}
int rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy)
{
dcdr->rtp_offset = DEFAULT_RTP_OFFSET;
dcdr->srtp_ctx = NULL; dcdr->srtp_ctx = NULL;
dcdr->start_tv.tv_usec = 0; dcdr->start_tv.tv_usec = 0;
dcdr->start_tv.tv_sec = 0; dcdr->start_tv.tv_sec = 0;
dcdr->frame_nr = -1; dcdr->frame_nr = -1;
dcdr->error_cnt = 0;
dcdr->rtp_cnt = 0;
dcdr->rtcp_cnt = 0;
dcdr->mode = mode;
dcdr->policy = policy; 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; return 0;
} }
@ -516,6 +706,8 @@ void rtp_decoder_handle_pkt(u_char *arg,
const u_char *bytes) const u_char *bytes)
{ {
rtp_decoder_t dcdr = (rtp_decoder_t)arg; rtp_decoder_t dcdr = (rtp_decoder_t)arg;
rtp_msg_t message;
int rtp;
int pktsize; int pktsize;
struct timeval delta; struct timeval delta;
int octets_recvd; int octets_recvd;
@ -531,7 +723,7 @@ void rtp_decoder_handle_pkt(u_char *arg,
} }
const void *rtp_packet = bytes + dcdr->rtp_offset; 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; pktsize = hdr->caplen - dcdr->rtp_offset;
octets_recvd = pktsize; octets_recvd = pktsize;
@ -539,24 +731,43 @@ void rtp_decoder_handle_pkt(u_char *arg,
return; return;
} }
/* verify rtp header */ if (dcdr->mode == mode_rtp) {
if (dcdr->message.header.version != 2) { rtp = 1;
return; } else if (dcdr->mode == mode_rtcp) {
} rtp = 0;
if (dcdr->srtp_ctx == NULL) { } else {
status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc); rtp = 1;
if (status) { if (octets_recvd >= 2) {
exit(1); /* rfc5761 */
u_char payload_type = *(bytes + dcdr->rtp_offset + 1) & 0x7f;
rtp = payload_type < 64 || payload_type > 95;
} }
} }
status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd);
if (status) { if (rtp) {
return; /* verify rtp header */
if (message.header.version != 2) {
return;
}
status = srtp_unprotect(dcdr->srtp_ctx, &message, &octets_recvd);
if (status) {
dcdr->error_cnt++;
return;
}
dcdr->rtp_cnt++;
} else {
status = srtp_unprotect_rtcp(dcdr->srtp_ctx, &message, &octets_recvd);
if (status) {
dcdr->error_cnt++;
return;
}
dcdr->rtcp_cnt++;
} }
timersub(&hdr->ts, &dcdr->start_tv, &delta); timersub(&hdr->ts, &dcdr->start_tv, &delta);
fprintf(stdout, "%02ld:%02ld.%06ld\n", delta.tv_sec / 60, delta.tv_sec % 60, fprintf(stdout, "%02ld:%02ld.%06ld\n", delta.tv_sec / 60, delta.tv_sec % 60,
(long)delta.tv_usec); (long)delta.tv_usec);
hexdump(&dcdr->message, octets_recvd); hexdump(&message, octets_recvd);
} }
void rtp_print_error(srtp_err_status_t status, char *message) void rtp_print_error(srtp_err_status_t status, char *message)

View File

@ -52,13 +52,22 @@
#define DEFAULT_RTP_OFFSET 42 #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 { typedef struct rtp_decoder_ctx_t {
srtp_policy_t policy; srtp_policy_t policy;
srtp_ctx_t *srtp_ctx; srtp_ctx_t *srtp_ctx;
rtp_decoder_mode_t mode;
int rtp_offset; int rtp_offset;
struct timeval start_tv; struct timeval start_tv;
int frame_nr; int frame_nr;
rtp_msg_t message; int error_cnt;
int rtp_cnt;
int rtcp_cnt;
} rtp_decoder_ctx_t; } rtp_decoder_ctx_t;
typedef struct rtp_decoder_ctx_t *rtp_decoder_t; typedef struct rtp_decoder_ctx_t *rtp_decoder_t;
@ -95,11 +104,19 @@ rtp_decoder_t rtp_decoder_alloc(void);
void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx); void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx);
int rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy); int rtp_decoder_init(rtp_decoder_t dcdr,
srtp_policy_t policy,
rtp_decoder_mode_t mode,
int rtp_packet_offset);
srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder, int rtp_decoder_deinit(rtp_decoder_t decoder);
unsigned int ssrc);
int rtp_decoder_deinit_srtp(rtp_decoder_t decoder); void rtp_decoder_srtp_log_handler(srtp_log_level_t level,
const char *msg,
void *data);
void rtp_decoder_srtp_log_handler(srtp_log_level_t level,
const char *msg,
void *data);
#endif /* RTP_DECODER_H */ #endif /* RTP_DECODER_H */

View File

@ -317,6 +317,7 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
memset(&name, 0, sizeof(struct sockaddr_in));
name.sin_addr = rcvr_addr; name.sin_addr = rcvr_addr;
name.sin_family = PF_INET; name.sin_family = PF_INET;
name.sin_port = htons(port); name.sin_port = htons(port);
@ -364,7 +365,7 @@ int main(int argc, char *argv[])
switch (sec_servs) { switch (sec_servs) {
case sec_serv_conf_and_auth: case sec_serv_conf_and_auth:
if (gcm_on) { if (gcm_on) {
#ifdef OPENSSL #ifdef GCM
switch (key_size) { switch (key_size) {
case 128: case 128:
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
@ -377,7 +378,7 @@ int main(int argc, char *argv[])
} }
#else #else
printf("error: GCM mode only supported when using the OpenSSL " printf("error: GCM mode only supported when using the OpenSSL "
"crypto engine.\n"); "or NSS crypto engine.\n");
return 0; return 0;
#endif #endif
} else { } else {
@ -413,7 +414,7 @@ int main(int argc, char *argv[])
break; break;
case sec_serv_auth: case sec_serv_auth:
if (gcm_on) { if (gcm_on) {
#ifdef OPENSSL #ifdef GCM
switch (key_size) { switch (key_size) {
case 128: case 128:
srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);

View File

@ -41,8 +41,13 @@ case $(uname -s) in
*CYGWIN*|*MINGW*) *CYGWIN*|*MINGW*)
EXE=".exe" EXE=".exe"
;; ;;
*) *Linux*)
EXE="" EXE=""
export LD_LIBRARY_PATH=$CRYPTO_LIBDIR
;;
*Darwin*)
EXE=""
export DYLD_LIBRARY_PATH=$CRYPTO_LIBDIR
;; ;;
esac esac

View File

@ -41,8 +41,13 @@ case $(uname -s) in
*CYGWIN*|*MINGW*) *CYGWIN*|*MINGW*)
EXE=".exe" EXE=".exe"
;; ;;
*) *Linux*)
EXE="" EXE=""
export LD_LIBRARY_PATH=$CRYPTO_LIBDIR
;;
*Darwin*)
EXE=""
export DYLD_LIBRARY_PATH=$CRYPTO_LIBDIR
;; ;;
esac esac

View File

@ -61,13 +61,13 @@
srtp_err_status_t srtp_validate(void); srtp_err_status_t srtp_validate(void);
#ifdef OPENSSL #ifdef GCM
srtp_err_status_t srtp_validate_gcm(void); srtp_err_status_t srtp_validate_gcm(void);
#endif #endif
srtp_err_status_t srtp_validate_encrypted_extensions_headers(void); 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); srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void);
#endif #endif
@ -79,7 +79,7 @@ srtp_err_status_t srtp_dealloc_big_policy(srtp_policy_t *list);
srtp_err_status_t srtp_test_empty_payload(void); srtp_err_status_t srtp_test_empty_payload(void);
#ifdef OPENSSL #ifdef GCM
srtp_err_status_t srtp_test_empty_payload_gcm(void); srtp_err_status_t srtp_test_empty_payload_gcm(void);
#endif #endif
@ -422,7 +422,7 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
#ifdef OPENSSL #ifdef GCM
printf("testing srtp_protect and srtp_unprotect against " printf("testing srtp_protect and srtp_unprotect against "
"reference packet using GCM\n"); "reference packet using GCM\n");
if (srtp_validate_gcm() == srtp_err_status_ok) { if (srtp_validate_gcm() == srtp_err_status_ok) {
@ -442,7 +442,7 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
#ifdef OPENSSL #ifdef GCM
printf("testing srtp_protect and srtp_unprotect against " printf("testing srtp_protect and srtp_unprotect against "
"reference packet with encrypted extension headers (GCM)\n"); "reference packet with encrypted extension headers (GCM)\n");
if (srtp_validate_encrypted_extensions_headers_gcm() == if (srtp_validate_encrypted_extensions_headers_gcm() ==
@ -478,7 +478,7 @@ int main(int argc, char *argv[])
printf("failed\n"); printf("failed\n");
exit(1); exit(1);
} }
#ifdef OPENSSL #ifdef GCM
printf("testing srtp_protect and srtp_unprotect against " printf("testing srtp_protect and srtp_unprotect against "
"packet with empty payload (GCM)\n"); "packet with empty payload (GCM)\n");
if (srtp_test_empty_payload_gcm() == srtp_err_status_ok) { if (srtp_test_empty_payload_gcm() == srtp_err_status_ok) {
@ -1341,6 +1341,8 @@ srtp_err_status_t srtcp_test(const srtp_policy_t *policy, int mki_index)
*/ */
rcvr_policy = (srtp_policy_t *)malloc(sizeof(srtp_policy_t)); rcvr_policy = (srtp_policy_t *)malloc(sizeof(srtp_policy_t));
if (rcvr_policy == NULL) { if (rcvr_policy == NULL) {
free(hdr);
free(hdr2);
return srtp_err_status_alloc_fail; return srtp_err_status_alloc_fail;
} }
memcpy(rcvr_policy, policy, sizeof(srtp_policy_t)); memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
@ -1606,6 +1608,9 @@ double mips_estimate(int num_trials, int *ignore)
sum += i; sum += i;
} }
t = clock() - t; t = clock() - t;
if (t < 1) {
t = 1;
}
/* printf("%d\n", sum); */ /* printf("%d\n", sum); */
*ignore = sum; *ignore = sum;
@ -1702,7 +1707,7 @@ srtp_err_status_t srtp_validate()
debug_print(mod_driver, "ciphertext reference:\n %s", debug_print(mod_driver, "ciphertext reference:\n %s",
octet_string_hex_string(srtp_ciphertext, len)); 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;
} }
@ -1720,7 +1725,7 @@ srtp_err_status_t srtp_validate()
debug_print(mod_driver, "srtcp ciphertext reference:\n %s", debug_print(mod_driver, "srtcp ciphertext reference:\n %s",
octet_string_hex_string(srtcp_ciphertext, len)); 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 srtp_err_status_fail;
} }
@ -1742,7 +1747,7 @@ srtp_err_status_t srtp_validate()
return status; 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_fail;
} }
@ -1755,7 +1760,7 @@ srtp_err_status_t srtp_validate()
return status; 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_fail;
} }
@ -1772,7 +1777,7 @@ srtp_err_status_t srtp_validate()
return srtp_err_status_ok; return srtp_err_status_ok;
} }
#ifdef OPENSSL #ifdef GCM
/* /*
* srtp_validate_gcm() verifies the correctness of libsrtp by comparing * srtp_validate_gcm() verifies the correctness of libsrtp by comparing
* an computed packet against the known ciphertext for the plaintext. * an computed packet against the known ciphertext for the plaintext.
@ -1870,7 +1875,7 @@ srtp_err_status_t srtp_validate_gcm()
debug_print(mod_driver, "srtp ciphertext reference:\n %s", debug_print(mod_driver, "srtp ciphertext reference:\n %s",
octet_string_hex_string(srtp_ciphertext, len)); 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; return srtp_err_status_fail;
} }
@ -1888,7 +1893,7 @@ srtp_err_status_t srtp_validate_gcm()
debug_print(mod_driver, "srtcp ciphertext reference:\n %s", debug_print(mod_driver, "srtcp ciphertext reference:\n %s",
octet_string_hex_string(srtcp_ciphertext, len)); 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 srtp_err_status_fail;
} }
@ -1911,7 +1916,7 @@ srtp_err_status_t srtp_validate_gcm()
return status; 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 srtp_err_status_fail;
} }
@ -1924,7 +1929,7 @@ srtp_err_status_t srtp_validate_gcm()
return status; 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_fail;
} }
@ -2027,7 +2032,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers()
debug_print(mod_driver, "ciphertext reference:\n %s", debug_print(mod_driver, "ciphertext reference:\n %s",
srtp_octet_string_hex_string(srtp_ciphertext, len)); 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;
/* /*
@ -2049,7 +2054,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers()
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; return srtp_err_status_fail;
status = srtp_dealloc(srtp_snd); status = srtp_dealloc(srtp_snd);
@ -2063,7 +2068,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers()
return srtp_err_status_ok; return srtp_err_status_ok;
} }
#ifdef OPENSSL #ifdef GCM
/* /*
* Headers of test vectors taken from RFC 6904, Appendix A * Headers of test vectors taken from RFC 6904, Appendix A
@ -2148,7 +2153,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm()
debug_print(mod_driver, "ciphertext reference:\n %s", debug_print(mod_driver, "ciphertext reference:\n %s",
srtp_octet_string_hex_string(srtp_ciphertext, len)); 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;
/* /*
@ -2170,7 +2175,7 @@ srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm()
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; return srtp_err_status_fail;
status = srtp_dealloc(srtp_snd); status = srtp_dealloc(srtp_snd);
@ -2264,7 +2269,7 @@ srtp_err_status_t srtp_validate_aes_256()
debug_print(mod_driver, "ciphertext reference:\n %s", debug_print(mod_driver, "ciphertext reference:\n %s",
octet_string_hex_string(srtp_ciphertext, len)); 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;
} }
@ -2286,7 +2291,7 @@ srtp_err_status_t srtp_validate_aes_256()
return status; 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_fail;
} }
@ -2424,7 +2429,7 @@ srtp_err_status_t srtp_test_empty_payload()
return srtp_err_status_ok; return srtp_err_status_ok;
} }
#ifdef OPENSSL #ifdef GCM
srtp_err_status_t srtp_test_empty_payload_gcm() srtp_err_status_t srtp_test_empty_payload_gcm()
{ {
srtp_t srtp_snd, srtp_recv; srtp_t srtp_snd, srtp_recv;
@ -2499,7 +2504,7 @@ srtp_err_status_t srtp_test_empty_payload_gcm()
return srtp_err_status_ok; return srtp_err_status_ok;
} }
#endif // OPENSSL #endif // GCM
srtp_err_status_t srtp_test_remove_stream() srtp_err_status_t srtp_test_remove_stream()
{ {
@ -2783,10 +2788,10 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams(
srtp_policy_t policy; srtp_policy_t policy;
srtp_policy_t policy_mki; srtp_policy_t policy_mki;
#ifdef OPENSSL #ifdef GCM
srtp_policy_t policy_aes_gcm; srtp_policy_t policy_aes_gcm;
srtp_policy_t policy_aes_gcm_mki; srtp_policy_t policy_aes_gcm_mki;
#endif // OPENSSL #endif // GCM
memset(&policy, 0, sizeof(policy)); memset(&policy, 0, sizeof(policy));
srtp_crypto_policy_set_rtp_default(&policy.rtp); srtp_crypto_policy_set_rtp_default(&policy.rtp);
@ -2810,7 +2815,7 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams(
policy_mki.keys = test_keys; policy_mki.keys = test_keys;
policy_mki.num_master_keys = 2; policy_mki.num_master_keys = 2;
#ifdef OPENSSL #ifdef GCM
memset(&policy_aes_gcm, 0, sizeof(policy_aes_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.rtp);
srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtcp); srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtcp);
@ -2832,7 +2837,7 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams(
policy_aes_gcm_mki.key = NULL; policy_aes_gcm_mki.key = NULL;
policy_aes_gcm_mki.keys = test_keys; policy_aes_gcm_mki.keys = test_keys;
policy_aes_gcm_mki.num_master_keys = 2; policy_aes_gcm_mki.num_master_keys = 2;
#endif #endif // GCM
/* create a send ctx with defualt profile and test_key */ /* create a send ctx with defualt profile and test_key */
status = srtp_create(srtp_send, &policy); status = srtp_create(srtp_send, &policy);
@ -2843,7 +2848,7 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams(
if (status) if (status)
return status; return status;
#ifdef OPENSSL #ifdef GCM
status = srtp_create(srtp_send_aes_gcm, &policy_aes_gcm); status = srtp_create(srtp_send_aes_gcm, &policy_aes_gcm);
if (status) if (status)
return status; return status;
@ -2851,7 +2856,7 @@ srtp_err_status_t srtp_test_setup_protect_trailer_streams(
status = srtp_create(srtp_send_aes_gcm_mki, &policy_aes_gcm_mki); status = srtp_create(srtp_send_aes_gcm_mki, &policy_aes_gcm_mki);
if (status) if (status)
return status; return status;
#endif // OPENSSL #endif // GCM
return srtp_err_status_ok; return srtp_err_status_ok;
} }
@ -2884,7 +2889,7 @@ srtp_err_status_t srtp_test_protect_trailer_length()
if (length != 14) if (length != 14)
return srtp_err_status_fail; return srtp_err_status_fail;
#ifdef OPENSSL #ifdef GCM
status = srtp_get_protect_trailer_length(srtp_send_aes_gcm, 0, 0, &length); status = srtp_get_protect_trailer_length(srtp_send_aes_gcm, 0, 0, &length);
if (status) if (status)
return status; return status;
@ -2901,11 +2906,11 @@ srtp_err_status_t srtp_test_protect_trailer_length()
/* TAG Length: 16 bytes + MKI length: 4 bytes*/ /* TAG Length: 16 bytes + MKI length: 4 bytes*/
if (length != 20) if (length != 20)
return srtp_err_status_fail; return srtp_err_status_fail;
#endif // OPENSSL #endif // GCM
srtp_dealloc(srtp_send); srtp_dealloc(srtp_send);
srtp_dealloc(srtp_send_mki); srtp_dealloc(srtp_send_mki);
#ifdef OPENSSL #ifdef GCM
srtp_dealloc(srtp_send_aes_gcm); srtp_dealloc(srtp_send_aes_gcm);
srtp_dealloc(srtp_send_aes_gcm_mki); srtp_dealloc(srtp_send_aes_gcm_mki);
#endif #endif
@ -2941,7 +2946,7 @@ srtp_err_status_t srtp_test_protect_rtcp_trailer_length()
if (length != 18) if (length != 18)
return srtp_err_status_fail; return srtp_err_status_fail;
#ifdef OPENSSL #ifdef GCM
status = status =
srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm, 0, 0, &length); srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm, 0, 0, &length);
if (status) if (status)
@ -2959,11 +2964,11 @@ srtp_err_status_t srtp_test_protect_rtcp_trailer_length()
/* TAG Length: 16 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/ /* TAG Length: 16 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/
if (length != 24) if (length != 24)
return srtp_err_status_fail; return srtp_err_status_fail;
#endif // OPENSSL #endif // GCM
srtp_dealloc(srtp_send); srtp_dealloc(srtp_send);
srtp_dealloc(srtp_send_mki); srtp_dealloc(srtp_send_mki);
#ifdef OPENSSL #ifdef GCM
srtp_dealloc(srtp_send_aes_gcm); srtp_dealloc(srtp_send_aes_gcm);
srtp_dealloc(srtp_send_aes_gcm_mki); srtp_dealloc(srtp_send_aes_gcm_mki);
#endif #endif
@ -3088,6 +3093,7 @@ static srtp_err_status_t test_set_receiver_roc(uint32_t packets,
if (status) { if (status) {
return status; return status;
} }
seq++; seq++;
ts++; ts++;
} }
@ -3500,7 +3506,7 @@ const srtp_policy_t hmac_only_policy = {
NULL NULL
}; };
#ifdef OPENSSL #ifdef GCM
const srtp_policy_t aes128_gcm_8_policy = { const srtp_policy_t aes128_gcm_8_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */ { ssrc_any_outbound, 0 }, /* SSRC */
{ {
@ -3786,7 +3792,7 @@ const srtp_policy_t *policy_array[] = {
&hmac_only_policy, &hmac_only_policy,
&aes_only_policy, &aes_only_policy,
&default_policy, &default_policy,
#ifdef OPENSSL #ifdef GCM
&aes128_gcm_8_policy, &aes128_gcm_8_policy,
&aes128_gcm_8_cauth_policy, &aes128_gcm_8_cauth_policy,
&aes256_gcm_8_policy, &aes256_gcm_8_policy,

View File

@ -43,16 +43,16 @@
* *
*/ */
/*
* Test specific.
*/
#include "cutest.h"
/* /*
* libSRTP specific. * libSRTP specific.
*/ */
#include "../srtp/srtp.c" // Get access to static functions #include "../srtp/srtp.c" // Get access to static functions
/*
* Test specific.
*/
#include "cutest.h"
/* /*
* Standard library. * Standard library.
*/ */
@ -152,14 +152,15 @@ void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number()
srtp_session_keys_t session_keys; srtp_session_keys_t session_keys;
srtcp_hdr_t header; srtcp_hdr_t header;
v128_t output_iv[SAMPLE_COUNT]; v128_t output_iv[SAMPLE_COUNT];
memset(&output_iv, 0, SAMPLE_COUNT * sizeof(v128_t));
uint32_t sequence_num[SAMPLE_COUNT]; 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[0] = 0xFF;
sequence_num[1] = 0xFF00; sequence_num[1] = 0xFF00;
sequence_num[2] = 0xFF0000; sequence_num[2] = 0xFF0000;
// Postconditions // Postconditions
v128_t final_iv[SAMPLE_COUNT];
memset(&final_iv, 0, SAMPLE_COUNT * sizeof(v128_t)); memset(&final_iv, 0, SAMPLE_COUNT * sizeof(v128_t));
final_iv[0].v8[11] = 0xFF; final_iv[0].v8[11] = 0xFF;
final_iv[1].v8[10] = 0xFF; final_iv[1].v8[10] = 0xFF;
@ -170,7 +171,6 @@ void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number()
memset(&header, 0, sizeof(srtcp_hdr_t)); memset(&header, 0, sizeof(srtcp_hdr_t));
// When // When
size_t i = 0;
for (i = 0; i < SAMPLE_COUNT; i++) { for (i = 0; i < SAMPLE_COUNT; i++) {
TEST_CHECK(srtp_calc_aead_iv_srtcp(&session_keys, &output_iv[i], TEST_CHECK(srtp_calc_aead_iv_srtcp(&session_keys, &output_iv[i],
sequence_num[i], sequence_num[i],

View File

@ -42,12 +42,14 @@
* *
*/ */
#include "config.h"
#include "util.h" #include "util.h"
#include <string.h> #include <string.h>
#include <stdint.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) static inline int hex_char_to_nibble(uint8_t c)
{ {
@ -151,7 +153,7 @@ char *octet_string_hex_string(const void *s, int length)
/* truncate string if it would be too long */ /* truncate string if it would be too long */
if (length > MAX_PRINT_STRING_LEN) { if (length > MAX_PRINT_STRING_LEN) {
length = MAX_PRINT_STRING_LEN - 1; length = MAX_PRINT_STRING_LEN;
} }
for (i = 0; i < length; i += 2) { for (i = 0; i < length; i += 2) {