]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
update to cvs head srtp
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 17 Jan 2013 23:59:53 +0000 (17:59 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Mon, 1 Apr 2013 02:27:19 +0000 (21:27 -0500)
100 files changed:
libs/srtp/.update
libs/srtp/LICENSE
libs/srtp/README
libs/srtp/VERSION
libs/srtp/config.hw
libs/srtp/configure.in
libs/srtp/crypto/.cvsignore [new file with mode: 0644]
libs/srtp/crypto/Makefile.in
libs/srtp/crypto/ae_xfm/xfm.c
libs/srtp/crypto/cipher/aes.c
libs/srtp/crypto/cipher/aes_cbc.c
libs/srtp/crypto/cipher/aes_icm.c
libs/srtp/crypto/cipher/cipher.c
libs/srtp/crypto/cipher/null_cipher.c
libs/srtp/crypto/hash/auth.c
libs/srtp/crypto/hash/hmac.c
libs/srtp/crypto/hash/null_auth.c
libs/srtp/crypto/hash/sha1.c
libs/srtp/crypto/include/.cvsignore [new file with mode: 0644]
libs/srtp/crypto/include/aes.h
libs/srtp/crypto/include/aes_cbc.h
libs/srtp/crypto/include/aes_icm.h
libs/srtp/crypto/include/alloc.h
libs/srtp/crypto/include/auth.h
libs/srtp/crypto/include/cipher.h
libs/srtp/crypto/include/crypto.h
libs/srtp/crypto/include/crypto_kernel.h
libs/srtp/crypto/include/crypto_math.h
libs/srtp/crypto/include/crypto_types.h
libs/srtp/crypto/include/cryptoalg.h
libs/srtp/crypto/include/datatypes.h
libs/srtp/crypto/include/err.h
libs/srtp/crypto/include/gf2_8.h
libs/srtp/crypto/include/hmac.h
libs/srtp/crypto/include/integers.h
libs/srtp/crypto/include/key.h
libs/srtp/crypto/include/null_auth.h
libs/srtp/crypto/include/null_cipher.h
libs/srtp/crypto/include/rand_source.h
libs/srtp/crypto/include/rdb.h
libs/srtp/crypto/include/rdbx.h
libs/srtp/crypto/include/sha1.h
libs/srtp/crypto/include/stat.h
libs/srtp/crypto/kernel/alloc.c
libs/srtp/crypto/kernel/crypto_kernel.c
libs/srtp/crypto/kernel/err.c
libs/srtp/crypto/kernel/key.c
libs/srtp/crypto/math/datatypes.c
libs/srtp/crypto/math/gf2_8.c
libs/srtp/crypto/math/math.c
libs/srtp/crypto/math/stat.c
libs/srtp/crypto/replay/rdb.c
libs/srtp/crypto/replay/rdbx.c
libs/srtp/crypto/replay/ut_sim.c
libs/srtp/crypto/rng/ctr_prng.c
libs/srtp/crypto/rng/prng.c
libs/srtp/crypto/rng/rand_source.c
libs/srtp/crypto/test/.cvsignore [new file with mode: 0644]
libs/srtp/crypto/test/aes_calc [new file with mode: 0755]
libs/srtp/crypto/test/aes_calc.c
libs/srtp/crypto/test/auth_driver.c
libs/srtp/crypto/test/cipher_driver.c
libs/srtp/crypto/test/datatypes_driver [new file with mode: 0755]
libs/srtp/crypto/test/datatypes_driver.c
libs/srtp/crypto/test/env.c
libs/srtp/crypto/test/kernel_driver.c
libs/srtp/crypto/test/rand_gen.c
libs/srtp/crypto/test/sha1_driver [new file with mode: 0755]
libs/srtp/crypto/test/sha1_driver.c
libs/srtp/crypto/test/stat_driver [new file with mode: 0755]
libs/srtp/crypto/test/stat_driver.c
libs/srtp/doc/Doxyfile
libs/srtp/doc/header.template
libs/srtp/doc/intro.txt
libs/srtp/doc/libsrtp.pdf
libs/srtp/include/ekt.h [new file with mode: 0644]
libs/srtp/include/getopt_s.h [new file with mode: 0644]
libs/srtp/include/rtp.h
libs/srtp/include/rtp_priv.h [new file with mode: 0644]
libs/srtp/include/srtp.h
libs/srtp/include/srtp_priv.h [new file with mode: 0644]
libs/srtp/include/ut_sim.h
libs/srtp/srtp.def
libs/srtp/srtp/ekt.c [new file with mode: 0644]
libs/srtp/srtp/srtp.c
libs/srtp/tables/aes_tables.c
libs/srtp/test/dtls_srtp_driver.c [new file with mode: 0644]
libs/srtp/test/getopt_s.c [new file with mode: 0644]
libs/srtp/test/rdbx_driver [new file with mode: 0755]
libs/srtp/test/rdbx_driver.c
libs/srtp/test/replay_driver [new file with mode: 0755]
libs/srtp/test/replay_driver.c
libs/srtp/test/roc_driver [new file with mode: 0755]
libs/srtp/test/roc_driver.c
libs/srtp/test/rtp.c
libs/srtp/test/rtpw.c
libs/srtp/test/rtpw_test.sh [new file with mode: 0755]
libs/srtp/test/srtp_driver.c
libs/srtp/update.sh
src/switch_rtp.c

index 0269e528540146669795901237d8a66e91158ccf..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-Fri Mar 16 17:20:27 EDT 2007
index d1ff4e8559a16db9a9657907a66f710fa90c8615..dd43240cae549b41df950a2a45a47adee360fd57 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 02dc1f8eb59d574effe86106bf3b3f8472c9c8bb..08fafaedbc4f6e5a72a9eab2c18937b5f015707a 100644 (file)
@@ -1,4 +1,4 @@
-Secure RTP (SRTP) and UST Reference Implementations
+Secure RTP (SRTP) Reference Implementation
 David A. McGrew
 Cisco Systems, Inc.
 mcgrew@cisco.com
@@ -9,7 +9,9 @@ Transport Protocol (SRTP), the Universal Security Transform (UST), and
 a supporting cryptographic kernel.  These mechanisms are documented in
 the Internet Drafts in the doc/ subdirectory.  The SRTP API is
 documented in include/srtp.h, and the library is in libsrtp.a (after
-compilation).
+compilation).  An overview and reference manual is available in
+doc/libsrtp.pdf.  The PDF documentation is more up to date than this
+file.
 
 
 Installation:
index 9df886c42a1e2082f1471383d986fea4d531f8ac..1c99cf0e80935dc79a726b43fb1a9de36e07ad46 100644 (file)
@@ -1 +1 @@
-1.4.2
+1.4.4
index 32f5ed9196bfc8d172b79aa5e06ae6f63bd43115..39d4e0736403f14058dd5f68f6648ec35fcda320 100644 (file)
-/* crypto/include/config.h.  Generated by configure.  */\r
-/* config_in.h.  Generated from configure.in by autoheader.  */\r
-\r
-/* Define if building for a CISC machine (e.g. Intel). */\r
-#define CPU_CISC 1\r
-\r
-/* Define if building for a RISC machine (assume slow byte access). */\r
-/* #undef CPU_RISC */\r
-\r
-/* Path to random device */\r
-/* #define DEV_URANDOM "/dev/urandom" */\r
-\r
-/* Define to compile in dynamic debugging system. */\r
-#define ENABLE_DEBUGGING 1\r
-\r
-/* Report errors to this file. */\r
-/* #undef ERR_REPORTING_FILE */\r
-\r
-/* Define to use logging to stdout. */\r
-#define ERR_REPORTING_STDOUT 1\r
-\r
-/* Define this to use ISMAcryp code. */\r
-/* #undef GENERIC_AESICM */\r
-\r
-/* Define to 1 if you have the <arpa/inet.h> header file. */\r
-/* #undef HAVE_ARPA_INET_H */\r
-\r
-/* Define to 1 if you have the <byteswap.h> header file. */\r
-/* #undef HAVE_BYTESWAP_H */\r
-\r
-/* Define to 1 if you have the `inet_aton' function. */\r
-/* #undef HAVE_INET_ATON */\r
-\r
-/* Define to 1 if the system has the type `int16_t'. */\r
-#define HAVE_INT16_T 1\r
-\r
-/* Define to 1 if the system has the type `int32_t'. */\r
-#define HAVE_INT32_T 1\r
-\r
-/* Define to 1 if the system has the type `int8_t'. */\r
-#define HAVE_INT8_T 1\r
-\r
-/* Define to 1 if you have the <inttypes.h> header file. */\r
-/* #undef HAVE_INTTYPES_H */\r
-\r
-/* Define to 1 if you have the `socket' library (-lsocket). */\r
-/* #undef HAVE_LIBSOCKET */\r
-\r
-/* Define to 1 if you have the <machine/types.h> header file. */\r
-/* #undef HAVE_MACHINE_TYPES_H */\r
-\r
-/* Define to 1 if you have the <memory.h> header file. */\r
-#define HAVE_MEMORY_H 1\r
-\r
-/* Define to 1 if you have the <netinet/in.h> header file. */\r
-/* #undef HAVE_NETINET_IN_H */\r
-\r
-/* Define to 1 if you have the `socket' function. */\r
-/* #undef HAVE_SOCKET */\r
-\r
-/* Define to 1 if you have the <stdint.h> header file. */\r
-/* #undef HAVE_STDINT_H */\r
-\r
-/* Define to 1 if you have the <stdlib.h> header file. */\r
-#define HAVE_STDLIB_H 1\r
-\r
-/* Define to 1 if you have the <strings.h> header file. */\r
-#define HAVE_STRINGS_H 1\r
-\r
-/* Define to 1 if you have the <string.h> header file. */\r
-#define HAVE_STRING_H 1\r
-\r
-/* Define to 1 if you have the <syslog.h> header file. */\r
-/* #undef HAVE_SYSLOG_H */\r
-\r
-/* Define to 1 if you have the <sys/int_types.h> header file. */\r
-/* #undef HAVE_SYS_INT_TYPES_H */\r
-\r
-/* Define to 1 if you have the <sys/socket.h> header file. */\r
-/* #undef HAVE_SYS_SOCKET_H */\r
-\r
-/* Define to 1 if you have the <sys/stat.h> header file. */\r
-#define HAVE_SYS_STAT_H 1\r
-\r
-/* Define to 1 if you have the <sys/types.h> header file. */\r
-#define HAVE_SYS_TYPES_H 1\r
-\r
-/* Define to 1 if you have the <sys/uio.h> header file. */\r
-/* #undef HAVE_SYS_UIO_H */\r
-\r
-/* Define to 1 if the system has the type `uint16_t'. */\r
-#define HAVE_UINT16_T 1\r
-\r
-/* Define to 1 if the system has the type `uint32_t'. */\r
-#define HAVE_UINT32_T 1\r
-\r
-/* Define to 1 if the system has the type `uint64_t'. */\r
-#define HAVE_UINT64_T 1\r
-\r
-/* Define to 1 if the system has the type `uint8_t'. */\r
-#define HAVE_UINT8_T 1\r
-\r
-/* Define to 1 if you have the <unistd.h> header file. */\r
-/* #undef HAVE_UNISTD_H */\r
-\r
-/* Define to 1 if you have the `usleep' function. */\r
-/* #undef HAVE_USLEEP */\r
-\r
-/* Define to 1 if you have the <windows.h> header file. */\r
-#define HAVE_WINDOWS_H 1\r
-\r
-/* Define to 1 if you have the <winsock2.h> header file. */\r
-#define HAVE_WINSOCK2_H 1\r
-\r
-/* Define to use X86 inlined assembly code */\r
-/* #undef HAVE_X86 */\r
-\r
-/* Define to the address where bug reports for this package should be sent. */\r
-#define PACKAGE_BUGREPORT ""\r
-\r
-/* Define to the full name of this package. */\r
-#define PACKAGE_NAME ""\r
-\r
-/* Define to the full name and version of this package. */\r
-#define PACKAGE_STRING ""\r
-\r
-/* Define to the one symbol short name of this package. */\r
-#define PACKAGE_TARNAME ""\r
-\r
-/* Define to the version of this package. */\r
-#define PACKAGE_VERSION ""\r
-\r
-/* The size of a `unsigned long', as computed by sizeof. */\r
-#define SIZEOF_UNSIGNED_LONG 4\r
-\r
-/* The size of a `unsigned long long', as computed by sizeof. */\r
-#define SIZEOF_UNSIGNED_LONG_LONG 8\r
-\r
-/* Define to use GDOI. */\r
-/* #undef SRTP_GDOI */\r
-\r
-/* Define to compile for kernel contexts. */\r
-/* #undef SRTP_KERNEL */\r
-\r
-/* Define to compile for Linux kernel context. */\r
-/* #undef SRTP_KERNEL_LINUX */\r
-\r
-/* Define to 1 if you have the ANSI C header files. */\r
-#define STDC_HEADERS 1\r
-\r
-/* Write errors to this file */\r
-/* #undef USE_ERR_REPORTING_FILE */\r
-\r
-/* Define to use syslog logging. */\r
-/* #undef USE_SYSLOG */\r
-\r
-/* Define to 1 if your processor stores words with the most significant byte\r
-   first (like Motorola and SPARC, unlike Intel and VAX). */\r
-/* #undef WORDS_BIGENDIAN */\r
-\r
-/* Define to empty if `const' does not conform to ANSI C. */\r
-/* #undef const */\r
-\r
-/* Define to `__inline__' or `__inline' if that's what the C compiler\r
-   calls it, or to nothing if 'inline' is not supported under any name.  */\r
-#ifndef __cplusplus\r
-#define inline __inline\r
-#endif\r
-\r
-/* Define to `unsigned' if <sys/types.h> does not define. */\r
-/* #undef size_t */\r
-\r
-#if (_MSC_VER >= 1400) // VC8+\r
-#ifndef _CRT_SECURE_NO_DEPRECATE\r
-#define _CRT_SECURE_NO_DEPRECATE\r
-#endif\r
-#ifndef _CRT_NONSTDC_NO_DEPRECATE\r
-#define _CRT_NONSTDC_NO_DEPRECATE\r
-#endif\r
-#endif // VC8+\r
-\r
-#ifndef uint32_t\r
-typedef unsigned __int8                uint8_t;\r
-typedef unsigned __int16       uint16_t;\r
-typedef unsigned __int32       uint32_t;\r
-typedef unsigned __int64    uint64_t;\r
-typedef __int8         int8_t;\r
-typedef __int16                int16_t;\r
-typedef __int32                int32_t;\r
-typedef __int64                int64_t;\r
-#endif\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable:4311)\r
-#endif\r
+/* crypto/include/config.h.  Generated by configure.  */
+/* config_in.h.  Generated from configure.in by autoheader.  */
+
+#if (_MSC_VER >= 1400)
+# define HAVE_RAND_S   1
+#endif
+
+/* Define if building for a CISC machine (e.g. Intel). */
+#define CPU_CISC 1
+
+/* Define if building for a RISC machine (assume slow byte access). */
+/* #undef CPU_RISC */
+
+/* Path to random device */
+/* #define DEV_URANDOM "/dev/urandom" */
+
+/* Define to compile in dynamic debugging system. */
+#define ENABLE_DEBUGGING 1
+
+/* Report errors to this file. */
+/* #undef ERR_REPORTING_FILE */
+
+/* Define to use logging to stdout. */
+#define ERR_REPORTING_STDOUT 1
+
+/* Define this to use ISMAcryp code. */
+/* #undef GENERIC_AESICM */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+/* #undef HAVE_ARPA_INET_H */
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+/* #undef HAVE_BYTESWAP_H */
+
+/* Define to 1 if you have the `inet_aton' function. */
+/* #undef HAVE_INET_ATON */
+
+/* Define to 1 if the system has the type `int16_t'. */
+#define HAVE_INT16_T 1
+
+/* Define to 1 if the system has the type `int32_t'. */
+#define HAVE_INT32_T 1
+
+/* Define to 1 if the system has the type `int8_t'. */
+#define HAVE_INT8_T 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the <machine/types.h> header file. */
+/* #undef HAVE_MACHINE_TYPES_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+/* #undef HAVE_NETINET_IN_H */
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+/* #undef HAVE_SYSLOG_H */
+
+/* Define to 1 if you have the <sys/int_types.h> header file. */
+/* #undef HAVE_SYS_INT_TYPES_H */
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+/* #undef HAVE_SYS_SOCKET_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+/* #undef HAVE_SYS_UIO_H */
+
+/* Define to 1 if the system has the type `uint16_t'. */
+#define HAVE_UINT16_T 1
+
+/* Define to 1 if the system has the type `uint32_t'. */
+#define HAVE_UINT32_T 1
+
+/* Define to 1 if the system has the type `uint64_t'. */
+#define HAVE_UINT64_T 1
+
+/* Define to 1 if the system has the type `uint8_t'. */
+#define HAVE_UINT8_T 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #undef HAVE_UNISTD_H */
+
+/* Define to 1 if you have the `usleep' function. */
+/* #undef HAVE_USLEEP */
+
+/* Define to 1 if you have the <windows.h> header file. */
+#define HAVE_WINDOWS_H 1
+
+/* Define to 1 if you have the <winsock2.h> header file. */
+#define HAVE_WINSOCK2_H 1
+
+/* Define to use X86 inlined assembly code */
+/* #undef HAVE_X86 */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* The size of a `unsigned long', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_LONG 4
+
+/* The size of a `unsigned long long', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_LONG_LONG 8
+
+/* Define to use GDOI. */
+/* #undef SRTP_GDOI */
+
+/* Define to compile for kernel contexts. */
+/* #undef SRTP_KERNEL */
+
+/* Define to compile for Linux kernel context. */
+/* #undef SRTP_KERNEL_LINUX */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Write errors to this file */
+/* #undef USE_ERR_REPORTING_FILE */
+
+/* Define to use syslog logging. */
+/* #undef USE_SYSLOG */
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define 'inline' to nothing, since the MSVC compiler doesn't support it.  */
+#define inline 
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+#if (_MSC_VER >= 1400) // VC8+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#ifndef _CRT_NONSTDC_NO_DEPRECATE
+#define _CRT_NONSTDC_NO_DEPRECATE
+#endif
+#endif // VC8+
+
+#ifndef uint32_t
+typedef unsigned __int8                uint8_t;
+typedef unsigned __int16       uint16_t;
+typedef unsigned __int32       uint32_t;
+typedef unsigned __int64    uint64_t;
+typedef __int8         int8_t;
+typedef __int16                int16_t;
+typedef __int32                int32_t;
+typedef __int64                int64_t;
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable:4311)
+#endif
index 2495a55f9553ab064782830342923bef614530c1..dc471c5b141e5a9c739e106b29203f5e2a970914 100644 (file)
@@ -144,10 +144,10 @@ fi
 
 AC_MSG_CHECKING(which random device to use)
 if test "$enable_kernel_linux" = "yes"; then
-   RNG_OBJS=rand_linux_kernel.c
+   RNG_OBJS=rand_linux_kernel.o
    AC_MSG_RESULT([Linux kernel builtin])
 else
-RNG_OBJS=rand_source.c
+RNG_OBJS=rand_source.o
    if test -n "$DEV_URANDOM"; then
       AC_DEFINE_UNQUOTED(DEV_URANDOM, "$DEV_URANDOM",[Path to random device])
       AC_MSG_RESULT([$DEV_URANDOM])
@@ -197,7 +197,7 @@ AC_C_INLINE
 AC_TYPE_SIZE_T
 
 dnl Checks for library functions.
-AC_CHECK_FUNCS(socket inet_aton usleep)
+AC_CHECK_FUNCS(socket inet_aton usleep sigaction)
 
 dnl Find socket function if not found yet.
 if test "x$ac_cv_func_socket" = "xno"; then
@@ -222,7 +222,7 @@ AC_C_BIGENDIAN
 
 dnl check host_cpu type, set defines appropriately
 case $host_cpu in
-     i*86 )
+     i*86 | x86_64 )
        AC_DEFINE(CPU_CISC, 1,
           [Define if building for a CISC machine (e.g. Intel).])
         AC_DEFINE(HAVE_X86, 1,
diff --git a/libs/srtp/crypto/.cvsignore b/libs/srtp/crypto/.cvsignore
new file mode 100644 (file)
index 0000000..f3c7a7c
--- /dev/null
@@ -0,0 +1 @@
+Makefile
index c14dba50c584a80b9ae0d60eceb40115b7aff9fb..9d521042103eae2b1041c9f36cffc02674245a93 100644 (file)
@@ -41,21 +41,28 @@ dummy : all runtest
 
 # test applications 
 
-testapp = test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \
-         test/stat_driver$(EXE) test/sha1_driver$(EXE) \
-         test/kernel_driver$(EXE) test/aes_calc$(EXE) test/rand_gen$(EXE) \
-         test/env$(EXE)
+testapp = #test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \
+         #test/stat_driver$(EXE) test/sha1_driver$(EXE) \
+         #test/kernel_driver$(EXE) test/aes_calc$(EXE) test/rand_gen$(EXE) \
+         #test/env$(EXE)
 
-# data values used to test the aes_calc application
+# data values used to test the aes_calc application for AES-128
+k128=000102030405060708090a0b0c0d0e0f
+p128=00112233445566778899aabbccddeeff
+c128=69c4e0d86a7b0430d8cdb78070b4c55a
+
+
+# data values used to test the aes_calc application for AES-256
+k256=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+p256=00112233445566778899aabbccddeeff
+c256=8ea2b7ca516745bfeafc49904b496089
 
-k=000102030405060708090a0b0c0d0e0f
-p=00112233445566778899aabbccddeeff
-c=69c4e0d86a7b0430d8cdb78070b4c55a
 
 runtest: libcryptomodule.a $(testapp)
        test/env$(EXE) # print out information on the build environment
        @echo "running libcryptomodule test applications..."
-       test `test/aes_calc $k $p` = $c
+       test `test/aes_calc $(k128) $(p128)` = $(c128)
+       test `test/aes_calc $(k256) $(p256)` = $(c256)
        test/cipher_driver$(EXE) -v >/dev/null
        test/datatypes_driver$(EXE) -v >/dev/null
        test/stat_driver$(EXE) >/dev/null
index 05ff710f9093dae53ac3da31ac0d59748fd92547..7aa338830f9740a3baf931a59135bfe981d3f91b 100644 (file)
@@ -63,7 +63,7 @@ aes_128_cbc_hmac_sha1_96_func(void *key,
     /* perform encryption and authentication */
 
     /* set aes key */
-    status = aes_cbc_context_init(&aes_ctx, key, direction_encrypt);
+    status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt);
     if (status) return status;
 
     /* set iv */
@@ -139,7 +139,7 @@ aes_128_cbc_hmac_sha1_96_inv(void *key,
     /* perform encryption and authentication */
 
     /* set aes key */
-    status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt);
+    status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt);
     if (status) return status;
 
     /* set iv */
@@ -227,7 +227,7 @@ aes_128_cbc_hmac_sha1_96_enc(void *key,
     /* perform encryption and authentication */
 
     /* set aes key */
-    status = aes_cbc_context_init(&aes_ctx, key, direction_encrypt);
+    status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt);
     if (status) return status;
 
     /* set iv */
@@ -397,7 +397,7 @@ aes_128_cbc_hmac_sha1_96_dec(void *key,
     *opaque_len -= TAG_LEN;
 
     /* decrypt the confidential data */
-    status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt);
+    status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt);
     if (status) return status;
     status = aes_cbc_set_iv(&aes_ctx, iv);
     if (status) return status;
@@ -564,7 +564,7 @@ cryptoalg_find_by_id(int id) {
   case 1:
     return cryptoalg;
   default:
-    return 0;
+    break;
   }
   return 0;
 }
index c736e17102c528727c952d642efdb9ac526042e7..a17b9e49933918a7bce7576c13d2888b951d39db 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -1358,51 +1358,50 @@ static uint32_t U4[256] = {
 
 extern debug_module_t mod_aes_icm;
 
-void
-aes_expand_encryption_key(const v128_t *key, 
-                         aes_expanded_key_t expanded_key) {
+static void
+aes_128_expand_encryption_key(const uint8_t *key, 
+                             aes_expanded_key_t *expanded_key) {
   int i;
   gf2_8 rc;
 
   /* initialize round constant */
   rc = 1;
 
-  expanded_key[0].v32[0] = key->v32[0];
-  expanded_key[0].v32[1] = key->v32[1];
-  expanded_key[0].v32[2] = key->v32[2];
-  expanded_key[0].v32[3] = key->v32[3];
+  expanded_key->num_rounds = 10;
+
+  v128_copy_octet_string(&expanded_key->round[0], key);
 
 #if 0
   debug_print(mod_aes_icm, 
-             "expanded key[0]:  %s", v128_hex_string(&expanded_key[0])); 
+             "expanded key[0]:  %s", v128_hex_string(&expanded_key->round[0])); 
 #endif
 
   /* loop over round keys */
   for (i=1; i < 11; i++) {
 
     /* munge first word of round key */
-    expanded_key[i].v8[0] = aes_sbox[expanded_key[i-1].v8[13]] ^ rc;
-    expanded_key[i].v8[1] = aes_sbox[expanded_key[i-1].v8[14]];
-    expanded_key[i].v8[2] = aes_sbox[expanded_key[i-1].v8[15]];
-    expanded_key[i].v8[3] = aes_sbox[expanded_key[i-1].v8[12]];
+    expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[13]] ^ rc;
+    expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[14]];
+    expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[15]];
+    expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[12]];
 
-    expanded_key[i].v32[0] ^=  expanded_key[i-1].v32[0];
+    expanded_key->round[i].v32[0] ^=  expanded_key->round[i-1].v32[0];
 
     /* set remaining 32 bit words to the exor of the one previous with
      * the one four words previous */
 
-    expanded_key[i].v32[1] =
-      expanded_key[i].v32[0] ^ expanded_key[i-1].v32[1];
+    expanded_key->round[i].v32[1] =
+      expanded_key->round[i].v32[0] ^ expanded_key->round[i-1].v32[1];
 
-    expanded_key[i].v32[2] =
-      expanded_key[i].v32[1] ^ expanded_key[i-1].v32[2];
+    expanded_key->round[i].v32[2] =
+      expanded_key->round[i].v32[1] ^ expanded_key->round[i-1].v32[2];
 
-    expanded_key[i].v32[3] =
-      expanded_key[i].v32[2] ^ expanded_key[i-1].v32[3];
+    expanded_key->round[i].v32[3] =
+      expanded_key->round[i].v32[2] ^ expanded_key->round[i-1].v32[3];
 
 #if 0
        debug_print2(mod_aes_icm, 
-                               "expanded key[%d]:  %s", i,v128_hex_string(&expanded_key[i])); 
+                               "expanded key[%d]:  %s", i,v128_hex_string(&expanded_key->round[i])); 
 #endif
 
     /* modify round constant */
@@ -1411,19 +1410,107 @@ aes_expand_encryption_key(const v128_t *key,
   }
 }
 
-void
-aes_expand_decryption_key(const v128_t *key, 
-                         aes_expanded_key_t expanded_key) {
+static void
+aes_256_expand_encryption_key(const unsigned char *key, 
+                             aes_expanded_key_t *expanded_key) {
+  int i;
+  gf2_8 rc;
+
+  /* initialize round constant */
+  rc = 1;
+
+  expanded_key->num_rounds = 14;
+
+  v128_copy_octet_string(&expanded_key->round[0], key);
+  v128_copy_octet_string(&expanded_key->round[1], key+16);
+
+#if 0
+  debug_print(mod_aes_icm, 
+             "expanded key[0]:  %s", v128_hex_string(&expanded_key->round[0])); 
+  debug_print(mod_aes_icm, 
+             "expanded key[1]:  %s", v128_hex_string(&expanded_key->round[1])); 
+#endif
+
+  /* loop over rest of round keys */
+  for (i=2; i < 15; i++) {
+
+    /* munge first word of round key */
+    if ((i & 1) == 0) {
+      expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[13]] ^ rc;
+      expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[14]];
+      expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[15]];
+      expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[12]];
+
+      /* modify round constant */
+      rc = gf2_8_shift(rc);
+    }
+    else {
+      expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[12]];
+      expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[13]];
+      expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[14]];
+      expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[15]];
+    }
+
+    expanded_key->round[i].v32[0] ^=  expanded_key->round[i-2].v32[0];
+
+    /* set remaining 32 bit words to the exor of the one previous with
+     * the one eight words previous */
+
+    expanded_key->round[i].v32[1] =
+      expanded_key->round[i].v32[0] ^ expanded_key->round[i-2].v32[1];
+
+    expanded_key->round[i].v32[2] =
+      expanded_key->round[i].v32[1] ^ expanded_key->round[i-2].v32[2];
+
+    expanded_key->round[i].v32[3] =
+      expanded_key->round[i].v32[2] ^ expanded_key->round[i-2].v32[3];
+
+#if 0
+    debug_print2(mod_aes_icm, 
+                "expanded key[%d]:  %s", i,v128_hex_string(&expanded_key->round[i])); 
+#endif
+
+  }
+}
+
+err_status_t
+aes_expand_encryption_key(const uint8_t *key, 
+                         int key_len,
+                         aes_expanded_key_t *expanded_key) {
+  if (key_len == 16) {
+    aes_128_expand_encryption_key(key, expanded_key);
+    return err_status_ok;
+  }
+  else if (key_len == 24) {
+    /* AES-192 not yet supported */
+    return err_status_bad_param;
+  }
+  else if (key_len == 32) {
+    aes_256_expand_encryption_key(key, expanded_key);
+    return err_status_ok;
+  }
+  else
+    return err_status_bad_param;
+}
+
+err_status_t
+aes_expand_decryption_key(const uint8_t *key, 
+                         int key_len,
+                         aes_expanded_key_t *expanded_key) {
   int i;
+  err_status_t status;
+  int num_rounds = expanded_key->num_rounds;
 
-  aes_expand_encryption_key(key, expanded_key);
+  status = aes_expand_encryption_key(key, key_len, expanded_key);
+  if (status)
+    return status;
 
   /* invert the order of the round keys */
-  for (i=0; i < 5; i++) {
+  for (i=0; i < num_rounds/2; i++) {
     v128_t tmp;
-    v128_copy(&tmp, &expanded_key[10-i]);
-    v128_copy(&expanded_key[10-i], &expanded_key[i]);
-    v128_copy(&expanded_key[i], &tmp);
+    v128_copy(&tmp, &expanded_key->round[num_rounds-i]);
+    v128_copy(&expanded_key->round[num_rounds-i], &expanded_key->round[i]);
+    v128_copy(&expanded_key->round[i], &tmp);
   }
 
   /* 
@@ -1434,33 +1521,33 @@ aes_expand_decryption_key(const v128_t *key,
    * followed by the T4 table (which cancels out the use of the sbox
    * in the U-tables)
    */
-  for (i=1; i < 10; i++) {
+  for (i=1; i < num_rounds; i++) {
 #ifdef CPU_RISC
     uint32_t tmp;
 
-    tmp = expanded_key[i].v32[0];
-    expanded_key[i].v32[0] = 
+    tmp = expanded_key->round[i].v32[0];
+    expanded_key->round[i].v32[0] = 
       U0[T4[(tmp >> 24)       ] & 0xff] ^ 
       U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ 
       U2[T4[(tmp >> 8)  & 0xff] & 0xff] ^ 
       U3[T4[(tmp)       & 0xff] & 0xff];
 
-    tmp = expanded_key[i].v32[1];
-    expanded_key[i].v32[1] = 
+    tmp = expanded_key->round[i].v32[1];
+    expanded_key->round[i].v32[1] = 
       U0[T4[(tmp >> 24)       ] & 0xff] ^ 
       U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ 
       U2[T4[(tmp >> 8)  & 0xff] & 0xff] ^ 
       U3[T4[(tmp)       & 0xff] & 0xff];
 
-    tmp = expanded_key[i].v32[2];
-    expanded_key[i].v32[2] = 
+    tmp = expanded_key->round[i].v32[2];
+    expanded_key->round[i].v32[2] = 
       U0[T4[(tmp >> 24)       ] & 0xff] ^ 
       U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ 
       U2[T4[(tmp >> 8)  & 0xff] & 0xff] ^ 
       U3[T4[(tmp)       & 0xff] & 0xff];
 
-    tmp = expanded_key[i].v32[3];
-    expanded_key[i].v32[3] = 
+    tmp = expanded_key->round[i].v32[3];
+    expanded_key->round[i].v32[3] = 
       U0[T4[(tmp >> 24)       ] & 0xff] ^ 
       U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ 
       U2[T4[(tmp >> 8)  & 0xff] & 0xff] ^ 
@@ -1469,33 +1556,35 @@ aes_expand_decryption_key(const v128_t *key,
 
     uint32_t c0, c1, c2, c3;
 
-    c0 = U0[aes_sbox[expanded_key[i].v8[0]]] 
-       ^ U1[aes_sbox[expanded_key[i].v8[1]]] 
-       ^ U2[aes_sbox[expanded_key[i].v8[2]]] 
-       ^ U3[aes_sbox[expanded_key[i].v8[3]]];
+    c0 = U0[aes_sbox[expanded_key->round[i].v8[0]]] 
+       ^ U1[aes_sbox[expanded_key->round[i].v8[1]]] 
+       ^ U2[aes_sbox[expanded_key->round[i].v8[2]]] 
+       ^ U3[aes_sbox[expanded_key->round[i].v8[3]]];
 
-    c1 = U0[aes_sbox[expanded_key[i].v8[4]]] 
-       ^ U1[aes_sbox[expanded_key[i].v8[5]]] 
-       ^ U2[aes_sbox[expanded_key[i].v8[6]]] 
-       ^ U3[aes_sbox[expanded_key[i].v8[7]]];
+    c1 = U0[aes_sbox[expanded_key->round[i].v8[4]]] 
+       ^ U1[aes_sbox[expanded_key->round[i].v8[5]]] 
+       ^ U2[aes_sbox[expanded_key->round[i].v8[6]]] 
+       ^ U3[aes_sbox[expanded_key->round[i].v8[7]]];
 
-    c2 = U0[aes_sbox[expanded_key[i].v8[8]]] 
-       ^ U1[aes_sbox[expanded_key[i].v8[9]]] 
-       ^ U2[aes_sbox[expanded_key[i].v8[10]]] 
-       ^ U3[aes_sbox[expanded_key[i].v8[11]]];
+    c2 = U0[aes_sbox[expanded_key->round[i].v8[8]]] 
+       ^ U1[aes_sbox[expanded_key->round[i].v8[9]]] 
+       ^ U2[aes_sbox[expanded_key->round[i].v8[10]]] 
+       ^ U3[aes_sbox[expanded_key->round[i].v8[11]]];
 
-    c3 = U0[aes_sbox[expanded_key[i].v8[12]]] 
-       ^ U1[aes_sbox[expanded_key[i].v8[13]]] 
-       ^ U2[aes_sbox[expanded_key[i].v8[14]]] 
-       ^ U3[aes_sbox[expanded_key[i].v8[15]]];
+    c3 = U0[aes_sbox[expanded_key->round[i].v8[12]]] 
+       ^ U1[aes_sbox[expanded_key->round[i].v8[13]]] 
+       ^ U2[aes_sbox[expanded_key->round[i].v8[14]]] 
+       ^ U3[aes_sbox[expanded_key->round[i].v8[15]]];
 
-    expanded_key[i].v32[0] = c0;
-    expanded_key[i].v32[1] = c1;
-    expanded_key[i].v32[2] = c2;
-    expanded_key[i].v32[3] = c3;
+    expanded_key->round[i].v32[0] = c0;
+    expanded_key->round[i].v32[1] = c1;
+    expanded_key->round[i].v32[2] = c2;
+    expanded_key->round[i].v32[3] = c3;
 
 #endif     
   }
+
+  return err_status_ok;
 }
 
 #ifdef CPU_CISC
@@ -1910,42 +1999,67 @@ aes_inv_final_round(v128_t *state, const v128_t *round_key) {
 
 
 void
-aes_encrypt(v128_t *plaintext, const aes_expanded_key_t exp_key) {
+aes_encrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key) {
 
   /* add in the subkey */
-  v128_xor_eq(plaintext, exp_key + 0);
-
-  /* now do nine rounds */
-  aes_round(plaintext, exp_key + 1);
-  aes_round(plaintext, exp_key + 2);
-  aes_round(plaintext, exp_key + 3);
-  aes_round(plaintext, exp_key + 4);
-  aes_round(plaintext, exp_key + 5);
-  aes_round(plaintext, exp_key + 6);
-  aes_round(plaintext, exp_key + 7);
-  aes_round(plaintext, exp_key + 8);  
-  aes_round(plaintext, exp_key + 9);
-  /* the last round is different */
-
- aes_final_round(plaintext, exp_key + 10);  
+  v128_xor_eq(plaintext, &exp_key->round[0]);
+
+  /* now do the rounds */
+  aes_round(plaintext, &exp_key->round[1]);
+  aes_round(plaintext, &exp_key->round[2]);
+  aes_round(plaintext, &exp_key->round[3]);
+  aes_round(plaintext, &exp_key->round[4]);
+  aes_round(plaintext, &exp_key->round[5]);
+  aes_round(plaintext, &exp_key->round[6]);
+  aes_round(plaintext, &exp_key->round[7]);
+  aes_round(plaintext, &exp_key->round[8]);  
+  aes_round(plaintext, &exp_key->round[9]);
+  if (exp_key->num_rounds == 10) {
+    aes_final_round(plaintext, &exp_key->round[10]);
+  }
+  else if (exp_key->num_rounds == 12) {
+    aes_round(plaintext, &exp_key->round[10]);  
+    aes_round(plaintext, &exp_key->round[11]);
+    aes_final_round(plaintext, &exp_key->round[12]);
+  }
+  else if (exp_key->num_rounds == 14) {
+    aes_round(plaintext, &exp_key->round[10]);  
+    aes_round(plaintext, &exp_key->round[11]);
+    aes_round(plaintext, &exp_key->round[12]);  
+    aes_round(plaintext, &exp_key->round[13]);
+    aes_final_round(plaintext, &exp_key->round[14]);  
+  }
 }
 
 void
-aes_decrypt(v128_t *plaintext, const aes_expanded_key_t exp_key) {
+aes_decrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key) {
 
   /* add in the subkey */
-  v128_xor_eq(plaintext, exp_key + 0);
-
-  /* now do nine rounds */
-  aes_inv_round(plaintext, exp_key + 1);
-  aes_inv_round(plaintext, exp_key + 2);
-  aes_inv_round(plaintext, exp_key + 3);
-  aes_inv_round(plaintext, exp_key + 4);
-  aes_inv_round(plaintext, exp_key + 5);
-  aes_inv_round(plaintext, exp_key + 6);
-  aes_inv_round(plaintext, exp_key + 7);
-  aes_inv_round(plaintext, exp_key + 8);  
-  aes_inv_round(plaintext, exp_key + 9);
-  /* the last round is different */
-  aes_inv_final_round(plaintext, exp_key + 10);  
+  v128_xor_eq(plaintext, &exp_key->round[0]);
+
+  /* now do the rounds */
+  aes_inv_round(plaintext, &exp_key->round[1]);
+  aes_inv_round(plaintext, &exp_key->round[2]);
+  aes_inv_round(plaintext, &exp_key->round[3]);
+  aes_inv_round(plaintext, &exp_key->round[4]);
+  aes_inv_round(plaintext, &exp_key->round[5]);
+  aes_inv_round(plaintext, &exp_key->round[6]);
+  aes_inv_round(plaintext, &exp_key->round[7]);
+  aes_inv_round(plaintext, &exp_key->round[8]);  
+  aes_inv_round(plaintext, &exp_key->round[9]);
+  if (exp_key->num_rounds == 10) {
+    aes_inv_final_round(plaintext, &exp_key->round[10]);  
+  }
+  else if (exp_key->num_rounds == 12) {
+    aes_inv_round(plaintext, &exp_key->round[10]);  
+    aes_inv_round(plaintext, &exp_key->round[11]);
+    aes_inv_final_round(plaintext, &exp_key->round[12]);  
+  }
+  else if (exp_key->num_rounds == 14) {
+    aes_inv_round(plaintext, &exp_key->round[10]);  
+    aes_inv_round(plaintext, &exp_key->round[11]);
+    aes_inv_round(plaintext, &exp_key->round[12]);  
+    aes_inv_round(plaintext, &exp_key->round[13]);
+    aes_inv_final_round(plaintext, &exp_key->round[14]);  
+  }
 }
index fbfce629e65460705f2099ac42ad38289e8053ff..ed33f5b01cd7de574d98541b18f69b9cadc2a959 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -63,12 +63,12 @@ aes_cbc_alloc(cipher_t **c, int key_len) {
   debug_print(mod_aes_cbc, 
              "allocating cipher with key length %d", key_len);
 
-  if (key_len != 16)
+  if (key_len != 16 && key_len != 24 && key_len != 32)
     return err_status_bad_param;
   
-  /* allocate memory a cipher of type aes_icm */
+  /* allocate memory a cipher of type aes_cbc */
   tmp = (sizeof(aes_cbc_ctx_t) + sizeof(cipher_t));
-  pointer = crypto_alloc(tmp);
+  pointer = (uint8_t*)crypto_alloc(tmp);
   if (pointer == NULL) 
     return err_status_alloc_fail;
 
@@ -104,23 +104,24 @@ aes_cbc_dealloc(cipher_t *c) {
 }
 
 err_status_t
-aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, 
+aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, int key_len,
                     cipher_direction_t dir) {
-  v128_t tmp_key;
-
-  /* set tmp_key (for alignment) */
-  v128_copy_octet_string(&tmp_key, key);
+  err_status_t status;
 
   debug_print(mod_aes_cbc, 
-             "key:  %s", v128_hex_string(&tmp_key)); 
+             "key:  %s", octet_string_hex_string(key, key_len)); 
 
   /* expand key for the appropriate direction */
   switch (dir) {
   case (direction_encrypt):
-    aes_expand_encryption_key(&tmp_key, c->expanded_key);
+    status = aes_expand_encryption_key(key, key_len, &c->expanded_key);
+    if (status)
+      return status;
     break;
   case (direction_decrypt):
-    aes_expand_decryption_key(&tmp_key, c->expanded_key);
+    status = aes_expand_decryption_key(key, key_len, &c->expanded_key);
+    if (status)
+      return status;
     break;
   default:
     return err_status_bad_param;
@@ -135,7 +136,7 @@ err_status_t
 aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) {
   int i;
 /*   v128_t *input = iv; */
-  uint8_t *input = iv;
+  uint8_t *input = (uint8_t*) iv;
  
   /* set state and 'previous' block to iv */
   for (i=0; i < 16; i++) 
@@ -181,7 +182,7 @@ aes_cbc_encrypt(aes_cbc_ctx_t *c,
     debug_print(mod_aes_cbc, "inblock:  %s", 
              v128_hex_string(&c->state));
 
-    aes_encrypt(&c->state, c->expanded_key);
+    aes_encrypt(&c->state, &c->expanded_key);
 
     debug_print(mod_aes_cbc, "outblock: %s", 
              v128_hex_string(&c->state));
@@ -236,7 +237,7 @@ aes_cbc_decrypt(aes_cbc_ctx_t *c,
              v128_hex_string(&state));
     
     /* decrypt state */
-    aes_decrypt(&state, c->expanded_key);
+    aes_decrypt(&state, &c->expanded_key);
 
     debug_print(mod_aes_cbc, "outblock: %s", 
              v128_hex_string(&state));
@@ -332,7 +333,7 @@ char
 aes_cbc_description[] = "aes cipher block chaining (cbc) mode";
 
 /*
- * Test case 0 is derived from FIPS 197 Appendix A; it uses an
+ * Test case 0 is derived from FIPS 197 Appendix C; it uses an
  * all-zero IV, so that the first block encryption matches the test
  * case in that appendix.  This property provides a check of the base
  * AES encryption and decryption algorithms; if CBC fails on some
@@ -428,6 +429,100 @@ cipher_test_case_t aes_cbc_test_case_1 = {
   &aes_cbc_test_case_0                    /* pointer to next testcase */
 };
 
+/*
+ * Test case 2 is like test case 0, but for 256-bit keys. (FIPS 197 
+ * appendix C.3).
+ */
+
+
+uint8_t aes_cbc_test_case_2_key[32] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+uint8_t aes_cbc_test_case_2_plaintext[64] =  {
+  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff 
+};
+
+uint8_t aes_cbc_test_case_2_ciphertext[80] = {
+  0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+  0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89,  
+  0x72, 0x72, 0x6e, 0xe7, 0x71, 0x39, 0xbf, 0x11,
+  0xe5, 0x40, 0xe2, 0x7c, 0x54, 0x65, 0x1d, 0xee
+};
+
+uint8_t aes_cbc_test_case_2_iv[16] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+cipher_test_case_t aes_cbc_test_case_2 = {
+  32,                                    /* octets in key            */
+  aes_cbc_test_case_2_key,               /* key                      */
+  aes_cbc_test_case_2_iv,                /* initialization vector    */
+  16,                                    /* octets in plaintext      */
+  aes_cbc_test_case_2_plaintext,         /* plaintext                */
+  32,                                    /* octets in ciphertext     */
+  aes_cbc_test_case_2_ciphertext,        /* ciphertext               */
+  &aes_cbc_test_case_1                   /* pointer to next testcase */
+};
+
+
+/*
+ * this test case is taken directly from Appendix F.2 of NIST Special
+ * Publication SP 800-38A
+ */
+
+uint8_t aes_cbc_test_case_3_key[32] = {
+  0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+  0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+  0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+  0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+};
+
+uint8_t aes_cbc_test_case_3_plaintext[64] =  {
+  0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 
+  0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+  0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 
+  0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+  0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+  0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+  0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 
+  0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+};
+
+uint8_t aes_cbc_test_case_3_ciphertext[80] = {
+  0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+  0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+  0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+  0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+  0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+  0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+  0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+  0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b,
+  0xfb, 0x98, 0x20, 0x2c, 0x45, 0xb2, 0xe4, 0xa0,
+  0x63, 0xc4, 0x68, 0xba, 0x84, 0x39, 0x16, 0x5a
+};
+
+uint8_t aes_cbc_test_case_3_iv[16] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+};
+
+cipher_test_case_t aes_cbc_test_case_3 = {
+  32,                                    /* octets in key            */
+  aes_cbc_test_case_3_key,               /* key                      */
+  aes_cbc_test_case_3_iv,                /* initialization vector    */
+  64,                                    /* octets in plaintext      */
+  aes_cbc_test_case_3_plaintext,         /* plaintext                */
+  80,                                    /* octets in ciphertext     */
+  aes_cbc_test_case_3_ciphertext,        /* ciphertext               */
+  &aes_cbc_test_case_2                    /* pointer to next testcase */
+};
+
 cipher_type_t aes_cbc = {
   (cipher_alloc_func_t)          aes_cbc_alloc,
   (cipher_dealloc_func_t)        aes_cbc_dealloc,  
@@ -437,8 +532,9 @@ cipher_type_t aes_cbc = {
   (cipher_set_iv_func_t)         aes_cbc_set_iv,
   (char *)                       aes_cbc_description,
   (int)                          0,   /* instance count */
-  (cipher_test_case_t *)        &aes_cbc_test_case_0,
-  (debug_module_t *)            &mod_aes_cbc
+  (cipher_test_case_t *)        &aes_cbc_test_case_3,
+  (debug_module_t *)            &mod_aes_cbc,
+  (cipher_type_id_t)             AES_CBC
 };
 
 
index 152e4c93b70f758d1f384d2c6483ec7ad0e76e19..1f9bcbd97cf3eef952f6e3feb6fbc91f1124dc96 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -49,9 +49,6 @@
 #include "aes_icm.h"
 #include "alloc.h"
 
-#ifdef _MSC_VER
-#pragma warning(disable:4100)
-#endif
 
 debug_module_t mod_aes_icm = {
   0,                 /* debugging is off by default */
@@ -98,21 +95,24 @@ aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp) {
   uint8_t *pointer;
   int tmp;
 
-  debug_print(mod_aes_icm, "allocating cipher with key length %d", key_len);
-
-  /* Ismacryp, for example, uses 16 byte key + 8 byte 
-        salt  so this function is called with key_len = 24.
-        The check for key_len = 30 does not apply. Our usage
-        of aes functions with key_len = values other than 30
-        has not broken anything. Don't know what would be the
-        effect of skipping this check for srtp in general.
-  */
-  if (!forIsmacryp && key_len != 30)
+  debug_print(mod_aes_icm, 
+            "allocating cipher with key length %d", key_len);
+
+  /*
+   * Ismacryp, for example, uses 16 byte key + 8 byte 
+   * salt  so this function is called with key_len = 24.
+   * The check for key_len = 30/38/46 does not apply. Our usage
+   * of aes functions with key_len = values other than 30
+   * has not broken anything. Don't know what would be the
+   * effect of skipping this check for srtp in general.
+   */
+  if (!(forIsmacryp && key_len > 16 && key_len < 30) &&
+      key_len != 30 && key_len != 38 && key_len != 46)
     return err_status_bad_param;
 
   /* allocate memory a cipher of type aes_icm */
   tmp = (sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
-  pointer = crypto_alloc(tmp);
+  pointer = (uint8_t*)crypto_alloc(tmp);
   if (pointer == NULL) 
     return err_status_alloc_fail;
 
@@ -163,30 +163,38 @@ aes_icm_dealloc(cipher_t *c) {
  */
 
 err_status_t
-aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key) {
-  v128_t tmp_key;
+aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key, int key_len) {
+  err_status_t status;
+  int base_key_len;
+
+  if (key_len > 16 && key_len < 30) /* Ismacryp */
+    base_key_len = 16;
+  else if (key_len == 30 || key_len == 38 || key_len == 46)
+    base_key_len = key_len - 14;
+  else
+    return err_status_bad_param;
 
   /* set counter and initial values to 'offset' value */
-  /* FIX!!! this assumes the salt is at key + 16, and thus that the */
-  /* FIX!!! cipher key length is 16!  Also note this copies past the
-            end of the 'key' array by 2 bytes! */
-  v128_copy_octet_string(&c->counter, key + 16);
-  v128_copy_octet_string(&c->offset, key + 16);
+  /* Note this copies past the end of the 'key' array by 2 bytes! */
+  v128_copy_octet_string(&c->counter, key + base_key_len);
+  v128_copy_octet_string(&c->offset, key + base_key_len);
 
   /* force last two octets of the offset to zero (for srtp compatibility) */
   c->offset.v8[14] = c->offset.v8[15] = 0;
   c->counter.v8[14] = c->counter.v8[15] = 0;
   
-  /* set tmp_key (for alignment) */
-  v128_copy_octet_string(&tmp_key, key);
-
   debug_print(mod_aes_icm, 
-             "key:  %s", v128_hex_string(&tmp_key)); 
+             "key:  %s", octet_string_hex_string(key, base_key_len)); 
   debug_print(mod_aes_icm, 
              "offset: %s", v128_hex_string(&c->offset)); 
 
   /* expand key */
-  aes_expand_encryption_key(&tmp_key, c->expanded_key);
+  status = aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
+  if (status) {
+    v128_set_to_zero(&c->counter);
+    v128_set_to_zero(&c->offset);
+    return status;
+  }
 
   /* indicate that the keystream_buffer is empty */
   c->bytes_in_buffer = 0;
@@ -232,7 +240,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
   /* fill keystream buffer, if needed */
   if (tail_num) {
     v128_copy(&c->keystream_buffer, &c->counter);
-    aes_encrypt(&c->keystream_buffer, c->expanded_key);
+    aes_encrypt(&c->keystream_buffer, &c->expanded_key);
     c->bytes_in_buffer = sizeof(v128_t);
 
     debug_print(mod_aes_icm, "counter:    %s", 
@@ -259,7 +267,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
 
 err_status_t
 aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
-  v128_t *nonce = iv;
+  v128_t *nonce = (v128_t *) iv;
 
   debug_print(mod_aes_icm, 
              "setting iv: %s", v128_hex_string(nonce)); 
@@ -284,11 +292,11 @@ aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
  * this is an internal, hopefully inlined function
  */
   
-inline void
+static inline void
 aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
   /* fill buffer with new keystream */
   v128_copy(&c->keystream_buffer, &c->counter);
-  aes_encrypt(&c->keystream_buffer, c->expanded_key);
+  aes_encrypt(&c->keystream_buffer, &c->expanded_key);
   c->bytes_in_buffer = sizeof(v128_t);
 
   debug_print(mod_aes_icm, "counter:    %s", 
@@ -300,7 +308,7 @@ aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
 
   if (forIsmacryp) {
     uint32_t temp;    
-    /* alex's clock counter forward */
+    //alex's clock counter forward
     temp = ntohl(c->counter.v32[3]);
     c->counter.v32[3] = htonl(++temp);
   } else {
@@ -309,7 +317,7 @@ aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
   }
 }
 
-inline void aes_icm_advance(aes_icm_ctx_t *c) {
+static inline void aes_icm_advance(aes_icm_ctx_t *c) {
   aes_icm_advance_ismacryp(c, 0);
 }
 
@@ -341,7 +349,7 @@ aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
 
  debug_print(mod_aes_icm, "block index: %d", 
            htons(c->counter.v16[7]));
-  if (bytes_to_encr <= c->bytes_in_buffer) {
+  if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
     
     /* deal with odd case of small bytes_to_encr */
     for (i = (sizeof(v128_t) - c->bytes_in_buffer);
@@ -370,7 +378,7 @@ aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
   for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
 
     /* fill buffer with new keystream */
-    aes_icm_advance_ismacryp(c, (uint8_t)forIsmacryp);
+    aes_icm_advance_ismacryp(c, forIsmacryp);
 
     /*
      * add keystream into the data buffer (this would be a lot faster
@@ -418,7 +426,7 @@ aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
   if ((bytes_to_encr & 0xf) != 0) {
     
     /* fill buffer with new keystream */
-    aes_icm_advance_ismacryp(c, (uint8_t)forIsmacryp);
+    aes_icm_advance_ismacryp(c, forIsmacryp);
     
     for (i=0; i < (bytes_to_encr & 0xf); i++)
       *buf++ ^= c->keystream_buffer.v8[i];
@@ -492,6 +500,46 @@ cipher_test_case_t aes_icm_test_case_0 = {
   NULL                                   /* pointer to next testcase */
 };
 
+uint8_t aes_icm_test_case_1_key[46] = {
+  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
+};
+
+uint8_t aes_icm_test_case_1_nonce[16] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+uint8_t aes_icm_test_case_1_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, 
+};
+
+uint8_t aes_icm_test_case_1_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
+};
+
+cipher_test_case_t aes_icm_test_case_1 = {
+  46,                                    /* octets in key            */
+  aes_icm_test_case_1_key,               /* key                      */
+  aes_icm_test_case_1_nonce,             /* packet index             */
+  32,                                    /* octets in plaintext      */
+  aes_icm_test_case_1_plaintext,         /* plaintext                */
+  32,                                    /* octets in ciphertext     */
+  aes_icm_test_case_1_ciphertext,        /* ciphertext               */
+  &aes_icm_test_case_0                   /* pointer to next testcase */
+};
+
+
 
 /*
  * note: the encrypt function is identical to the decrypt function
@@ -506,7 +554,8 @@ cipher_type_t aes_icm = {
   (cipher_set_iv_func_t)         aes_icm_set_iv,
   (char *)                       aes_icm_description,
   (int)                          0,   /* instance count */
-  (cipher_test_case_t *)        &aes_icm_test_case_0,
-  (debug_module_t *)            &mod_aes_icm
+  (cipher_test_case_t *)        &aes_icm_test_case_1,
+  (debug_module_t *)            &mod_aes_icm,
+  (cipher_type_id_t)             AES_ICM
 };
 
index 761918bf5bbbe593828fa887dce4289c49ef87d3..27da651c7204111460c448cc5852c6614de4749f 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -71,8 +71,8 @@ cipher_get_key_length(const cipher_t *c) {
 }
 
 /* 
- * cipher_type_self_test(ct) tests a cipher of type ct against test cases
- * provided in an array of values of key, salt, xtd_seq_num_t,
+ * cipher_type_test(ct, test_data) tests a cipher of type ct against
+ * test cases provided in a list test_data of values of key, salt, iv,
  * plaintext, and ciphertext that is known to be good
  */
 
@@ -81,8 +81,8 @@ cipher_get_key_length(const cipher_t *c) {
 #define MAX_KEY_LEN          64
 
 err_status_t
-cipher_type_self_test(const cipher_type_t *ct) {
-  const cipher_test_case_t *test_case = ct->test_data;
+cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
+  const cipher_test_case_t *test_case = test_data;
   cipher_t *c;
   err_status_t status;
   uint8_t buffer[SELF_TEST_BUF_OCTETS];
@@ -155,7 +155,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
                                     test_case->ciphertext_length_octets));
 
     /* compare the resulting ciphertext with that in the test case */
-    if ((int)len != test_case->ciphertext_length_octets)
+    if (len != test_case->ciphertext_length_octets)
       return err_status_algo_fail;
     status = err_status_ok;
     for (i=0; i < test_case->ciphertext_length_octets; i++)
@@ -222,7 +222,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
                                     test_case->plaintext_length_octets));
 
     /* compare the resulting plaintext with that in the test case */
-    if ((int)len != test_case->plaintext_length_octets)
+    if (len != test_case->plaintext_length_octets)
       return err_status_algo_fail;
     status = err_status_ok;
     for (i=0; i < test_case->plaintext_length_octets; i++)
@@ -260,7 +260,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
   /* now run some random invertibility tests */
 
   /* allocate cipher, using paramaters from the first test case */
-  test_case = ct->test_data;
+  test_case = test_data;
   status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
   if (status)
       return status;
@@ -344,7 +344,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
                octet_string_hex_string(buffer, length));    
 
     /* compare the resulting plaintext with the original one */
-    if ((int)length != plaintext_len)
+    if (length != plaintext_len)
       return err_status_algo_fail;
     status = err_status_ok;
     for (i=0; i < plaintext_len; i++)
@@ -360,10 +360,24 @@ cipher_type_self_test(const cipher_type_t *ct) {
         
   }
 
+  status = cipher_dealloc(c);
+  if (status)
+    return status;
+
   return err_status_ok;
 }
 
 
+/* 
+ * cipher_type_self_test(ct) performs cipher_type_test on ct's internal
+ * list of test data.
+ */
+
+err_status_t
+cipher_type_self_test(const cipher_type_t *ct) {
+  return cipher_type_test(ct, ct->test_data);
+}
+
 /*
  * cipher_bits_per_second(c, l, t) computes (an estimate of) the
  * number of bits that a cipher implementation can encrypt in a second
@@ -383,7 +397,7 @@ cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) {
   unsigned char *enc_buf;
   unsigned int len = octets_in_buffer;
 
-  enc_buf = crypto_alloc(octets_in_buffer);
+  enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer);
   if (enc_buf == NULL)
     return 0;  /* indicate bad parameters by returning null */
   
index 988f6a56afac044bb04b7e9a49af828148e57466..724f4df3a897ac89f463421e523e78a0749fa16b 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 #include "null_cipher.h"
 #include "alloc.h"
 
-#ifdef _MSC_VER
-#pragma warning(disable:4100)
-#endif
-
 /* the null_cipher uses the cipher debug module  */
 
 extern debug_module_t mod_cipher;
@@ -65,7 +61,7 @@ null_cipher_alloc(cipher_t **c, int key_len) {
              "allocating cipher with key length %d", key_len);
 
   /* allocate memory a cipher of type null_cipher */
-  pointer = crypto_alloc(sizeof(null_cipher_ctx_t) + sizeof(cipher_t));
+  pointer = (uint8_t*)crypto_alloc(sizeof(null_cipher_ctx_t) + sizeof(cipher_t));
   if (pointer == NULL)
     return err_status_alloc_fail;
 
@@ -103,7 +99,7 @@ null_cipher_dealloc(cipher_t *c) {
 }
 
 err_status_t
-null_cipher_init(null_cipher_ctx_t *ctx, const uint8_t *key) {
+null_cipher_init(null_cipher_ctx_t *ctx, const uint8_t *key, int key_len) {
 
   debug_print(mod_cipher, "initializing null cipher", NULL);
 
@@ -151,6 +147,7 @@ cipher_type_t null_cipher = {
   (char *)                      null_cipher_description,
   (int)                         0,
   (cipher_test_case_t *)       &null_cipher_test_0,
-  (debug_module_t *)            NULL
+  (debug_module_t *)            NULL,
+  (cipher_type_id_t)            NULL_CIPHER
 };
 
index 2773c16cc396f534171586dc735b5228d4c87232..aaf0269c71c5b35586589d79b9e904735925c477 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -74,8 +74,8 @@ auth_type_get_ref_count(const auth_type_t *at) {
 }
 
 /*
- * auth_type_self_test() tests an auth function of type ct against
- * test cases provided in an array of values of key, data, and tag
+ * auth_type_test() tests an auth function of type ct against
+ * test cases provided in a list test_data of values of key, data, and tag
  * that is known to be good
  */
 
@@ -83,8 +83,8 @@ auth_type_get_ref_count(const auth_type_t *at) {
 #define SELF_TEST_TAG_BUF_OCTETS 32
 
 err_status_t
-auth_type_self_test(const auth_type_t *at) {
-  auth_test_case_t *test_case = at->test_data;
+auth_type_test(const auth_type_t *at, const auth_test_case_t *test_data) {
+  const auth_test_case_t *test_case = test_data;
   auth_t *a;
   err_status_t status;
   uint8_t tag[SELF_TEST_TAG_BUF_OCTETS];
@@ -171,3 +171,13 @@ auth_type_self_test(const auth_type_t *at) {
 }
 
 
+/* 
+ * auth_type_self_test(at) performs auth_type_test on at's internal
+ * list of test data.
+ */
+
+err_status_t
+auth_type_self_test(const auth_type_t *at) {
+  return auth_type_test(at, at->test_data);
+}
+
index a786523c50a0826d63640831d49a2195fc547ac3..4f389fe18e236ecfc92d07f6ef04c3ccbee7c9c2 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,6 @@ err_status_t
 hmac_alloc(auth_t **a, int key_len, int out_len) {
   extern auth_type_t hmac;
   uint8_t *pointer;
-  hmac_ctx_t *new_hmac_ctx;
 
   debug_print(mod_hmac, "allocating auth func with key length %d", key_len);
   debug_print(mod_hmac, "                          tag length %d", out_len);
@@ -74,7 +73,7 @@ hmac_alloc(auth_t **a, int key_len, int out_len) {
     return err_status_bad_param;
 
   /* allocate memory for auth and hmac_ctx_t structures */
-  pointer = crypto_alloc(sizeof(hmac_ctx_t) + sizeof(auth_t));
+  pointer = (uint8_t*)crypto_alloc(sizeof(hmac_ctx_t) + sizeof(auth_t));
   if (pointer == NULL)
     return err_status_alloc_fail;
 
@@ -85,7 +84,6 @@ hmac_alloc(auth_t **a, int key_len, int out_len) {
   (*a)->out_len = out_len;
   (*a)->key_len = key_len;
   (*a)->prefix_len = 0;
-  new_hmac_ctx = (hmac_ctx_t *)((*a)->state);
 
   /* increment global count of all hmac uses */
   hmac.ref_count++;
@@ -180,7 +178,7 @@ hmac_compute(hmac_ctx_t *state, const void *message,
     return err_status_bad_param;
   
   /* hash message, copy output into H */
-  hmac_update(state, message, msg_octets);
+  hmac_update(state, (const uint8_t*)message, msg_octets);
   sha1_final(&state->ctx, H);
 
   /*
@@ -264,6 +262,7 @@ hmac  = {
   (char *)               hmac_description,
   (int)                  0,  /* instance count */
   (auth_test_case_t *)  &hmac_test_case_0,
-  (debug_module_t *)    &mod_hmac
+  (debug_module_t *)    &mod_hmac,
+  (auth_type_id_t)       HMAC_SHA1
 };
 
index 1d8c556310581d527913d98b45023398c7f15f95..103444bc5309819a37f65d314586d6e2797bf105 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 #include "null_auth.h" 
 #include "alloc.h"
 
-#ifdef _MSC_VER
-#pragma warning(disable:4100)
-#endif
-
 /* null_auth uses the auth debug module */
 
 extern debug_module_t mod_auth;
@@ -65,7 +61,7 @@ null_auth_alloc(auth_t **a, int key_len, int out_len) {
   debug_print(mod_auth, "                          tag length %d", out_len);
 
   /* allocate memory for auth and null_auth_ctx_t structures */
-  pointer = crypto_alloc(sizeof(null_auth_ctx_t) + sizeof(auth_t));
+  pointer = (uint8_t*)crypto_alloc(sizeof(null_auth_ctx_t) + sizeof(auth_t));
   if (pointer == NULL)
     return err_status_alloc_fail;
 
@@ -159,6 +155,8 @@ null_auth  = {
   (auth_start_func)      null_auth_start,
   (char *)               null_auth_description,
   (int)                  0,  /* instance count */
-  (auth_test_case_t *)   &null_auth_test_case_0
+  (auth_test_case_t *)   &null_auth_test_case_0,
+  (debug_module_t *)     NULL,
+  (auth_type_id_t)       NULL_AUTH
 };
 
index d4eba3cc262ae8f70d5c0155cd592d589cca264b..b9a8d10509820af29f5121321cf8a9966883a35e 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -114,7 +114,7 @@ sha1_core(const uint32_t M[16], uint32_t hash_value[5]) {
   H4 = hash_value[4];
 
   /* copy/xor message into array */
-    
+
   W[0]  = be32_to_cpu(M[0]);
   W[1]  = be32_to_cpu(M[1]);
   W[2]  = be32_to_cpu(M[2]);
@@ -184,7 +184,7 @@ sha1_core(const uint32_t M[16], uint32_t hash_value[5]) {
 
 void
 sha1_init(sha1_ctx_t *ctx) {
+
   /* initialize state vector */
   ctx->H[0] = 0x67452301;
   ctx->H[1] = 0xefcdab89;
@@ -210,7 +210,7 @@ sha1_update(sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_msg) {
 
   /* loop over 16-word blocks of M */
   while (octets_in_msg > 0) {
-    
+
     if (octets_in_msg + ctx->octets_in_buffer >= 64) {
 
       /* 
@@ -260,7 +260,7 @@ sha1_final(sha1_ctx_t *ctx, uint32_t *output) {
    */
   {
     int tail = ctx->octets_in_buffer % 4;
-    
+
     /* copy/xor message into array */
     for (i=0; i < (ctx->octets_in_buffer+3)/4; i++) 
       W[i]  = be32_to_cpu(ctx->M[i]);
@@ -283,7 +283,7 @@ sha1_final(sha1_ctx_t *ctx, uint32_t *output) {
       W[i] = 0x80000000;
       break;
     }
-    
+
     /* zeroize remaining words */
     for (i++   ; i < 15; i++)
       W[i] = 0x0;
@@ -299,7 +299,8 @@ sha1_final(sha1_ctx_t *ctx, uint32_t *output) {
     else if (ctx->octets_in_buffer < 60)
       W[15] = 0x0;
 
-    /* process the word array */    for (t=16; t < 80; t++) {
+    /* process the word array */
+    for (t=16; t < 80; t++) {
       TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
       W[t] = S1(TEMP);
     }
diff --git a/libs/srtp/crypto/include/.cvsignore b/libs/srtp/crypto/include/.cvsignore
new file mode 100644 (file)
index 0000000..0e56cf2
--- /dev/null
@@ -0,0 +1 @@
+config.h
index e59fdadb776e5186922bfa458f54b3e19dc39e6f..288133743fce1b1c84f18fde0822d7a9acec0768 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 
 #include "datatypes.h"
 #include "gf2_8.h"
+#include "err.h"
 
 /* aes internals */
 
-typedef v128_t aes_expanded_key_t[11];
+typedef struct {
+  v128_t round[15];
+  int num_rounds;
+} aes_expanded_key_t;
 
-void
-aes_expand_encryption_key(const v128_t *key,
-                         aes_expanded_key_t expanded_key);
+err_status_t
+aes_expand_encryption_key(const uint8_t *key,
+                         int key_len,
+                         aes_expanded_key_t *expanded_key);
 
-void
-aes_expand_decryption_key(const v128_t *key,
-                         aes_expanded_key_t expanded_key);
+err_status_t
+aes_expand_decryption_key(const uint8_t *key,
+                         int key_len,
+                         aes_expanded_key_t *expanded_key);
 
 void
-aes_encrypt(v128_t *plaintext, const aes_expanded_key_t exp_key);
+aes_encrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key);
 
 void
-aes_decrypt(v128_t *plaintext, const aes_expanded_key_t exp_key);
+aes_decrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key);
 
 #if 0
 /*
index 9fb6682bd0dc77c7fe1b34776d05b3395e5629a2..bc4e41a4c193c7f1af407667f6be653f6da56cde 100644 (file)
@@ -31,7 +31,7 @@ aes_cbc_encrypt(aes_cbc_ctx_t *c,
 
 err_status_t
 aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, 
-                    cipher_direction_t dir);
+                    int key_len, cipher_direction_t dir);
 
 err_status_t
 aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv);
index 67f2359315614b2079d6ca44ace980c1e46e6b92..dac0cdccc662b3a7581f6e36b7bcb2122c19e89b 100644 (file)
@@ -19,13 +19,14 @@ typedef struct {
   v128_t   offset;                 /* initial offset value             */
   v128_t   keystream_buffer;       /* buffers bytes of keystream       */
   aes_expanded_key_t expanded_key; /* the cipher key                   */
-  unsigned int      bytes_in_buffer;        /* number of unused bytes in buffer */
+  int      bytes_in_buffer;        /* number of unused bytes in buffer */
 } aes_icm_ctx_t;
 
 
 err_status_t
 aes_icm_context_init(aes_icm_ctx_t *c,
-                    const unsigned char *key); 
+                    const unsigned char *key,
+                    int key_len); 
 
 err_status_t
 aes_icm_set_iv(aes_icm_ctx_t *c, void *iv);
index 5eb508c719236969906e1617aef8474ec3dbe087..5980eed6c13c6be2c43be308cc3e9d8a81676386 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 6e32480daa0d8e8782d8d69ad5ea3baca75e9e78..5b5e4b21d470fedd5a5f106a56fd2639a9d12e13 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,8 @@
 
 #include "datatypes.h"          
 #include "err.h"                /* error codes    */
+#include "crypto.h"            /* for auth_type_id_t */
+#include "crypto_types.h"      /* for values of auth_type_id_t */
 
 typedef struct auth_type_t *auth_type_pointer;
 typedef struct auth_t      *auth_pointer_t;
@@ -129,6 +131,7 @@ typedef struct auth_type_t {
   int                  ref_count;
   auth_test_case_t    *test_data;
   debug_module_t      *debug;
+  auth_type_id_t       id;
 } auth_type_t;
 
 typedef struct auth_t {
@@ -148,6 +151,15 @@ typedef struct auth_t {
 err_status_t
 auth_type_self_test(const auth_type_t *at);
 
+/* 
+ * auth_type_test() tests an auth_type against external test cases
+ * provided in an array of values of key/message/tag that is known to
+ * be good
+ */
+
+err_status_t
+auth_type_test(const auth_type_t *at, const auth_test_case_t *test_data);
+
 /*
  * auth_type_get_ref_count(at) returns the reference count (the number
  * of instantiations) of the auth_type_t at
index 5c37c38413a0d614817b46c39f5d4dc110fb0598..eff6dd154b63ee2fccdcae25b442aabe6dd17993 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -49,6 +49,8 @@
 #include "datatypes.h"          
 #include "rdbx.h"               /* for xtd_seq_num_t */
 #include "err.h"                /* for error codes  */
+#include "crypto.h"            /* for cipher_type_id_t */
+#include "crypto_types.h"      /* for values of cipher_type_id_t */
 
 
 /**
@@ -86,7 +88,7 @@ typedef err_status_t (*cipher_alloc_func_t)
  */
 
 typedef err_status_t (*cipher_init_func_t)
-  (void *state, const uint8_t *key, cipher_direction_t dir);
+(void *state, const uint8_t *key, int key_len, cipher_direction_t dir);
 
 /* a cipher_dealloc_func_t de-allocates a cipher_t */
 
@@ -108,8 +110,7 @@ typedef err_status_t (*cipher_decrypt_func_t)
      (void *state, uint8_t *buffer, unsigned int *octets_to_decrypt);
 
 /* 
- * a cipher_set_nonce_seq_func_t function sets both the nonce
- * and the extended sequence number
+ * a cipher_set_iv_func_t function sets the current initialization vector
  */
 
 typedef err_status_t (*cipher_set_iv_func_t)
@@ -147,6 +148,7 @@ typedef struct cipher_type_t {
   int                         ref_count;
   cipher_test_case_t         *test_data;
   debug_module_t             *debug;
+  cipher_type_id_t            id;
 } cipher_type_t;
 
 /*
@@ -169,7 +171,7 @@ typedef struct cipher_t {
 
 #define cipher_dealloc(c) (((c)->type)->dealloc(c))
 
-#define cipher_init(c, k, dir) (((c)->type)->init(((c)->state), (k), (dir)))
+#define cipher_init(c, k, dir) (((c)->type)->init(((c)->state), (k), ((c)->key_len), (dir)))
 
 #define cipher_encrypt(c, buf, len) \
         (((c)->type)->encrypt(((c)->state), (buf), (len)))
@@ -178,7 +180,7 @@ typedef struct cipher_t {
         (((c)->type)->decrypt(((c)->state), (buf), (len)))
 
 #define cipher_set_iv(c, n)                           \
-  ((c) ? (((c)->type)->set_iv(((c)->state), (n))) :   \
+  ((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)->state), (n))) :   \
                                 err_status_no_such_op)  
 
 err_status_t
@@ -201,6 +203,16 @@ err_status_t
 cipher_type_self_test(const cipher_type_t *ct);
 
 
+/* 
+ * cipher_type_test() tests a cipher against external test cases provided in 
+ * an array of values of key/xtd_seq_num_t/plaintext/ciphertext 
+ * that is known to be good
+ */
+
+err_status_t
+cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data);
+
+
 /*
  * cipher_bits_per_second(c, l, t) computes (and estimate of) the
  * number of bits that a cipher implementation can encrypt in a second
index dc52821e4340da05f1a556f7a3af9d9d092e6247..0e9667da57b062193191573e20cd181b6ebbf089 100644 (file)
 #ifndef CRYPTO_H
 #define CRYPTO_H
 
-#include "crypto_kernel.h"
+/** 
+ *  @brief A cipher_type_id_t is an identifier for a particular cipher
+ *  type.
+ *
+ *  A cipher_type_id_t is an integer that represents a particular
+ *  cipher type, e.g. the Advanced Encryption Standard (AES).  A
+ *  NULL_CIPHER is avaliable; this cipher leaves the data unchanged,
+ *  and can be selected to indicate that no encryption is to take
+ *  place.
+ * 
+ *  @ingroup Ciphers
+ */
+typedef uint32_t cipher_type_id_t; 
+
+/**
+ *  @brief An auth_type_id_t is an identifier for a particular authentication
+ *   function.
+ *
+ *  An auth_type_id_t is an integer that represents a particular
+ *  authentication function type, e.g. HMAC-SHA1.  A NULL_AUTH is
+ *  avaliable; this authentication function performs no computation,
+ *  and can be selected to indicate that no authentication is to take
+ *  place.
+ *  
+ *  @ingroup Authentication
+ */
+typedef uint32_t auth_type_id_t;
 
 #endif /* CRYPTO_H */
 
index 029f1c885af9b60fc2c54a5e669bf125792037a5..1acf4978d0ea4b0f5e73c90319fdd99a9ea7e77f 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,7 @@
 #include "err.h"
 #include "crypto_types.h"
 #include "key.h"
-
+#include "crypto.h"
 
 /*
  * crypto_kernel_state_t defines the possible states:
@@ -69,36 +69,6 @@ typedef enum {
   crypto_kernel_state_secure
 } crypto_kernel_state_t;
 
-
-/** 
- *  @brief A cipher_type_id_t is an identifier for a particular cipher
- *  type.
- *
- *  A cipher_type_id_t is an integer that represents a particular
- *  cipher type, e.g. the Advanced Encryption Standard (AES).  A
- *  NULL_CIPHER is avaliable; this cipher leaves the data unchanged,
- *  and can be selected to indicate that no encryption is to take
- *  place.
- * 
- *  @ingroup Ciphers
- */
-typedef uint32_t cipher_type_id_t; 
-
-/**
- *  @brief An auth_type_id_t is an identifier for a particular authentication
- *   function.
- *
- *  An auth_type_id_t is an integer that represents a particular
- *  authentication function type, e.g. HMAC-SHA1.  A NULL_AUTH is
- *  avaliable; this authentication function performs no computation,
- *  and can be selected to indicate that no authentication is to take
- *  place.
- *  
- *  @ingroup Authentication
- */
-typedef uint32_t auth_type_id_t;
-
-
 /* 
  * linked list of cipher types 
  */
@@ -212,6 +182,28 @@ crypto_kernel_load_cipher_type(cipher_type_t *ct, cipher_type_id_t id);
 err_status_t
 crypto_kernel_load_auth_type(auth_type_t *ct, auth_type_id_t id);
 
+/*
+ * crypto_kernel_replace_cipher_type(ct, id)
+ * 
+ * replaces the crypto kernel's existing cipher for the cipher_type id
+ * with a new one passed in externally.  The new cipher must pass all the
+ * existing cipher_type's self tests as well as its own.
+ */
+err_status_t
+crypto_kernel_replace_cipher_type(cipher_type_t *ct, cipher_type_id_t id);
+
+
+/*
+ * crypto_kernel_replace_auth_type(ct, id)
+ * 
+ * replaces the crypto kernel's existing cipher for the auth_type id
+ * with a new one passed in externally.  The new auth type must pass all the
+ * existing auth_type's self tests as well as its own.
+ */
+err_status_t
+crypto_kernel_replace_auth_type(auth_type_t *ct, auth_type_id_t id);
+
+
 err_status_t
 crypto_kernel_load_debug_module(debug_module_t *new_dm);
 
index be6558f638109b52ebbabacf533dc2dd399688b4..52f083721d07f5e4464cbb0c55198b33e5020cb6 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -233,40 +233,6 @@ void
 octet_string_set_to_zero(uint8_t *s, int len);
 
 
-/*
- * functions manipulating bit_vector_t 
- *
- * A bitvector_t consists of an array of words and an integer
- * representing the number of significant bits stored in the array.
- * The bits are packed as follows: the least significant bit is that
- * of word[0], while the most significant bit is the nth most
- * significant bit of word[m], where length = bits_per_word * m + n.
- * 
- */
-
-#define bits_per_word  32
-#define bytes_per_word 4
-
-typedef struct {
-  uint32_t length;   
-  uint32_t *word;
-} bitvector_t;
-
-int
-bitvector_alloc(bitvector_t *v, unsigned long length);
-
-void
-bitvector_set_bit(bitvector_t *v, int bit_index);
-
-int
-bitvector_get_bit(const bitvector_t *v, int bit_index);
-
-int
-bitvector_print_hex(const bitvector_t *v, FILE *stream);
-
-int
-bitvector_set_from_hex(bitvector_t *v, char *string);
-
 #endif /* MATH_H */
 
 
index e20c7715b07c19293599d000e9d4f7ed0cd8f017..35317108c3ffec1d991bfc5f6d8b6b019460430e 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 #define NULL_CIPHER        0            
 
 /** 
- * @brief AES-128 Integer Counter Mode (AES ICM)             
+ * @brief AES Integer Counter Mode (AES ICM)             
  *
- * AES-128 ICM is the variant of counter mode that is used by Secure RTP.  
- * This cipher uses a 16-octet key and a 30-octet offset (or salt) value.
+ * AES ICM is the variant of counter mode that is used by Secure RTP.  
+ * This cipher uses a 16-, 24-, or 32-octet key concatenated with a
+ * 14-octet offset (or salt) value.
+ */
+#define AES_ICM            1            
+
+/** 
+ * @brief AES-128 Integer Counter Mode (AES ICM)             
+ * AES-128 ICM is a deprecated alternate name for AES ICM.
  */
-#define AES_128_ICM        1            
+#define AES_128_ICM        AES_ICM
 
 /**
  * @brief SEAL 3.0 
 #define SEAL               2            
 
 /** 
- * @brief AES-128 Integer Counter Mode (AES ICM)             
+ * @brief AES Cipher Block Chaining mode (AES CBC)             
+ *
+ * AES CBC is the AES Cipher Block Chaining mode.
+ * This cipher uses a 16-, 24-, or 32-octet key.
+ */
+#define AES_CBC            3            
+
+/** 
+ * @brief AES-128 Cipher Block Chaining mode (AES CBC)             
  *
- * AES-128 ICM is the variant of counter mode that is used by Secure RTP.  
- * This cipher uses a 16-octet key and a 30-octet offset (or salt) value.
+ * AES-128 CBC is a deprecated alternate name for AES CBC.
  */
-#define AES_128_CBC        3            
+#define AES_128_CBC        AES_CBC            
 
 /**
  * @brief Strongest available cipher.
  *
  * This identifier resolves to the strongest cipher type available.
  */
-#define STRONGHOLD_CIPHER  AES_128_ICM  
+#define STRONGHOLD_CIPHER  AES_ICM  
 
 /**
  * @}
index 9024a71117b742b25de9ba503dfb1c4d7cd4b90f..d9f0441e0ebf79257a306cba9d50141550b83ddd 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 17b531beb6a4a869e1998c745ffdb11c4fa0abf3..e16d895bb5927be395e2505924f77179c0c0c49d 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,7 @@
 # endif
 #endif
 
+
 /* if DATATYPES_USE_MACROS is defined, then little functions are macros */
 #define DATATYPES_USE_MACROS  
 
@@ -154,10 +155,10 @@ void
 v128_copy_octet_string(v128_t *x, const uint8_t s[16]);
 
 void
-v128_left_shift(v128_t *x, int index);
+v128_left_shift(v128_t *x, int shift_index);
 
 void
-v128_right_shift(v128_t *x, int index);
+v128_right_shift(v128_t *x, int shift_index);
 
 /*
  * the following macros define the data manipulation functions
@@ -313,7 +314,7 @@ v128_right_shift(v128_t *x, int index);
 
 
 #ifdef DATATYPES_USE_MACROS  /* little functions are really macros */
-
+   
 #define v128_set_to_zero(z)       _v128_set_to_zero(z)
 #define v128_copy(z, x)           _v128_copy(z, x)
 #define v128_xor(z, x, y)         _v128_xor(z, x, y)
@@ -392,22 +393,114 @@ octet_string_set_to_zero(uint8_t *s, int len);
 # define be64_to_cpu(x)        bswap_64((x))
 #else
 
+#if defined(__GNUC__) && defined(HAVE_X86)
+/* Fall back. */
+static inline uint32_t be32_to_cpu(uint32_t v) {
+   /* optimized for x86. */
+   asm("bswap %0" : "=r" (v) : "0" (v));
+   return v;
+}
+# else /* HAVE_X86 */
 #  ifdef HAVE_NETINET_IN_H
 #   include <netinet/in.h>
 #  elif defined HAVE_WINSOCK2_H
 #   include <winsock2.h>
 #  endif
 #  define be32_to_cpu(x)       ntohl((x))
+# endif /* HAVE_X86 */
 
+static inline uint64_t be64_to_cpu(uint64_t v) {
 # ifdef NO_64BIT_MATH
    /* use the make64 functions to do 64-bit math */
-#  define be64_to_cpu(v) (make64(htonl(low32(v)),htonl(high32(v))))
+   v = make64(htonl(low32(v)),htonl(high32(v)));
 # else
-#  define be64_to_cpu(v) ((ntohl((uint32_t)(v >> 32))) | (((uint64_t)ntohl((uint32_t)v)) << 32))
+   /* use the native 64-bit math */
+   v= (uint64_t)((be32_to_cpu((uint32_t)(v >> 32))) | (((uint64_t)be32_to_cpu((uint32_t)v)) << 32));
 # endif
+   return v;
+}
 
 #endif /* ! SRTP_KERNEL_LINUX */
 
 #endif /* WORDS_BIGENDIAN */
 
+/*
+ * functions manipulating bitvector_t 
+ *
+ * A bitvector_t consists of an array of words and an integer
+ * representing the number of significant bits stored in the array.
+ * The bits are packed as follows: the least significant bit is that
+ * of word[0], while the most significant bit is the nth most
+ * significant bit of word[m], where length = bits_per_word * m + n.
+ * 
+ */
+
+#define bits_per_word  32
+#define bytes_per_word 4
+
+typedef struct {
+  uint32_t length;   
+  uint32_t *word;
+} bitvector_t;
+
+
+#define _bitvector_get_bit(v, bit_index)                               \
+(                                                                      \
+ ((((v)->word[((bit_index) >> 5)]) >> ((bit_index) & 31)) & 1)         \
+)
+
+
+#define _bitvector_set_bit(v, bit_index)                               \
+(                                                                      \
+ (((v)->word[((bit_index) >> 5)] |= ((uint32_t)1 << ((bit_index) & 31)))) \
+)
+
+#define _bitvector_clear_bit(v, bit_index)                             \
+(                                                                      \
+ (((v)->word[((bit_index) >> 5)] &= ~((uint32_t)1 << ((bit_index) & 31)))) \
+)
+
+#define _bitvector_get_length(v)                                       \
+(                                                                      \
+ ((v)->length)                                                         \
+)
+
+#ifdef DATATYPES_USE_MACROS  /* little functions are really macros */
+
+#define bitvector_get_bit(v, bit_index) _bitvector_get_bit(v, bit_index)
+#define bitvector_set_bit(v, bit_index) _bitvector_set_bit(v, bit_index)
+#define bitvector_clear_bit(v, bit_index) _bitvector_clear_bit(v, bit_index)
+#define bitvector_get_length(v) _bitvector_get_length(v)
+
+#else
+
+int
+bitvector_get_bit(const bitvector_t *v, int bit_index);
+
+void
+bitvector_set_bit(bitvector_t *v, int bit_index);
+
+void
+bitvector_clear_bit(bitvector_t *v, int bit_index);
+
+unsigned long
+bitvector_get_length(const bitvector_t *v);
+
+#endif
+
+int
+bitvector_alloc(bitvector_t *v, unsigned long length);
+
+void
+bitvector_dealloc(bitvector_t *v);
+
+void
+bitvector_set_to_zero(bitvector_t *x);
+
+void
+bitvector_left_shift(bitvector_t *x, int index);
+
+char *
+bitvector_bit_string(bitvector_t *x, char* buf, int len);
+
 #endif /* _DATATYPES_H */
index 37d3cb93e81ffbc35aa4e4281c6351fa9d67c07c..1a6e17018238a888d5d24810a643a6c4e8f491a7 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -90,7 +90,7 @@ typedef enum {
   err_status_parse_err    = 21, /**< error pasring data                      */
   err_status_encode_err   = 22, /**< error encoding data                     */
   err_status_semaphore_err = 23,/**< error while using semaphores            */
-  err_status_pfkey_err = 24    ,/**< error while using pfkey                 */
+  err_status_pfkey_err    = 24  /**< error while using pfkey                 */
 } err_status_t;
 
 /**
index ea40a4412b6b24be9aa6ce7cd63a39d5312f7476..098d37c9e25d775df65b8eb0f438492634111ec7 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 6abfdf8d510da8787af2fbef1368954f472be889..262c0e2d6eaf4a38796137ed1422cf77170db6e8 100644 (file)
@@ -9,7 +9,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 8b55720a91a3c6043f21d80313c3cdb28843d2be..7010efdde3bc5abbd6a5ecb902bdcfd1638ae16a 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -113,7 +113,7 @@ extern uint32_t low32(uint64_t value);
    addresses.  This is required for processors that do not allow unaligned
    loads. */
 #ifdef ALIGNMENT_32BIT_REQUIRED
-// Note that if it's in a variable, you can memcpy it
+/* Note that if it's in a variable, you can memcpy it */
 #ifdef WORDS_BIGENDIAN
 #define PUT_32(addr,value) \
     { \
index 6e89697a0d747eb8aa74eaf90308940392b9db4f..e7e07448e70dfca1a4bf4d1aec716fa59b3cc00a 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index cebb86b1a592b760f7715df7f87584446dfe6387..44f9a4a2ba3c3f20394f41ece7f807037ae3c6a1 100644 (file)
@@ -8,7 +8,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 7f348be5ff6b2bf02ce06ecb50d40d29217b0552..39da59a812960feb7aa62069b99474d71f9c1f3f 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -62,11 +62,11 @@ typedef struct {
  */
 
 err_status_t
-null_cipher_init(null_cipher_ctx_t *c, const uint8_t *key);
+null_cipher_init(null_cipher_ctx_t *c, const uint8_t *key, int key_len);
 
 err_status_t
 null_cipher_set_segment(null_cipher_ctx_t *c,
-                       unsigned long index);
+                       unsigned long segment_index);
 
 err_status_t
 null_cipher_encrypt(null_cipher_ctx_t *c,
index 19a3f94b1be3a7c347ed5a6fdf4fd1267479935c..b4c21103ace20891d4f1cfd85eb60b969fb017d9 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 5a26c5e303e5e87bcaede0474d3ccba6d9faa55d..2ccb1448e2079000e87b59bbd76219e1a7731a7e 100644 (file)
@@ -49,7 +49,7 @@ rdb_init(rdb_t *rdb);
  */
 
 err_status_t
-rdb_check(const rdb_t *rdb, uint32_t index);  
+rdb_check(const rdb_t *rdb, uint32_t rdb_index);  
 
 /*
  * rdb_add_index
@@ -61,7 +61,7 @@ rdb_check(const rdb_t *rdb, uint32_t index);
  */
 
 err_status_t
-rdb_add_index(rdb_t *rdb, uint32_t index);
+rdb_add_index(rdb_t *rdb, uint32_t rdb_index);
 
 /*
  * the functions rdb_increment() and rdb_get_value() are for use by 
index ce9ecf6f4773c12da6cfc02e5c2c334eaa76c969..146fb42f25aacbffa959618d4f8317bf0dd68e60 100644 (file)
@@ -46,19 +46,29 @@ typedef uint64_t xtd_seq_num_t;
 
 typedef struct {
   xtd_seq_num_t index;
-  v128_t bitmask;
+  bitvector_t bitmask;
 } rdbx_t;
 
 
 /*
- * rdbx_init(rdbx_ptr)
+ * rdbx_init(rdbx_ptr, ws)
  *
- * initializes the rdbx pointed to by its argument, setting the
- * rollover counter and sequence number to zero
+ * initializes the rdbx pointed to by its argument with the window size ws,
+ * setting the rollover counter and sequence number to zero
  */
 
 err_status_t
-rdbx_init(rdbx_t *rdbx);
+rdbx_init(rdbx_t *rdbx, unsigned long ws);
+
+
+/*
+ * rdbx_dealloc(rdbx_ptr)
+ *
+ * frees memory associated with the rdbx
+ */
+
+err_status_t
+rdbx_dealloc(rdbx_t *rdbx);
 
 
 /*
@@ -100,12 +110,42 @@ rdbx_check(const rdbx_t *rdbx, int difference);
 err_status_t
 rdbx_add_index(rdbx_t *rdbx, int delta);
 
+
+/*
+ * rdbx_set_roc(rdbx, roc) initalizes the rdbx_t at the location rdbx
+ * to have the rollover counter value roc.  If that value is less than
+ * the current rollover counter value, then the function returns
+ * err_status_replay_old; otherwise, err_status_ok is returned.
+ * 
+ */
+
+err_status_t
+rdbx_set_roc(rdbx_t *rdbx, uint32_t roc);
+
+/*
+ * rdbx_get_roc(rdbx) returns the value of the rollover counter for
+ * the rdbx_t pointed to by rdbx
+ * 
+ */
+
+xtd_seq_num_t
+rdbx_get_packet_index(const rdbx_t *rdbx);
+
 /*
  * xtd_seq_num_t functions - these are *internal* functions of rdbx, and
  * shouldn't be used to manipulate rdbx internal values.  use the rdbx
  * api instead!
  */
 
+/*
+ * rdbx_get_ws(rdbx_ptr)
+ *
+ * gets the window size which was used to initialize the rdbx
+ */
+
+unsigned long
+rdbx_get_window_size(const rdbx_t *rdbx);
+
 
 /* index_init(&pi) initializes a packet index pi (sets it to zero) */
 
index 1d61c5832caff620422e8b6050096ab9704ac6a9..e3af4d4b4b8836675a64022a2e39b4cf70efe540 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 1fe4f2f481f1d998ea82233ba004949944e9b333..e28b1314a8f6f44bbc5ddbdddf6e38b0f36f93ff 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright(c) 2001-2005, Cisco Systems, Inc.
+ * Copyright(c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 9ff5898f063fb5937c004c9ac73b64cce166f07b..5dd094749000d19350a3ce0b892eecbf00838ee4 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 23131c9c548dbc7f6db430655c8952bfac1449d5..0e969bc8601f339966c8ea0db4215d76224b31fd 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -151,10 +151,10 @@ crypto_kernel_init() {
   status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER);
   if (status) 
     return status;
-  status = crypto_kernel_load_cipher_type(&aes_icm, AES_128_ICM);
+  status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM);
   if (status) 
     return status;
-  status = crypto_kernel_load_cipher_type(&aes_cbc, AES_128_CBC);
+  status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC);
   if (status) 
     return status;
 
@@ -297,15 +297,19 @@ crypto_kernel_shutdown() {
   return err_status_ok;
 }
 
-err_status_t
-crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
-  kernel_cipher_type_t *ctype, *new;
+static inline err_status_t
+crypto_kernel_do_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id,
+                                 int replace) {
+  kernel_cipher_type_t *ctype, *new_ctype;
   err_status_t status;
 
   /* defensive coding */
   if (new_ct == NULL)
     return err_status_bad_param;
 
+  if (new_ct->id != id)
+    return err_status_bad_param;
+
   /* check cipher type by running self-test */
   status = cipher_type_self_test(new_ct);
   if (status) {
@@ -315,24 +319,35 @@ crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
   /* walk down list, checking if this type is in the list already  */
   ctype = crypto_kernel.cipher_type_list;
   while (ctype != NULL) {
-    if ((new_ct == ctype->cipher_type) || (id == ctype->id))
+    if (id == ctype->id) {
+      if (!replace)
+       return err_status_bad_param;
+      status = cipher_type_test(new_ct, ctype->cipher_type->test_data);
+      if (status)
+       return status;
+      new_ctype = ctype;
+      break;
+    }
+    else if (new_ct == ctype->cipher_type)
       return err_status_bad_param;    
     ctype = ctype->next;
   }
 
-  /* put new_ct at the head of the list */
+  /* if not found, put new_ct at the head of the list */
+  if (ctype == NULL) {
   /* allocate memory */
-  new = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t));
-  if (new == NULL)
-    return err_status_alloc_fail;
+    new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t));
+    if (new_ctype == NULL)
+      return err_status_alloc_fail;
+    new_ctype->next = crypto_kernel.cipher_type_list;
+
+    /* set head of list to new cipher type */
+    crypto_kernel.cipher_type_list = new_ctype;    
+  }
     
   /* set fields */
-  new->cipher_type = new_ct;
-  new->id = id;
-  new->next = crypto_kernel.cipher_type_list;
-
-  /* set head of list to new cipher type */
-  crypto_kernel.cipher_type_list = new;    
+  new_ctype->cipher_type = new_ct;
+  new_ctype->id = id;
 
   /* load debug module, if there is one present */
   if (new_ct->debug != NULL)
@@ -343,14 +358,28 @@ crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
 }
 
 err_status_t
-crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) {
-  kernel_auth_type_t *atype, *new;
+crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
+  return crypto_kernel_do_load_cipher_type(new_ct, id, 0);
+}
+
+err_status_t
+crypto_kernel_replace_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
+  return crypto_kernel_do_load_cipher_type(new_ct, id, 1);
+}
+
+err_status_t
+crypto_kernel_do_load_auth_type(auth_type_t *new_at, auth_type_id_t id,
+                               int replace) {
+  kernel_auth_type_t *atype, *new_atype;
   err_status_t status;
 
   /* defensive coding */
   if (new_at == NULL)
     return err_status_bad_param;
 
+  if (new_at->id != id)
+    return err_status_bad_param;
+
   /* check auth type by running self-test */
   status = auth_type_self_test(new_at);
   if (status) {
@@ -360,24 +389,35 @@ crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) {
   /* walk down list, checking if this type is in the list already  */
   atype = crypto_kernel.auth_type_list;
   while (atype != NULL) {
-    if ((new_at == atype->auth_type) || (id == atype->id))
+    if (id == atype->id) {
+      if (!replace)
+       return err_status_bad_param;
+      status = auth_type_test(new_at, atype->auth_type->test_data);
+      if (status)
+       return status;
+      new_atype = atype;
+      break;
+    }
+    else if (new_at == atype->auth_type)
       return err_status_bad_param;    
     atype = atype->next;
   }
 
-  /* put new_at at the head of the list */
-  /* allocate memory */
-  new = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t));
-  if (new == NULL)
-    return err_status_alloc_fail;
+  /* if not found, put new_at at the head of the list */
+  if (atype == NULL) {
+    /* allocate memory */
+    new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t));
+    if (new_atype == NULL)
+      return err_status_alloc_fail;
+
+    new_atype->next = crypto_kernel.auth_type_list;
+    /* set head of list to new auth type */
+    crypto_kernel.auth_type_list = new_atype;
+  }
     
   /* set fields */
-  new->auth_type = new_at;
-  new->id = id;
-  new->next = crypto_kernel.auth_type_list;
-
-  /* set head of list to new auth type */
-  crypto_kernel.auth_type_list = new;    
+  new_atype->auth_type = new_at;
+  new_atype->id = id;
 
   /* load debug module, if there is one present */
   if (new_at->debug != NULL)
@@ -388,6 +428,16 @@ crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) {
 
 }
 
+err_status_t
+crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) {
+  return crypto_kernel_do_load_auth_type(new_at, id, 0);
+}
+
+err_status_t
+crypto_kernel_replace_auth_type(auth_type_t *new_at, auth_type_id_t id) {
+  return crypto_kernel_do_load_auth_type(new_at, id, 1);
+}
+
 
 cipher_type_t *
 crypto_kernel_get_cipher_type(cipher_type_id_t id) {
index f68a629975c22211ec8a6bddc9c8ba38bc1c3f9c..4a3a8589e990ab491ea2530db79c94e24da4a82c 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  *
  */
 
-#ifdef _MSC_VER
-#pragma warning(disable:4100)
-#endif
-
 #include "err.h"
 
 #ifdef ERR_REPORTING_SYSLOG
index 8c86b89f266e4bb7fcfe61ee03f16b4d092e524c..9f63b22c216521ce6f92559c3cfdaac6261e6f1e 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 58c7502176dad0d36241502d5a39d8afa8ab9a32..21c0dc0782272527000d6e2690e5e61123d56f3b 100644 (file)
@@ -9,7 +9,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -95,7 +95,7 @@ octet_get_weight(uint8_t octet) {
 
 /* the value MAX_PRINT_STRING_LEN is defined in datatypes.h */
 
-static char bit_string[MAX_PRINT_STRING_LEN];
+char bit_string[MAX_PRINT_STRING_LEN];
 
 uint8_t
 nibble_to_hex_char(uint8_t nibble) {
@@ -106,7 +106,7 @@ nibble_to_hex_char(uint8_t nibble) {
 
 char *
 octet_string_hex_string(const void *s, int length) {
-  const uint8_t *str = s;
+  const uint8_t *str = (const uint8_t *)s;
   int i;
   
   /* double length, since one octet takes two hex characters */
@@ -124,7 +124,7 @@ octet_string_hex_string(const void *s, int length) {
   return bit_string;
 }
 
-inline int
+static inline int
 hex_char_to_nibble(uint8_t c) {
   switch(c) {
   case ('0'): return 0x0;
@@ -149,9 +149,10 @@ hex_char_to_nibble(uint8_t c) {
   case ('E'): return 0xe;
   case ('f'): return 0xf;
   case ('F'): return 0xf;
+  default: return -1;   /* this flags an error */
   }
-  /* this flags an error */
-  return -1;
+  /* NOTREACHED */
+  return -1;  /* this keeps compilers from complaining */
 }
 
 int
@@ -178,7 +179,7 @@ hex_string_to_octet_string(char *raw, char *hex, int len) {
     tmp = hex_char_to_nibble(hex[0]);
     if (tmp == -1)
       return hex_len;
-    x = (uint8_t)(tmp << 4);
+    x = (tmp << 4);
     hex_len++;
     tmp = hex_char_to_nibble(hex[1]);
     if (tmp == -1)
@@ -206,16 +207,16 @@ v128_hex_string(v128_t *x) {
 
 char *
 v128_bit_string(v128_t *x) {
-  int j, index;
+  int j, i;
   uint32_t mask;
   
-  for (j=index=0; j < 4; j++) {
+  for (j=i=0; j < 4; j++) {
     for (mask=0x80000000; mask > 0; mask >>= 1) {
       if (x->v32[j] & mask)
-       bit_string[index] = '1';
+       bit_string[i] = '1';
       else
-       bit_string[index] = '0';
-      ++index;
+       bit_string[i] = '0';
+      ++i;
     }
   }
   bit_string[128] = 0; /* null terminate string */
@@ -322,13 +323,13 @@ v128_set_bit_to(v128_t *x, int i, int y){
 #endif /* DATATYPES_USE_MACROS */
 
 void
-v128_right_shift(v128_t *x, int index) {
-  const int base_index = index >> 5;
-  const int bit_index = index & 31;
+v128_right_shift(v128_t *x, int shift) {
+  const int base_index = shift >> 5;
+  const int bit_index = shift & 31;
   int i, from;
   uint32_t b;
     
-  if (index > 127) {
+  if (shift > 127) {
     v128_set_to_zero(x);
     return;
   }
@@ -360,12 +361,12 @@ v128_right_shift(v128_t *x, int index) {
 }
 
 void
-v128_left_shift(v128_t *x, int index) {
+v128_left_shift(v128_t *x, int shift) {
   int i;
-  const int base_index = index >> 5;
-  const int bit_index = index & 31;
+  const int base_index = shift >> 5;
+  const int bit_index = shift & 31;
 
-  if (index > 127) {
+  if (shift > 127) {
     v128_set_to_zero(x);
     return;
   } 
@@ -386,6 +387,124 @@ v128_left_shift(v128_t *x, int index) {
 
 }
 
+/* functions manipulating bitvector_t */
+
+#ifndef DATATYPES_USE_MACROS /* little functions are not macros */
+
+int
+bitvector_get_bit(const bitvector_t *v, int bit_index)
+{
+  return _bitvector_get_bit(v, bit_index);
+}
+
+void
+bitvector_set_bit(bitvector_t *v, int bit_index)
+{
+  _bitvector_set_bit(v, bit_index);
+}
+
+void
+bitvector_clear_bit(bitvector_t *v, int bit_index)
+{
+  _bitvector_clear_bit(v, bit_index);
+}
+
+
+#endif /* DATATYPES_USE_MACROS */
+
+int
+bitvector_alloc(bitvector_t *v, unsigned long length) {
+  unsigned long l;
+
+  /* Round length up to a multiple of bits_per_word */
+  length = (length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1));
+
+  l = length / bits_per_word * bytes_per_word;
+
+  /* allocate memory, then set parameters */
+  if (l == 0)
+    v->word = NULL;
+  else {
+    v->word = (uint32_t*)crypto_alloc(l);
+    if (v->word == NULL) {
+      v->word = NULL;
+      v->length = 0;
+      return -1;
+    }
+  }
+  v->length = length;
+
+  /* initialize bitvector to zero */
+  bitvector_set_to_zero(v);
+
+  return 0;
+}
+
+
+void
+bitvector_dealloc(bitvector_t *v) {
+  if (v->word != NULL)
+    crypto_free(v->word);
+  v->word = NULL;
+  v->length = 0;
+}
+
+void
+bitvector_set_to_zero(bitvector_t *x)
+{
+  /* C99 guarantees that memset(0) will set the value 0 for uint32_t */
+  memset(x->word, 0, x->length >> 3);
+}
+
+char *
+bitvector_bit_string(bitvector_t *x, char* buf, int len) {
+  int j, i;
+  uint32_t mask;
+  
+  for (j=i=0; j < (int)(x->length>>5) && i < len-1; j++) {
+    for (mask=0x80000000; mask > 0; mask >>= 1) {
+      if (x->word[j] & mask)
+       buf[i] = '1';
+      else
+       buf[i] = '0';
+      ++i;
+      if (i >= len-1)
+        break;
+    }
+  }
+  buf[i] = 0; /* null terminate string */
+
+  return buf;
+}
+
+void
+bitvector_left_shift(bitvector_t *x, int shift) {
+  int i;
+  const int base_index = shift >> 5;
+  const int bit_index = shift & 31;
+  const int word_length = x->length >> 5;
+
+  if (shift >= (int)x->length) {
+    bitvector_set_to_zero(x);
+    return;
+  } 
+  
+  if (bit_index == 0) {
+    for (i=0; i < word_length - base_index; i++)
+      x->word[i] = x->word[i+base_index];
+  } else {
+    for (i=0; i < word_length - base_index - 1; i++)
+      x->word[i] = (x->word[i+base_index] >> bit_index) ^
+       (x->word[i+base_index+1] << (32 - bit_index));
+    x->word[word_length - base_index-1] = x->word[word_length-1] >> bit_index;
+  }
+
+  /* now wrap up the final portion */
+  for (i = word_length - base_index; i < word_length; i++) 
+    x->word[i] = 0;
+
+}
+
 
 int
 octet_string_is_eq(uint8_t *a, uint8_t *b, int len) {
@@ -563,6 +682,8 @@ base64_char_to_sextet(uint8_t c) {
     return 63;
   case '=':
     return 64;
+  default:
+    break;
  }
  return -1;
 }
@@ -583,7 +704,7 @@ base64_string_to_octet_string(char *raw, char *base64, int len) {
     tmp = base64_char_to_sextet(base64[0]);
     if (tmp == -1)
       return base64_len;
-    x = (uint8_t)(tmp << 6);
+    x = (tmp << 6);
     base64_len++;
     tmp = base64_char_to_sextet(base64[1]);
     if (tmp == -1)
index 7bd5a0dea2804d102f884e711c68396ab26fa199..f1f45bdd56c4df8411015fc3566448c248ca2fa6 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,7 @@
 
 /* gf2_8_shift() moved to gf2_8.h as an inline function */
 
-inline gf2_8
+gf2_8
 gf2_8_multiply(gf2_8 x, gf2_8 y) {
   gf2_8 z = 0;
 
index f3aaf650141ec643ed6f0357f8a3b4b2fb8887f7..9e3e78ed1228d60c4ce71893c4d0026cd8d3e3dc 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,6 @@
  */
 
 #include "crypto_math.h"
-#include <stdlib.h>           /* malloc() used in bitvector_alloc */
 
 int 
 octet_weight[256] = {
@@ -173,7 +172,7 @@ v32_weight(v32_t a) {
   return wt;
 }
 
-inline unsigned char
+unsigned char
 v32_distance(v32_t x, v32_t y) {
   x.value ^= y.value;
   return v32_weight(x);
@@ -192,7 +191,7 @@ v32_dot_product(v32_t a, v32_t b) {
 
 #define MAX_STRING_LENGTH 1024
 
-static char bit_string[MAX_STRING_LENGTH];
+char bit_string[MAX_STRING_LENGTH];
 
 char *
 octet_bit_string(uint8_t x) {
@@ -524,13 +523,13 @@ A_times_x_plus_b(uint8_t A[8], uint8_t x, uint8_t b) {
   return b;
 }
 
-inline void
+void
 v16_copy_octet_string(v16_t *x, const uint8_t s[2]) {
   x->v8[0]  = s[0];
   x->v8[1]  = s[1];
 }
 
-inline void
+void
 v32_copy_octet_string(v32_t *x, const uint8_t s[4]) {
   x->v8[0]  = s[0];
   x->v8[1]  = s[1];
@@ -538,7 +537,7 @@ v32_copy_octet_string(v32_t *x, const uint8_t s[4]) {
   x->v8[3]  = s[3];
 }
 
-inline void
+void
 v64_copy_octet_string(v64_t *x, const uint8_t s[8]) {
   x->v8[0]  = s[0];
   x->v8[1]  = s[1];
@@ -632,7 +631,7 @@ v128_set_bit_to(v128_t *x, int i, int y){
 #endif /* DATATYPES_USE_MACROS */
 
 
-inline void
+static inline void
 v128_left_shift2(v128_t *x, int num_bits) {
   int i;
   int word_shift = num_bits >> 5;
@@ -773,165 +772,6 @@ octet_string_set_to_zero(uint8_t *s, int len) {
   
 }
 
-/* functions manipulating bit_vector_t */
-
-#define BITVECTOR_MAX_WORDS 5
-
-int
-bitvector_alloc(bitvector_t *v, unsigned long length) {
-  unsigned long l = (length + bytes_per_word - 1) / bytes_per_word;
-  int i;
-
-  /* allocate memory, then set parameters */
-  if (l > BITVECTOR_MAX_WORDS)
-    return -1;
-  else
-    l = BITVECTOR_MAX_WORDS;
-  v->word   = malloc(l);
-  if (v->word == NULL)
-    return -1;
-  v->length = length;
-
-  /* initialize bitvector to zero */
-  for (i=0; i < (length >> 5); i++) {
-    v->word = 0;
-  }
-
-  return 0;
-}
-
-void
-bitvector_set_bit(bitvector_t *v, int bit_index) {
-
-  v->word[(bit_index >> 5)] |= (1 << (bit_index & 31));
-  
-}
-
-int
-bitvector_get_bit(const bitvector_t *v, int bit_index) {
-
-  return ((v->word[(bit_index >> 5)]) >> (bit_index & 31)) & 1;
-  
-}
-
-#include <stdio.h>
-
-int
-bitvector_print_hex(const bitvector_t *v, FILE *stream) {
-  int i;
-  int m = v->length >> 5;
-  int n = v->length & 31;
-  char string[9];
-  uint32_t tmp;
-
-  /* if length isn't a multiple of four, we can't hex_print */
-  if (n & 3)
-    return -1;
-  
-  /* if the length is zero, do nothing */
-  if (v->length == 0)
-    return 0;
-
-  /*
-   * loop over words from most significant to least significant - 
-   */
-  
-  for (i=m; i > 0; i++) {
-    char *str = string + 7;
-    tmp = v->word[i];
-    
-    /* null terminate string */
-    string[8] = 0;   
-
-    /* loop over nibbles */
-    *str-- = nibble_to_hex_char(tmp & 0xf);  tmp >>= 4; 
-    *str-- = nibble_to_hex_char(tmp & 0xf);  tmp >>= 4; 
-    *str-- = nibble_to_hex_char(tmp & 0xf);  tmp >>= 4; 
-    *str-- = nibble_to_hex_char(tmp & 0xf);  tmp >>= 4; 
-    *str-- = nibble_to_hex_char(tmp & 0xf);  tmp >>= 4; 
-    *str-- = nibble_to_hex_char(tmp & 0xf);  tmp >>= 4; 
-    *str-- = nibble_to_hex_char(tmp & 0xf);  tmp >>= 4; 
-    *str-- = nibble_to_hex_char(tmp & 0xf);   
-
-    /* now print stream */
-    fprintf(stream, string);
-  }
-  
-  return 0;
-
-}
-
-
-int
-hex_string_length(char *s) {
-  int count = 0;
-  
-  /* ignore leading zeros */
-  while ((*s != 0) && *s == '0')
-    s++;
-
-  /* count remaining characters */
-  while (*s != 0) {
-    if (hex_char_to_nibble(*s++) == -1)
-      return -1;
-    count++;
-  }
-
-  return count;
-}
-
-int
-bitvector_set_from_hex(bitvector_t *v, char *string) {
-  int num_hex_chars, m, n, i, j;
-  uint32_t tmp;
-  
-  num_hex_chars = hex_string_length(string);
-  if (num_hex_chars == -1)
-    return -1;
-
-  /* set length */
-  v->length = num_hex_chars * 4;
-  /* 
-   * at this point, we should subtract away a bit if the high
-   * bit of the first character is zero, but we ignore that 
-   * for now and assume that we're four-bit aligned - DAM
-   */
-
-  
-  m = num_hex_chars / 8;   /* number of words                */
-  n = num_hex_chars % 8;   /* number of nibbles in last word */
-
-  /* if the length is greater than the bitvector, return an error */
-  if (m > BITVECTOR_MAX_WORDS)
-    return -1;
-
-  /* 
-   * loop over words from most significant - first word is a special
-   * case 
-   */
-  
-  if (n) {
-    tmp = 0;
-    for (i=0; i < n; i++) {
-      tmp = hex_char_to_nibble(*string++); 
-      tmp <<= 4;  
-    }
-    v->word[m] = tmp;
-  }
-
-  /* now loop over the rest of the words */
-  for (i=m-1; i >= 0; i--) {
-     tmp = 0;
-     for (j=0; j < 8; j++) {
-       tmp = hex_char_to_nibble(*string++); 
-       tmp <<= 4;  
-     }
-     v->word[i] = tmp;
-  }
-
-  return 0;
-}
-
 
 /* functions below not yet tested! */
 
index 6f94a0c6e690f4a8bd0e00cd0db93a70a4b44689..5e46c209e3da998804996cfa009d9b3abe28379a 100644 (file)
@@ -28,7 +28,7 @@ stat_test_monobit(uint8_t *data) {
 
   ones_count = 0;
   while (data < data_end) {
-    ones_count = (uint16_t)(ones_count + octet_get_weight(*data));
+    ones_count += octet_get_weight(*data);
     data++;
   }
 
@@ -83,7 +83,7 @@ stat_test_runs(uint8_t *data) {
   uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
   uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
   uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
-  int16_t  state = 0;
+  int state = 0;
   uint16_t mask;
   int i;
   
@@ -208,7 +208,7 @@ stat_test_rand_source(rand_source_func_t get_rand_bytes) {
   uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
   uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
   uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
-  int16_t  state = 0;
+  int state = 0;
   uint16_t mask;
   
   /* counters for monobit, poker, and runs tests are initialized above */
index e2e645be1be51b25215216d16bb65244346a5fcf..5d204ec0e1aaca4a233ec4b98e455bfaeb7c3633 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -70,19 +70,19 @@ rdb_init(rdb_t *rdb) {
  */
 
 err_status_t
-rdb_check(const rdb_t *rdb, uint32_t index) {
+rdb_check(const rdb_t *rdb, uint32_t p_index) {
   
   /* if the index appears after (or at very end of) the window, its good */
-  if (index >= rdb->window_start + rdb_bits_in_bitmask)
+  if (p_index >= rdb->window_start + rdb_bits_in_bitmask)
     return err_status_ok;
   
   /* if the index appears before the window, its bad */
-  if (index < rdb->window_start)
-    return err_status_fail;
+  if (p_index < rdb->window_start)
+    return err_status_replay_old;
 
   /* otherwise, the index appears within the window, so check the bitmask */
-  if (v128_get_bit(&rdb->bitmask, (index - rdb->window_start)) == 1)
-    return err_status_fail;    
+  if (v128_get_bit(&rdb->bitmask, (p_index - rdb->window_start)) == 1)
+    return err_status_replay_fail;    
       
   /* otherwise, the index is okay */
   return err_status_ok;
@@ -98,15 +98,15 @@ rdb_check(const rdb_t *rdb, uint32_t index) {
  */
 
 err_status_t
-rdb_add_index(rdb_t *rdb, uint32_t index) {
+rdb_add_index(rdb_t *rdb, uint32_t p_index) {
   int delta;  
 
-  /* here we *assume* that index > rdb->window_start */
+  /* here we *assume* that p_index > rdb->window_start */
 
-  delta = (index - rdb->window_start);    
+  delta = (p_index - rdb->window_start);    
   if (delta < rdb_bits_in_bitmask) {
 
-    /* if the index is within the window, set the appropriate bit */
+    /* if the p_index is within the window, set the appropriate bit */
     v128_set_bit(&rdb->bitmask, delta);
 
   } else { 
@@ -115,7 +115,7 @@ rdb_add_index(rdb_t *rdb, uint32_t index) {
 
     /* shift the window forward by delta bits*/
     v128_left_shift(&rdb->bitmask, delta);
-    v128_set_bit(&rdb->bitmask, rdb_bits_in_bitmask-delta);
+    v128_set_bit(&rdb->bitmask, rdb_bits_in_bitmask-1);
     rdb->window_start += delta;
 
   }    
index dcdb138510a21643e376f274bca36773870bc63f..54671cab0ca9a7c2d5f504499891c78e3a5a37e8 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 
 #include "rdbx.h"
 
-#define rdbx_high_bit_in_bitmask 127
 
 /*
- * from draft-ietf-avt-srtp-00.txt:
+ * from RFC 3711:
  *
  * A receiver reconstructs the index i of a packet with sequence
- *  number s using the estimate
+ *  number SEQ using the estimate
  *
- * i = 65,536 * t + s,
+ * i = 2^16 * v + SEQ,
  *
- * where t is chosen from the set { r-1, r, r+1 } such that i is
- * closest to the value 65,536 * r + s_l.  If the value r+1 is used,
+ * where v is chosen from the set { ROC-1, ROC, ROC+1 } such that i is
+ * closest to the value 2^16 * ROC + s_l.  If the value r+1 is used,
  * then the rollover counter r in the cryptographic context is
  * incremented by one (if the packet containing s is authentic).
  */
@@ -146,18 +145,18 @@ index_guess(const xtd_seq_num_t *local,
   if (local_seq < seq_num_median) {
     if (s - local_seq > seq_num_median) {
       guess_roc = local_roc - 1;
-      difference = seq_num_max - s + local_seq;
+      difference = s - local_seq - seq_num_max;
     } else {
       guess_roc = local_roc;
       difference = s - local_seq;
     }
   } else {
     if (local_seq - seq_num_median > s) {
-      guess_roc = local_roc+1;
-      difference = seq_num_max - local_seq + s;
+      guess_roc = local_roc + 1;
+      difference = s - local_seq + seq_num_max;
     } else {
-      difference = s - local_seq;
       guess_roc = local_roc;
+      difference = s - local_seq;
     }
   }
   guess_seq = s;
@@ -180,17 +179,81 @@ index_guess(const xtd_seq_num_t *local,
 
 
 /*
- *  rdbx_init(&r) initalizes the rdbx_t pointed to by r 
+ *  rdbx_init(&r, ws) initializes the rdbx_t pointed to by r with window size ws
  */
 
 err_status_t
-rdbx_init(rdbx_t *rdbx) {
-  v128_set_to_zero(&rdbx->bitmask);
+rdbx_init(rdbx_t *rdbx, unsigned long ws) {
+  if (ws == 0)
+    return err_status_bad_param;
+
+  if (bitvector_alloc(&rdbx->bitmask, ws) != 0)
+    return err_status_alloc_fail;
+
   index_init(&rdbx->index);
 
   return err_status_ok;
 }
 
+/*
+ *  rdbx_dealloc(&r) frees memory for the rdbx_t pointed to by r
+ */
+
+err_status_t
+rdbx_dealloc(rdbx_t *rdbx) {
+  bitvector_dealloc(&rdbx->bitmask);
+
+  return err_status_ok;
+}
+
+/*
+ * rdbx_set_roc(rdbx, roc) initalizes the rdbx_t at the location rdbx
+ * to have the rollover counter value roc.  If that value is less than
+ * the current rollover counter value, then the function returns
+ * err_status_replay_old; otherwise, err_status_ok is returned.
+ * 
+ */
+
+err_status_t
+rdbx_set_roc(rdbx_t *rdbx, uint32_t roc) {
+  bitvector_set_to_zero(&rdbx->bitmask);
+
+#ifdef NO_64BIT_MATH
+  #error not yet implemented
+#else
+
+  /* make sure that we're not moving backwards */
+  if (roc < (rdbx->index >> 16))
+    return err_status_replay_old;
+
+  rdbx->index &= 0xffff;   /* retain lowest 16 bits */
+  rdbx->index |= ((uint64_t)roc) << 16;  /* set ROC */
+#endif
+
+  return err_status_ok;
+}
+
+/*
+ * rdbx_get_packet_index(rdbx) returns the value of the packet index
+ * for the rdbx_t pointed to by rdbx
+ * 
+ */
+
+xtd_seq_num_t
+rdbx_get_packet_index(const rdbx_t *rdbx) {
+  return rdbx->index;   
+}
+
+/*
+ * rdbx_get_window_size(rdbx) returns the value of the window size
+ * for the rdbx_t pointed to by rdbx
+ * 
+ */
+
+unsigned long
+rdbx_get_window_size(const rdbx_t *rdbx) {
+  return bitvector_get_length(&rdbx->bitmask);
+}
 
 /*
  * rdbx_check(&r, delta) checks to see if the xtd_seq_num_t
@@ -202,11 +265,11 @@ rdbx_check(const rdbx_t *rdbx, int delta) {
   
   if (delta > 0) {       /* if delta is positive, it's good */
     return err_status_ok;
-  } else if (rdbx_high_bit_in_bitmask + delta < 0) {   
+  } else if ((int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta < 0) {   
                          /* if delta is lower than the bitmask, it's bad */
     return err_status_replay_old; 
-  } else if (v128_get_bit(&rdbx->bitmask, 
-                         rdbx_high_bit_in_bitmask + delta) == 1) {
+  } else if (bitvector_get_bit(&rdbx->bitmask, 
+                              (int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta) == 1) {
                          /* delta is within the window, so check the bitmask */
     return err_status_replay_fail;    
   }
@@ -229,12 +292,12 @@ rdbx_add_index(rdbx_t *rdbx, int delta) {
   
   if (delta > 0) {
     /* shift forward by delta */
-    index_advance(&rdbx->index, (sequence_number_t)delta);
-    v128_left_shift(&rdbx->bitmask, delta);
-    v128_set_bit(&rdbx->bitmask, 127);
+    index_advance(&rdbx->index, delta);
+    bitvector_left_shift(&rdbx->bitmask, delta);
+    bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) - 1);
   } else {
-    /* delta is in window, so flip bit in bitmask */
-    v128_set_bit(&rdbx->bitmask, -delta);
+    /* delta is in window */
+    bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) -1 + delta);
   }
 
   /* note that we need not consider the case that delta == 0 */
index 15258c76ab29ef57bfa65088b085b6a5fc0f2e28..43c411e46b3b9f048e802a7c74ef57af2ef67948 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -47,9 +47,6 @@
 
 #include "ut_sim.h"
 
-#ifdef _MSC_VER
-#pragma warning(disable:4100)
-#endif
 
 int
 ut_compar(const void *a, const void *b) {
index 91effb96abc51ad02d4fcb9b1211f266456a492d..41d46a8f55165f14396c5891f7b7bbb9b2ccbd83 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
 
 /* single, global prng structure */
 
-static ctr_prng_t ctr_prng;
+ctr_prng_t ctr_prng;
 
 err_status_t
 ctr_prng_init(rand_source_func_t random_source) {
@@ -66,7 +66,7 @@ ctr_prng_init(rand_source_func_t random_source) {
     return status;
 
   /* initialize aes ctr context with random key */
-  status = aes_icm_context_init(&ctr_prng.state, tmp_key);
+  status = aes_icm_context_init(&ctr_prng.state, tmp_key, 30);
   if (status) 
     return status;
 
@@ -92,7 +92,7 @@ ctr_prng_get_octet_string(void *dest, uint32_t len) {
   /*
    * write prng output 
    */
-  status = aes_icm_output(&ctr_prng.state, dest, len);
+  status = aes_icm_output(&ctr_prng.state, (uint8_t*)dest, len);
   if (status)
     return status;
   
index 0cd027eeced82e683862dcf0b5a58a5c5bd19ac5..62b5e11d4e36bc71ce79befd61086045485e41b5 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 
 /* single, global prng structure */
 
-static x917_prng_t x917_prng;
+x917_prng_t x917_prng;
 
 err_status_t
 x917_prng_init(rand_source_func_t random_source) {
-  v128_t tmp_key;
+  uint8_t tmp_key[16];
   err_status_t status;
 
   /* initialize output count to zero */
@@ -61,12 +61,12 @@ x917_prng_init(rand_source_func_t random_source) {
   x917_prng.rand = random_source;
   
   /* initialize secret key from random source */
-  status = random_source((uint8_t *)&tmp_key, 16);
+  status = random_source(tmp_key, 16);
   if (status) 
     return status;
 
   /* expand aes key */
-  aes_expand_encryption_key(&tmp_key, x917_prng.key);
+  aes_expand_encryption_key(tmp_key, 16, &x917_prng.key);
 
   /* initialize prng state from random source */
   status = x917_prng.rand((uint8_t *)&x917_prng.state, 16);
@@ -80,7 +80,7 @@ err_status_t
 x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
   uint32_t t;
   v128_t buffer;
-  int i, tail_len;
+  uint32_t i, tail_len;
   err_status_t status;
 
   /* 
@@ -99,7 +99,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
   t = (uint32_t)time(NULL);
   
   /* loop until we have output enough data */
-  for (i=0; (uint32_t)i < len/16; i++) {
+  for (i=0; i < len/16; i++) {
     
     /* exor time into state */
     x917_prng.state.v32[0] ^= t; 
@@ -108,7 +108,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
     v128_copy(&buffer, &x917_prng.state);
 
     /* apply aes to buffer */
-    aes_encrypt(&buffer, x917_prng.key);
+    aes_encrypt(&buffer, &x917_prng.key);
     
     /* write data to output */
     *dest++ = buffer.v8[0];
@@ -132,7 +132,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
     buffer.v32[0] ^= t;
 
     /* encrypt buffer */
-    aes_encrypt(&buffer, x917_prng.key);
+    aes_encrypt(&buffer, &x917_prng.key);
 
     /* copy buffer into state */
     v128_copy(&x917_prng.state, &buffer);
@@ -150,7 +150,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
     v128_copy(&buffer, &x917_prng.state);
 
     /* apply aes to buffer */
-    aes_encrypt(&buffer, x917_prng.key);
+    aes_encrypt(&buffer, &x917_prng.key);
 
     /* write data to output */
     for (i=0; i < tail_len; i++) {
@@ -163,7 +163,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
     buffer.v32[0] ^= t;
 
     /* encrypt buffer */
-    aes_encrypt(&buffer, x917_prng.key);
+    aes_encrypt(&buffer, &x917_prng.key);
 
     /* copy buffer into state */
     v128_copy(&x917_prng.state, &buffer);
index aee16c03e877eb8ac64eb8da2265afbd77788a49..1eb6fbb09cf9c4d4fccebe16ed137deee3eaa915 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  */
 
 #include "config.h"
-#include "rand_source.h"
 
 #ifdef DEV_URANDOM
 # include <fcntl.h>          /* for open()  */
 # include <unistd.h>         /* for close() */
+#elif defined(HAVE_RAND_S)
+# define _CRT_RAND_S
+# include <stdlib.h>         
 #else
 # include <stdio.h>
 #endif
 
-/* global dev_rand_fdes is file descriptor for /dev/random */
+#include "rand_source.h"
+
+
+/* 
+ * global dev_rand_fdes is file descriptor for /dev/random 
+ * 
+ * This variable is also used to indicate that the random source has
+ * been initialized.  When this variable is set to the value of the
+ * #define RAND_SOURCE_NOT_READY, it indicates that the random source
+ * is not ready to be used.  The value of the #define
+ * RAND_SOURCE_READY is for use whenever that variable is used as an
+ * indicator of the state of the random source, but not as a file
+ * descriptor.
+ */
 
-static int dev_random_fdes = -1;
+#define RAND_SOURCE_NOT_READY (-1)
+#define RAND_SOURCE_READY     (17)
+
+static int dev_random_fdes = RAND_SOURCE_NOT_READY;
 
 
 err_status_t
@@ -68,10 +86,12 @@ rand_source_init(void) {
   dev_random_fdes = open(DEV_URANDOM, O_RDONLY);
   if (dev_random_fdes < 0)
     return err_status_init_fail;
+#elif defined(HAVE_RAND_S)
+  dev_random_fdes = RAND_SOURCE_READY;
 #else
   /* no random source available; let the user know */
   fprintf(stderr, "WARNING: no real random source present!\n");
-  dev_random_fdes = 17;
+  dev_random_fdes = RAND_SOURCE_READY;
 #endif
   return err_status_ok;
 }
@@ -85,25 +105,45 @@ rand_source_get_octet_string(void *dest, uint32_t len) {
    * written 
    */
 #ifdef DEV_URANDOM
-  if (read(dev_random_fdes, dest, len) != len)
-    return err_status_fail;
+  uint8_t *dst = (uint8_t *)dest;
+  while (len)
+  {
+    ssize_t num_read = read(dev_random_fdes, dst, len);
+    if (num_read <= 0 || num_read > len)
+      return err_status_fail;
+    len -= num_read;
+    dst += num_read;
+  }
+#elif 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 err_status_fail;
+  
+    *dst++ = val & 0xff;
+    len--;
+  }
 #else
   /* Generic C-library (rand()) version */
   /* This is a random source of last resort */
-  uint8_t *dst = dest;
+  uint8_t *dst = (uint8_t *)dest;
   while (len)
   {
          int val = rand();
          /* rand() returns 0-32767 (ugh) */
          /* Is this a good enough way to get random bytes?
             It is if it passes FIPS-140... */
-         *dst++ = (uint8_t)(val & 0xff);
+         *dst++ = val & 0xff;
          len--;
   }
 #endif
   return err_status_ok;
 }
-
 err_status_t
 rand_source_deinit(void) {
   if (dev_random_fdes < 0)
@@ -112,7 +152,7 @@ rand_source_deinit(void) {
 #ifdef DEV_URANDOM
   close(dev_random_fdes);  
 #endif
-  dev_random_fdes = -1;
+  dev_random_fdes = RAND_SOURCE_NOT_READY;
   
   return err_status_ok;  
 }
diff --git a/libs/srtp/crypto/test/.cvsignore b/libs/srtp/crypto/test/.cvsignore
new file mode 100644 (file)
index 0000000..888bf59
--- /dev/null
@@ -0,0 +1,8 @@
+aes_calc
+cipher_driver
+datatypes_driver
+env
+kernel_driver
+rand_gen
+sha1_driver
+stat_driver
diff --git a/libs/srtp/crypto/test/aes_calc b/libs/srtp/crypto/test/aes_calc
new file mode 100755 (executable)
index 0000000..ddefb75
Binary files /dev/null and b/libs/srtp/crypto/test/aes_calc differ
index 2fac07ae35c357d5c657930bfdcc2611340b0586..fe3c6ad07df3b4bb9f1a6f169c08dc8b21bcb011 100644 (file)
@@ -28,14 +28,16 @@ usage(char *prog_name) {
   exit(255);
 }
 
-#define AES_KEY_LEN 16
+#define AES_MAX_KEY_LEN 32
 
 int
 main (int argc, char *argv[]) {
-  v128_t data, key;
+  v128_t data;
+  uint8_t key[AES_MAX_KEY_LEN];
   aes_expanded_key_t exp_key;
-  int len;
+  int key_len, len;
   int verbose;
+  err_status_t status;
 
   if (argc == 3) {
     /* we're not in verbose mode */
@@ -54,22 +56,23 @@ main (int argc, char *argv[]) {
   }
   
   /* read in key, checking length */
-  if (strlen(argv[1]) > AES_KEY_LEN*2) {
+  if (strlen(argv[1]) > AES_MAX_KEY_LEN*2) {
     fprintf(stderr, 
            "error: too many digits in key "
-           "(should be %d hexadecimal digits, found %u)\n",
-           AES_KEY_LEN*2, (unsigned)strlen(argv[1]));
+           "(should be at most %d hexadecimal digits, found %u)\n",
+           AES_MAX_KEY_LEN*2, (unsigned)strlen(argv[1]));
     exit(1);    
   }
-  len = hex_string_to_octet_string((char *)&key, argv[1], AES_KEY_LEN*2);
+  len = hex_string_to_octet_string((char*)key, argv[1], AES_MAX_KEY_LEN*2);
   /* check that hex string is the right length */
-  if (len < AES_KEY_LEN*2) {
+  if (len != 32 && len != 48 && len != 64) {
     fprintf(stderr, 
-           "error: too few digits in key "
-           "(should be %d hexadecimal digits, found %d)\n",
-           AES_KEY_LEN*2, len);
+           "error: bad number of digits in key "
+           "(should be 32/48/64 hexadecimal digits, found %d)\n",
+           len);
     exit(1);    
   } 
+  key_len = len/2;
       
   /* read in plaintext, checking length */
   if (strlen(argv[2]) > 16*2) {
@@ -95,13 +98,18 @@ main (int argc, char *argv[]) {
   }
 
   /* encrypt plaintext */
-  aes_expand_encryption_key(&key, exp_key);
+  status = aes_expand_encryption_key(key, key_len, &exp_key);
+  if (status) {
+    fprintf(stderr,
+           "error: AES key expansion failed.\n");
+    exit(1);
+  }
 
-  aes_encrypt(&data, exp_key);
+  aes_encrypt(&data, &exp_key);
 
   /* write ciphertext to output */
   if (verbose) {
-    printf("key:\t\t%s\n", v128_hex_string(&key));
+    printf("key:\t\t%s\n", octet_string_hex_string(key, key_len));
     printf("ciphertext:\t");
   }
   printf("%s\n", v128_hex_string(&data));
index 3073d49500a7baa0d9eeb65d3ca6ed385353a6a0..cd8a75dd09a0854ff2e09d7716196afa19f0fd28 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 276e775b833c43aee0f40df9748d594f904e55ec..ea41ff5a4c943b450b39402e4dfd87a33f506bc2 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -120,10 +120,13 @@ int
 main(int argc, char *argv[]) {
   cipher_t *c = NULL;
   err_status_t status;
-  unsigned char test_key[20] = {
+  unsigned char test_key[48] = {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   };
   int q;
   unsigned do_timing_test = 0;
@@ -168,9 +171,14 @@ main(int argc, char *argv[]) {
     for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
       cipher_driver_test_array_throughput(&aes_icm, 30, num_cipher); 
 
+    for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
+      cipher_driver_test_array_throughput(&aes_icm, 46, num_cipher); 
+
     for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
       cipher_driver_test_array_throughput(&aes_cbc, 16, num_cipher); 
  
+    for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
+      cipher_driver_test_array_throughput(&aes_cbc, 32, num_cipher); 
   }
 
   if (do_validation) {
@@ -196,7 +204,7 @@ main(int argc, char *argv[]) {
   check_status(status);
   
 
-  /* run the throughput test on the aes_icm cipher */
+  /* run the throughput test on the aes_icm cipher (128-bit key) */
     status = cipher_type_alloc(&aes_icm, &c, 30);  
     if (status) {
       fprintf(stderr, "error: can't allocate cipher\n");
@@ -216,6 +224,27 @@ main(int argc, char *argv[]) {
     
     status = cipher_dealloc(c);
     check_status(status);
+
+  /* repeat the tests with 256-bit keys */
+    status = cipher_type_alloc(&aes_icm, &c, 46);  
+    if (status) {
+      fprintf(stderr, "error: can't allocate cipher\n");
+      exit(status);
+    }
+
+    status = cipher_init(c, test_key, direction_encrypt);
+    check_status(status);
+
+    if (do_timing_test)
+      cipher_driver_test_throughput(c);
+    
+    if (do_validation) {
+      status = cipher_driver_test_buffering(c);
+      check_status(status);
+    }
+    
+    status = cipher_dealloc(c);
+    check_status(status);
   
   return 0;
 }
@@ -225,9 +254,9 @@ cipher_driver_test_throughput(cipher_t *c) {
   int i;
   int min_enc_len = 32;     
   int max_enc_len = 2048;   /* should be a power of two */
-  int num_trials = 100000;  
+  int num_trials = 1000000;  
   
-  printf("timing %s throughput:\n", c->type->description);
+  printf("timing %s throughput, key length %d:\n", c->type->description, c->key_len);
   fflush(stdout);
   for (i=min_enc_len; i <= max_enc_len; i = i * 2)
     printf("msg len: %d\tgigabits per second: %f\n",
@@ -348,6 +377,9 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
   err_status_t status;
   uint8_t *key;
   cipher_t **cipher_array;
+  /* pad klen allocation, to handle aes_icm reading 16 bytes for the
+     14-byte salt */
+  int klen_pad = ((klen + 15) >> 4) << 4;
 
   /* allocate array of pointers to ciphers */
   cipher_array = (cipher_t **) malloc(sizeof(cipher_t *) * num_ciphers);
@@ -358,7 +390,7 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
   *ca = cipher_array;
 
   /* allocate key */
-  key = crypto_alloc(klen);
+  key = crypto_alloc(klen_pad);
   if (key == NULL) {
     free(cipher_array);
     return err_status_alloc_fail;
@@ -375,6 +407,8 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
     /* generate random key and initialize cipher */
     for (j=0; j < klen; j++)
       key[j] = (uint8_t) rand();
+    for (; j < klen_pad; j++)
+      key[j] = 0;
     status = cipher_init(*cipher_array, key, direction_encrypt);
     if (status)
       return status;
@@ -387,6 +421,8 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
     cipher_array++;
   }
 
+  crypto_free(key);
+
   return err_status_ok;
 }
 
@@ -423,24 +459,28 @@ cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher,
   v128_t nonce;
   clock_t timer;
   unsigned char *enc_buf;
-  int cipher_index = 0;
+  int cipher_index = rand() % num_cipher;
 
-
-  enc_buf = crypto_alloc(octets_in_buffer);
+  /* Over-alloc, for NIST CBC padding */
+  enc_buf = crypto_alloc(octets_in_buffer+17);
   if (enc_buf == NULL)
     return 0;  /* indicate bad parameters by returning null */
+  memset(enc_buf, 0, octets_in_buffer);
   
   /* time repeated trials */
   v128_set_to_zero(&nonce);
   timer = clock();
   for(i=0; i < num_trials; i++, nonce.v32[3] = i) {
-
-    /* choose a cipher at random from the array*/
-    cipher_index = (*((uint32_t *)enc_buf)) % num_cipher;
+    /* length parameter to cipher_encrypt is in/out -- out is total, padded
+     * length -- so reset it each time. */
+    unsigned octets_to_encrypt = octets_in_buffer;
 
     /* encrypt buffer with cipher */
     cipher_set_iv(cipher_array[cipher_index], &nonce);
-    cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_in_buffer);
+    cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_to_encrypt);
+
+    /* choose a cipher at random from the array*/
+    cipher_index = (*((uint32_t *)enc_buf)) % num_cipher;
   }
   timer = clock() - timer;
 
@@ -451,7 +491,7 @@ cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher,
     return 0;
   }
 
-  return CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
+  return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
 }
 
 void
@@ -459,10 +499,10 @@ cipher_array_test_throughput(cipher_t *ca[], int num_cipher) {
   int i;
   int min_enc_len = 16;     
   int max_enc_len = 2048;   /* should be a power of two */
-  int num_trials = 10000;
+  int num_trials = 1000000;
 
-  printf("timing %s throughput with array size %d:\n", 
-        (ca[0])->type->description, num_cipher);
+  printf("timing %s throughput with key length %d, array size %d:\n", 
+        (ca[0])->type->description, (ca[0])->key_len, num_cipher);
   fflush(stdout);
   for (i=min_enc_len; i <= max_enc_len; i = i * 4)
     printf("msg len: %d\tgigabits per second: %f\n", i,
diff --git a/libs/srtp/crypto/test/datatypes_driver b/libs/srtp/crypto/test/datatypes_driver
new file mode 100755 (executable)
index 0000000..8f32a62
Binary files /dev/null and b/libs/srtp/crypto/test/datatypes_driver differ
index f8e34ef942fc7192778461f7fa22859d0402ae96..f1866524c7e74729f4de7686510e201028448e23 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 07b6f515275e1fbd0b891269ff0102a8d8182f5d..37a6e2731b5436b3c6397cb9b1cc0a930b4a021c 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 4271f8ee68f44d4a0635fd8f418c266e66cab6ef..8ef8a5f4b35ca6a79706d0d3c86926e1acd20e72 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index 8fcf89cd6657d01ffffcfd732db3744841b14432..ccea097f266658868319332175717d4500e2f82b 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
diff --git a/libs/srtp/crypto/test/sha1_driver b/libs/srtp/crypto/test/sha1_driver
new file mode 100755 (executable)
index 0000000..2e9b028
Binary files /dev/null and b/libs/srtp/crypto/test/sha1_driver differ
index f7cb6ca2a6be32d0425a506ff6a95e5017efcc1d..6036022e93c9b2d4c76a1dcfb939e9d086cca38b 100644 (file)
@@ -113,17 +113,17 @@ sha1_test_case_validate(const hash_test_case_t *test_case) {
   if (0 == memcmp(test_case->hash, hash_value, 20)) {
 #if VERBOSE
     printf("PASSED: reference value: %s\n", 
-          octet_string_hex_string((uint8_t *)test_case->hash, 20));
+          octet_string_hex_string((const uint8_t *)test_case->hash, 20));
     printf("PASSED: computed value:  %s\n", 
-          octet_string_hex_string((uint8_t *)hash_value, 20));   
+          octet_string_hex_string((const uint8_t *)hash_value, 20));   
 #endif 
     return err_status_ok;
   }
 
   printf("reference value: %s\n", 
-        octet_string_hex_string((uint8_t *)test_case->hash, 20));
+        octet_string_hex_string((const uint8_t *)test_case->hash, 20));
   printf("computed value:  %s\n", 
-        octet_string_hex_string((uint8_t *)hash_value, 20));
+        octet_string_hex_string((const uint8_t *)hash_value, 20));
 
   return err_status_algo_fail;
   
@@ -136,7 +136,7 @@ struct hex_sha1_test_case_t {
 };
 
 err_status_t
-sha1_add_test_cases() {
+sha1_add_test_cases(void) {
   int i;
   err_status_t err;
 
@@ -485,6 +485,21 @@ sha1_add_test_cases() {
   return err_status_ok;
 }
 
+err_status_t
+sha1_dealloc_test_cases(void) {
+  hash_test_case_t *t, *next;
+
+  for (t = sha1_test_case_list; t != NULL; t = next) {
+    next = t->next_test_case;
+    free(t);
+  }
+
+  sha1_test_case_list = NULL;
+
+  return err_status_ok;
+}
+
+
 
 err_status_t
 sha1_validate(void) {
@@ -510,6 +525,8 @@ sha1_validate(void) {
     test_case = test_case->next_test_case;
   }
 
+  sha1_dealloc_test_cases();
+
   return err_status_ok;
 }
 
diff --git a/libs/srtp/crypto/test/stat_driver b/libs/srtp/crypto/test/stat_driver
new file mode 100755 (executable)
index 0000000..753df31
Binary files /dev/null and b/libs/srtp/crypto/test/stat_driver differ
index 09cc44a6462467ba4fe23a332bfd1bfa8c473d87..f9d75b76562c6d33c6f7b5bfa568aa793db09682 100644 (file)
@@ -37,7 +37,9 @@ main (int argc, char *argv[]) {
   int i, j;
   extern cipher_type_t aes_icm;
   cipher_t *c;
-  uint8_t key[30] = {
+  uint8_t key[46] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
@@ -97,5 +99,41 @@ main (int argc, char *argv[]) {
   printf("(nota bene: a small fraction of stat_test failures does not \n"
         "indicate that the random source is invalid)\n");
 
+  err_check(cipher_dealloc(c));
+
+  printf("running stat_tests on AES-256-ICM, expecting success\n");
+  /* set buffer to cipher output */
+  for (i=0; i < 2500; i++)
+    buffer[i] = 0;
+  err_check(cipher_type_alloc(&aes_icm, &c, 46));
+  err_check(cipher_init(c, key, direction_encrypt));
+  err_check(cipher_set_iv(c, &nonce));
+  err_check(cipher_encrypt(c, buffer, &buf_len));
+  /* run tests on cipher outout */
+  printf("monobit %d\n", stat_test_monobit(buffer));
+  printf("poker   %d\n", stat_test_poker(buffer));
+  printf("runs    %d\n", stat_test_runs(buffer));
+
+  printf("runs test (please be patient): ");
+  fflush(stdout);
+  num_fail = 0;
+  v128_set_to_zero(&nonce);
+  for(j=0; j < num_trials; j++) {
+    for (i=0; i < 2500; i++)
+      buffer[i] = 0;
+    nonce.v32[3] = i;
+    err_check(cipher_set_iv(c, &nonce));
+    err_check(cipher_encrypt(c, buffer, &buf_len));
+    if (stat_test_runs(buffer)) {
+      num_fail++;
+    }
+  }
+
+  printf("%d failures in %d tests\n", num_fail, num_trials);
+  printf("(nota bene: a small fraction of stat_test failures does not \n"
+        "indicate that the random source is invalid)\n");
+
+  err_check(cipher_dealloc(c));
+
   return 0;
 }
index fc6ac95e1100e4e88bb7271bf0e12b96437c74ac..c6e6a6d238f7139895384ae2d08c6d6f83b358f0 100644 (file)
@@ -346,7 +346,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = intro.txt ../include/srtp.h ../crypto/include/crypto_types.h ../crypto/include/err.h ../crypto/include/crypto_kernel.h  crypto_kernel.txt 
+INPUT                  = intro.txt ../include/srtp.h ../crypto/include/crypto_types.h ../crypto/include/err.h ../crypto/include/crypto.h  crypto_kernel.txt 
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
index bb1200e92bac04c220633c30177f571d118b664c..2c0b96d46f0a4d56f2d0997e0ebb5c4c0d58a46d 100644 (file)
@@ -86,14 +86,17 @@ libSRTP LIBSRTPVERSION Overview and Reference Manual\\
 
 The original implementation and documentation of libSRTP was written
 by David McGrew of Cisco Systems, Inc. in order to promote the use,
-understanding, and interoperability of Secure RTP.  Randell Jesup
-contributed a working SRTCP implementation and other fixes.  Alex
-Vanzella and Will Clark contributed changes so that the AES ICM
-implementation can be used for ISMA media encryption.  Steve Underwood
-contributed x86\_64 portability changes.  We also give thanks to Brian
-Weis, Mark Baugher, Jeff Chan, Bill Simon, Douglas Smith, Bill May,
-Richard Preistley, Joe Tardo and others for contributions, comments,
-and corrections.
+understanding, and interoperability of Secure RTP.  Michael Jerris
+contributed support for building under MSVC.  Andris Pavenis
+contributed many important fixes.  Brian West contributed changes to
+enable dynamic linking.  Yves Shumann reported documentation bugs.
+Randell Jesup contributed a working SRTCP implementation and other
+fixes.  Alex Vanzella and Will Clark contributed changes so that the
+AES ICM implementation can be used for ISMA media encryption.  Steve
+Underwood contributed x86\_64 portability changes.  We also give
+thanks to Fredrik Thulin, Brian Weis, Mark Baugher, Jeff Chan, Bill
+Simon, Douglas Smith, Bill May, Richard Preistley, Joe Tardo and
+others for contributions, comments, and corrections.
 
 This reference material in this documenation was generated using the
 \texttt{doxygen} utility for automatic documentation of source code.
index f3155992550802ba280dbc27fcefa198a1c85622..e8607d1c132f8831569cc7244b969c20f3464ee5 100644 (file)
@@ -5,10 +5,10 @@
 This document describes libSRTP, the Open Source Secure RTP library
 from Cisco Systems, Inc.  RTP is the Real-time Transport Protocol, an
 IETF standard for the transport of real-time data such as telephony,
-audio, and video, defined by RFC1889.  Secure RTP (SRTP) is an RTP
+audio, and video, defined by RFC 3550.  Secure RTP (SRTP) is an RTP
 profile for providing confidentiality to RTP data and authentication
-to the RTP header and payload.  SRTP is an IETF Proposed Standard, and
-is defined in RFC 3711, and was developed in the IETF Audio/Video
+to the RTP header and payload.  SRTP is an IETF Proposed Standard,
+defined in RFC 3711, and was developed in the IETF Audio/Video
 Transport (AVT) Working Group.  This library supports all of the
 mandatory features of SRTP, but not all of the optional features.  See
 the @ref Features section for more detailed information.
@@ -110,7 +110,7 @@ the minor release number, and \texttt{tgz} is the file
 extension\footnote{The extension \texttt{.tgz} is identical to
 \texttt{tar.gz}, and indicates a compressed tar file.}  You probably
 want to get the most recent release.  Unpack the distribution and
-extract the source files; the directory into which the soruce files
+extract the source files; the directory into which the source files
 will go is named \texttt{srtp}.
 
 libSRTP uses the GNU \texttt{autoconf} and \texttt{make}
@@ -135,7 +135,7 @@ The configure script accepts the following options:
 \end{description}
 \end{quote}
 
-By default, dynamic debbuging is enabled and stdout is used for
+By default, dynamic debugging is enabled and stdout is used for
 debugging.  You can use the configure options to have the debugging
 output sent to syslog or the system console.  Alternatively, you can
 define ERR\_REPORTING\_FILE in \texttt{include/conf.h} to be any other
@@ -181,7 +181,7 @@ using gdoi will be added later.
 The usage for rtpw is
 
 \texttt{rtpw [[-d $<$debug$>$]* [-k $<$key$>$ [-a][-e]] [-s | -r] dest\_ip
-dest\_port][-l]}
+dest\_port] | [-l]}
 
 Either the -s (sender) or -r (receiver) option must be chosen.  The
 values dest\_ip, dest\_port are the IP address and UDP port to which
@@ -189,7 +189,7 @@ the dictionary will be sent, respectively.  The options are:
 \begin{center}
 \begin{tabular}{ll}
   -s           & (S)RTP sender - causes app to send words \\
-  -r           & (S)RTP receive - causes app to receve words \\
+  -r           & (S)RTP receive - causes app to receive words \\
   -k $<$key$>$      & use SRTP master key $<$key$>$, where the 
                key is a hexadecimal value (without the
                 leading "0x") \\
@@ -197,7 +197,7 @@ the dictionary will be sent, respectively.  The options are:
                 (requires use of -k option as well)\\
   -a            & message authentication 
                 (requires use of -k option as well) \\
-  -l            & list the avaliable debug modules \\
+  -l            & list the available debug modules \\
   -d $<$debug$>$    & turn on debugging for module $<$debug$>$ \\
 \end{tabular}
 \end{center}
@@ -359,7 +359,7 @@ length as its second argument.
    crypto_get_random(key, 30);          
 
    // allocate and initialize the SRTP session 
-   srtp_create(&session, policy);  
+   srtp_create(&session, &policy);  
    
    // main loop: get rtp packets, send srtp packets
    while (1) {
index 0538ab4551f293e0fc497a8b98237731d4f18d5c..6f5e448e89ae34b31c2973641d402f5bf982ee64 100644 (file)
Binary files a/libs/srtp/doc/libsrtp.pdf and b/libs/srtp/doc/libsrtp.pdf differ
diff --git a/libs/srtp/include/ekt.h b/libs/srtp/include/ekt.h
new file mode 100644 (file)
index 0000000..b0d888b
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * ekt.h
+ *
+ * interface to Encrypted Key Transport for SRTP
+ *
+ * David McGrew
+ * Cisco Systems, Inc.
+ */
+/*
+ *     
+ * Copyright (c) 2001-2005 Cisco Systems, Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *   Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 
+ *   Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ * 
+ *   Neither the name of the Cisco Systems, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+/*
+ * EKT implementation strategy 
+ * 
+ * use stream_template approach
+ *
+ * in srtp_unprotect, when a new stream appears, check if template has
+ * EKT defined, and if it does, then apply EKT processing 
+ *
+ * question: will we want to allow key-sharing templates in addition
+ * to EKT templates?  could define a new ssrc_type_t that's associated
+ * with an EKT, e.g.  ssrc_any_ekt.
+ *
+ *
+ */
+
+#ifndef EKT_H
+#define EKT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "srtp_priv.h"
+
+#define EKT_CIPHER_DEFAULT           1
+#define EKT_CIPHER_AES_128_ECB       1
+#define EKT_CIPHER_AES_192_KEY_WRAP  2
+#define EKT_CIPHER_AES_256_KEY_WRAP  3
+
+typedef uint16_t ekt_spi_t;
+
+
+unsigned
+ekt_octets_after_base_tag(ekt_stream_t ekt);
+
+/*
+ * an srtp_policy_t structure can contain a pointer to an
+ * ekt_policy_t structure
+ *
+ * this structure holds all of the high level EKT information, and it
+ * is passed into libsrtp to indicate what policy should be in effect
+ */
+
+typedef struct ekt_policy_ctx_t {
+  ekt_spi_t  spi;     /* security parameter index */
+  uint8_t    ekt_cipher_type;
+  uint8_t   *ekt_key;
+  struct ekt_policy_ctx_t *next_ekt_policy;
+} ekt_policy_ctx_t;
+
+
+/*
+ * an ekt_data_t structure holds the data corresponding to an ekt key,
+ * spi, and so on
+ */
+
+typedef struct ekt_data_t {
+  ekt_spi_t spi;
+  uint8_t ekt_cipher_type;
+  aes_expanded_key_t ekt_enc_key;
+  aes_expanded_key_t ekt_dec_key;
+  struct ekt_data_t *next_ekt_data;
+} ekt_data_t;
+
+/*
+ * an srtp_stream_ctx_t can contain an ekt_stream_ctx_t
+ *
+ * an ekt_stream_ctx_t structure holds all of the EKT information for
+ * a specific SRTP stream
+ */
+
+typedef struct ekt_stream_ctx_t {
+  ekt_data_t *data;    
+  uint16_t    isn;     /* initial sequence number  */
+  uint8_t     encrypted_master_key[SRTP_MAX_KEY_LEN];
+} ekt_stream_ctx_t;
+
+
+
+err_status_t 
+ekt_alloc(ekt_stream_t *stream_data, ekt_policy_t policy);
+
+err_status_t
+ekt_stream_init(ekt_stream_t e, 
+               ekt_spi_t spi,
+               void *ekt_key,
+               unsigned ekt_cipher_type);
+
+err_status_t
+ekt_stream_init_from_policy(ekt_stream_t e, ekt_policy_t p);
+  
+
+
+err_status_t
+srtp_stream_init_from_ekt(srtp_stream_t stream,                          
+                         const void *srtcp_hdr,
+                         unsigned pkt_octet_len);
+               
+
+void
+ekt_write_data(ekt_stream_t ekt,
+              uint8_t *base_tag, 
+              unsigned base_tag_len, 
+              int *packet_len,
+              xtd_seq_num_t pkt_index);                
+
+/*
+ * We handle EKT by performing some additional steps before
+ * authentication (copying the auth tag into a temporary location,
+ * zeroizing the "base tag" field in the packet)
+ *
+ * With EKT, the tag_len parameter is actually the base tag
+ * length
+ */
+
+err_status_t
+ekt_tag_verification_preproces(uint8_t *pkt_tag, 
+                              uint8_t *pkt_tag_copy, 
+                              unsigned tag_len);
+
+err_status_t
+ekt_tag_verification_postproces(uint8_t *pkt_tag,
+                               uint8_t *pkt_tag_copy,
+                               unsigned tag_len);
+
+
+/*
+ * @brief EKT pre-processing for srtcp tag generation
+ *
+ * This function does the pre-processing of the SRTCP authentication
+ * tag format.  When EKT is used, it consists of writing the Encrypted
+ * Master Key, the SRTP ROC, the Initial Sequence Number, and SPI
+ * fields.  The Base Authentication Tag field is set to the all-zero
+ * value
+ * 
+ * When EKT is not used, this function is a no-op.
+ * 
+ */
+
+err_status_t
+srtp_stream_srtcp_auth_tag_generation_preprocess(const srtp_stream_t *s,
+                                                uint8_t *pkt_tag,
+                                                unsigned pkt_octet_len);
+
+/* it's not clear that a tag_generation_postprocess function is needed */
+
+err_status_t
+srtcp_auth_tag_generation_postprocess(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EKT_H */
diff --git a/libs/srtp/include/getopt_s.h b/libs/srtp/include/getopt_s.h
new file mode 100644 (file)
index 0000000..2a6ece3
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * getopt.h
+ *
+ * interface to a minimal implementation of the getopt() function,
+ * written so that test applications that use that function can run on
+ * non-POSIX platforms
+ *
+ */
+/*
+ *     
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *   Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 
+ *   Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ * 
+ *   Neither the name of the Cisco Systems, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GETOPT_S_H
+#define GETOPT_S_H
+
+/* 
+ * getopt_s(), optarg_s, and optind_s are small, locally defined
+ * versions of the POSIX standard getopt() interface.
+ */
+int
+getopt_s(int argc, char * const argv[], const char *optstring);
+
+extern char *optarg_s;    /* defined in getopt.c */
+
+extern int optind_s;      /* defined in getopt.c */
+
+#endif /* GETOPT_S_H */
index 65975ff35b47fd92b23e0bc83c643a9894930c9b..0e0119cf7bb191ed7d2b9e98dcdf946fd5d4fc3e 100644 (file)
@@ -16,7 +16,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 #ifndef RTP_H
 #define RTP_H
 
-#include "srtp.h"
-
 #ifdef HAVE_NETINET_IN_H
 # include <netinet/in.h>
 #elif defined HAVE_WINSOCK2_H
 # include <winsock2.h>
 #endif
 
-#define rtp_header_len 12
-
-typedef srtp_hdr_t rtp_hdr_t;
-
-#define RTP_MAX_BUF_LEN 16384
-
-typedef struct {
-  srtp_hdr_t header;        
-  char body[RTP_MAX_BUF_LEN];  
-} rtp_msg_t;
-
-typedef struct {
-  rtp_msg_t message;         
-  int socket;
-  srtp_ctx_t *srtp_ctx;
-  struct sockaddr_in addr;   /* reciever's address */
-} rtp_sender_t;
+#include "srtp.h"
 
-typedef struct {
-  rtp_msg_t message;
-  int socket;
-  srtp_ctx_t *srtp_ctx;
-  struct sockaddr_in addr;   /* receiver's address */
-} rtp_receiver_t;
+typedef struct rtp_sender_ctx_t *rtp_sender_t;
 
+typedef struct rtp_receiver_ctx_t *rtp_receiver_t;
 
-ssize_t
-rtp_sendto(rtp_sender_t *sender, const void* msg, int len);
+int
+rtp_sendto(rtp_sender_t sender, const void* msg, int len);
 
-ssize_t
-rtp_recvfrom(rtp_receiver_t *receiver, void *msg, int *len);
+int
+rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len);
 
 int
-rtp_receiver_init(rtp_receiver_t *rcvr, int socket
-                 struct sockaddr_in addr, uint32_t ssrc);
+rtp_receiver_init(rtp_receiver_t rcvr, int sock
+                 struct sockaddr_in addr, unsigned int ssrc);
 
 int
-rtp_sender_init(rtp_sender_t *sender, int socket
-               struct sockaddr_in addr, uint32_t ssrc);
+rtp_sender_init(rtp_sender_t sender, int sock
+               struct sockaddr_in addr, unsigned int ssrc);
 
 /*
  * srtp_sender_init(...) initializes an rtp_sender_t
- *
  */
 
 int
-srtp_sender_init(rtp_sender_t *rtp_ctx,         /* structure to be init'ed */
+srtp_sender_init(rtp_sender_t rtp_ctx,          /* structure to be init'ed */
                 struct sockaddr_in name,       /* socket name             */
                 sec_serv_t security_services,  /* sec. servs. to be used  */
                 unsigned char *input_key       /* master key/salt in hex  */
                 );
 
 int
-srtp_receiver_init(rtp_receiver_t *rtp_ctx,      /* structure to be init'ed */
+srtp_receiver_init(rtp_receiver_t rtp_ctx,       /* structure to be init'ed */
                   struct sockaddr_in name,      /* socket name             */
                   sec_serv_t security_services, /* sec. servs. to be used  */
                   unsigned char *input_key      /* master key/salt in hex  */
                   );
 
 
+int
+rtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy);
+
+int
+rtp_sender_deinit_srtp(rtp_sender_t sender);
+
+int
+rtp_receiver_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy);
+
+int
+rtp_receiver_deinit_srtp(rtp_receiver_t sender);
+
+
+rtp_sender_t 
+rtp_sender_alloc(void);
+
+void
+rtp_sender_dealloc(rtp_sender_t rtp_ctx);
+
+rtp_receiver_t 
+rtp_receiver_alloc(void);
+
+void
+rtp_receiver_dealloc(rtp_receiver_t rtp_ctx);
+
+
+/*
+ * RTP_HEADER_LEN indicates the size of an RTP header
+ */
+#define RTP_HEADER_LEN   12
+
+/* 
+ * RTP_MAX_BUF_LEN defines the largest RTP packet in the rtp.c implementation
+ */
+#define RTP_MAX_BUF_LEN  16384
+
+
 #endif /* RTP_H */
diff --git a/libs/srtp/include/rtp_priv.h b/libs/srtp/include/rtp_priv.h
new file mode 100644 (file)
index 0000000..1421386
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * rtp_priv.h
+ *
+ * private, internal header file for RTP
+ *
+ * David A. McGrew
+ * Cisco Systems, Inc.
+ */
+/*
+ *     
+ * Copyright (c) 2001-2006 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 RTP_PRIV_H
+#define RTP_PRIV_H
+
+#include "srtp_priv.h"
+#include "rtp.h"
+
+typedef srtp_hdr_t rtp_hdr_t;
+
+typedef struct {
+  srtp_hdr_t header;        
+  char body[RTP_MAX_BUF_LEN];  
+} rtp_msg_t;
+
+typedef struct rtp_sender_ctx_t {
+  rtp_msg_t message;         
+  int socket;
+  srtp_ctx_t *srtp_ctx;
+  struct sockaddr_in addr;   /* reciever's address */
+} rtp_sender_ctx_t;
+
+typedef struct rtp_receiver_ctx_t {
+  rtp_msg_t message;
+  int socket;
+  srtp_ctx_t *srtp_ctx;
+  struct sockaddr_in addr;   /* receiver's address */
+} rtp_receiver_ctx_t;
+
+
+#endif /* RTP_PRIV_H */
index cb78f7e9c96a7817ad91db2d5a936a9a1615030b..eb95e7d47780b2b311bd7b4d9c835f8b2fa77fed 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 extern "C" {
 #endif
 
-#ifdef _MSC_VER
-#pragma warning(disable:4214)
-#endif
-
-#include "crypto_kernel.h"
-#include "rdbx.h"
-#include "rdb.h"
-#include "integers.h"
+#include "crypto_kernel.h" 
 
 /**
  * @defgroup SRTP Secure RTP
@@ -171,10 +164,22 @@ typedef enum {
 
 typedef struct { 
   ssrc_type_t type;   /**< The type of this particular SSRC */
-  uint32_t value;     /**< The value of this SSRC, if it is not a wildcard */
+  unsigned int value; /**< The value of this SSRC, if it is not a wildcard */
 } ssrc_t;
 
 
+/**
+ * @brief points to an EKT policy
+ */
+typedef struct ekt_policy_ctx_t *ekt_policy_t;
+
+
+/**
+ * @brief points to EKT stream data
+ */
+typedef struct ekt_stream_ctx_t *ekt_stream_t;
+
+
 /** 
  * @brief represents the policy for an SRTP session.  
  *
@@ -210,8 +215,18 @@ typedef struct srtp_policy_t {
                              */
   crypto_policy_t rtp;         /**< SRTP crypto policy.                  */
   crypto_policy_t rtcp;        /**< SRTCP crypto policy.                 */
-  uint8_t *key;                /**< Pointer to the SRTP master key for
+  unsigned char *key;          /**< Pointer to the SRTP master key for
                                *    this stream.                        */
+  ekt_policy_t ekt;            /**< Pointer to the EKT policy structure
+                                *   for this stream (if any)             */ 
+  unsigned long window_size;   /**< The window size to use for replay
+                               *   protection. */
+  int        allow_repeat_tx;  /**< Whether retransmissions of
+                               *   packets with the same sequence number
+                               *   are allowed.  (Note that such repeated
+                               *   transmissions must have the same RTP
+                               *   payload, or a severe security weakness
+                               *   is introduced!)                      */
   struct srtp_policy_t *next;  /**< Pointer to next stream policy.       */
 } srtp_policy_t;
 
@@ -260,6 +275,15 @@ typedef struct srtp_stream_ctx_t *srtp_stream_t;
 err_status_t
 srtp_init(void);
 
+/**
+ * @brief srtp_shutdown() de-initializes the srtp library.
+ *
+ * @warning No srtp functions may be called after calling this function.
+ */
+
+err_status_t
+srtp_shutdown(void);
+
 /**
  * @brief srtp_protect() is the Secure RTP sender-side packet processing
  * function.
@@ -413,14 +437,13 @@ srtp_add_stream(srtp_t session,
  */
 
 err_status_t
-srtp_remove_stream(srtp_t session, uint32_t ssrc);
+srtp_remove_stream(srtp_t session, unsigned int ssrc);
 
 /**
  * @brief crypto_policy_set_rtp_default() sets a crypto policy
  * structure to the SRTP default policy for RTP protection.
  *
- * @param p is a pointer to the policy strucutre to be set to the
- * default policy.
+ * @param p is a pointer to the policy structure to be set 
  * 
  * The function call crypto_policy_set_rtp_default(&p) sets the
  * crypto_policy_t at location p to the SRTP default policy for RTP
@@ -442,8 +465,7 @@ crypto_policy_set_rtp_default(crypto_policy_t *p);
  * @brief crypto_policy_set_rtcp_default() sets a crypto policy
  * structure to the SRTP default policy for RTCP protection.
  *
- * @param p is a pointer to the policy strucutre to be set to the
- * default policy.
+ * @param p is a pointer to the policy structure to be set 
  * 
  * The function call crypto_policy_set_rtcp_default(&p) sets the
  * crypto_policy_t at location p to the SRTP default policy for RTCP
@@ -465,13 +487,12 @@ crypto_policy_set_rtcp_default(crypto_policy_t *p);
  * @brief crypto_policy_set_aes_cm_128_hmac_sha1_80() sets a crypto
  * policy structure to the SRTP default policy for RTP protection.
  *
- * @param p is a pointer to the policy strucutre to be set to the
- * default policy.
+ * @param p is a pointer to the policy structure to be set 
  * 
  * The function crypto_policy_set_aes_cm_128_hmac_sha1_80() is a
  * synonym for crypto_policy_set_rtp_default().  It conforms to the
- * naming convention used in
- * http://www.ietf.org/internet-drafts/draft-ietf-mmusic-sdescriptions-12.txt
+ * naming convention used in RFC 4568 (SDP Security Descriptions for
+ * Media Streams).
  * 
  * @return void.
  * 
@@ -484,13 +505,12 @@ crypto_policy_set_rtcp_default(crypto_policy_t *p);
  * @brief crypto_policy_set_aes_cm_128_hmac_sha1_32() sets a crypto
  * policy structure to a short-authentication tag policy
  *
- * @param p is a pointer to the policy strucutre to be set to the
- * default policy.
+ * @param p is a pointer to the policy structure to be set 
  * 
  * The function call crypto_policy_set_aes_cm_128_hmac_sha1_32(&p)
  * sets the crypto_policy_t at location p to use policy
- * AES_CM_128_HMAC_SHA1_32 as defined in
- * draft-ietf-mmusic-sdescriptions-12.txt.  This policy uses AES-128
+ * AES_CM_128_HMAC_SHA1_32 as defined in RFC 4568.
+ * This policy uses AES-128
  * Counter Mode encryption and HMAC-SHA1 authentication, with an
  * authentication tag that is only 32 bits long.  This length is
  * considered adequate only for protecting audio and video media that
@@ -521,8 +541,7 @@ crypto_policy_set_aes_cm_128_hmac_sha1_32(crypto_policy_t *p);
  * @brief crypto_policy_set_aes_cm_128_null_auth() sets a crypto
  * policy structure to an encryption-only policy
  *
- * @param p is a pointer to the policy strucutre to be set to the
- * default policy.
+ * @param p is a pointer to the policy structure to be set 
  * 
  * The function call crypto_policy_set_aes_cm_128_null_auth(&p) sets
  * the crypto_policy_t at location p to use the SRTP default cipher
@@ -552,8 +571,7 @@ crypto_policy_set_aes_cm_128_null_auth(crypto_policy_t *p);
  * @brief crypto_policy_set_null_cipher_hmac_sha1_80() sets a crypto
  * policy structure to an authentication-only policy
  *
- * @param p is a pointer to the policy strucutre to be set to the
- * default policy.
+ * @param p is a pointer to the policy structure to be set 
  * 
  * The function call crypto_policy_set_null_cipher_hmac_sha1_80(&p)
  * sets the crypto_policy_t at location p to use HMAC-SHA1 with an 80
@@ -577,6 +595,70 @@ crypto_policy_set_aes_cm_128_null_auth(crypto_policy_t *p);
 void
 crypto_policy_set_null_cipher_hmac_sha1_80(crypto_policy_t *p);
 
+
+/**
+ * @brief crypto_policy_set_aes_cm_256_hmac_sha1_80() sets a crypto
+ * policy structure to a encryption and authentication policy using AES-256 
+ * for RTP protection.
+ *
+ * @param p is a pointer to the policy structure to be set 
+ * 
+ * The function call crypto_policy_set_aes_cm_256_hmac_sha1_80(&p)
+ * sets the crypto_policy_t at location p to use policy
+ * AES_CM_256_HMAC_SHA1_80 as defined in
+ * draft-ietf-avt-srtp-big-aes-03.txt.  This policy uses AES-256
+ * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit
+ * authentication tag.
+ * 
+ * This function is a convenience that helps to avoid dealing directly
+ * with the policy data structure.  You are encouraged to initialize
+ * policy elements with this function call.  Doing so may allow your
+ * code to be forward compatible with later versions of libSRTP that
+ * include more elements in the crypto_policy_t datatype.
+ *
+ * @return void.
+ * 
+ */
+
+void crypto_policy_set_aes_cm_256_hmac_sha1_80(crypto_policy_t *p);
+
+
+/**
+ * @brief crypto_policy_set_aes_cm_256_hmac_sha1_32() sets a crypto
+ * policy structure to a short-authentication tag policy using AES-256
+ * encryption.
+ *
+ * @param p is a pointer to the policy structure to be set 
+ * 
+ * The function call crypto_policy_set_aes_cm_256_hmac_sha1_32(&p)
+ * sets the crypto_policy_t at location p to use policy
+ * AES_CM_256_HMAC_SHA1_32 as defined in
+ * draft-ietf-avt-srtp-big-aes-03.txt.  This policy uses AES-256
+ * Counter Mode encryption and HMAC-SHA1 authentication, with an
+ * authentication tag that is only 32 bits long.  This length is
+ * considered adequate only for protecting audio and video media that
+ * use a stateless playback function.  See Section 7.5 of RFC 3711
+ * (http://www.ietf.org/rfc/rfc3711.txt).
+ * 
+ * This function is a convenience that helps to avoid dealing directly
+ * with the policy data structure.  You are encouraged to initialize
+ * policy elements with this function call.  Doing so may allow your
+ * code to be forward compatible with later versions of libSRTP that
+ * include more elements in the crypto_policy_t datatype.
+ *
+ * @warning This crypto policy is intended for use in SRTP, but not in
+ * SRTCP.  It is recommended that a policy that uses longer
+ * authentication tags be used for SRTCP.  See Section 7.5 of RFC 3711
+ * (http://www.ietf.org/rfc/rfc3711.txt).
+ *
+ * @return void.
+ * 
+ */
+
+void
+crypto_policy_set_aes_cm_256_hmac_sha1_32(crypto_policy_t *p);
+
+
 /**
  * @brief srtp_dealloc() deallocates storage for an SRTP session
  * context.
@@ -597,68 +679,112 @@ err_status_t
 srtp_dealloc(srtp_t s);
 
 
-
-/**
- * @}
+/*
+ * @brief identifies a particular SRTP profile 
+ *
+ * An srtp_profile_t enumeration is used to identify a particular SRTP
+ * profile (that is, a set of algorithms and parameters).  These
+ * profiles are defined in the DTLS-SRTP draft.
  */
 
+typedef enum {
+  srtp_profile_reserved           = 0,
+  srtp_profile_aes128_cm_sha1_80  = 1,
+  srtp_profile_aes128_cm_sha1_32  = 2,
+  srtp_profile_aes256_cm_sha1_80  = 3,
+  srtp_profile_aes256_cm_sha1_32  = 4,
+  srtp_profile_null_sha1_80       = 5,
+  srtp_profile_null_sha1_32       = 6,
+} srtp_profile_t;
 
-/*
- * the following declarations are libSRTP internal functions 
- */
 
-/*
- * srtp_get_stream(ssrc) returns a pointer to the stream corresponding
- * to ssrc, or NULL if no stream exists for that ssrc
+/**
+ * @brief crypto_policy_set_from_profile_for_rtp() sets a crypto policy
+ * structure to the appropriate value for RTP based on an srtp_profile_t
+ *
+ * @param p is a pointer to the policy structure to be set 
+ * 
+ * The function call crypto_policy_set_rtp_default(&policy, profile)
+ * sets the crypto_policy_t at location policy to the policy for RTP
+ * protection, as defined by the srtp_profile_t profile.
+ * 
+ * This function is a convenience that helps to avoid dealing directly
+ * with the policy data structure.  You are encouraged to initialize
+ * policy elements with this function call.  Doing so may allow your
+ * code to be forward compatible with later versions of libSRTP that
+ * include more elements in the crypto_policy_t datatype.
+ * 
+ * @return values
+ *     - err_status_ok         no problems were encountered
+ *     - err_status_bad_param  the profile is not supported 
+ * 
  */
+err_status_t
+crypto_policy_set_from_profile_for_rtp(crypto_policy_t *policy, 
+                                      srtp_profile_t profile);
 
-srtp_stream_t 
-srtp_get_stream(srtp_t srtp, uint32_t ssrc);
 
 
 
-/*
- * libsrtp internal datatypes 
+/**
+ * @brief crypto_policy_set_from_profile_for_rtcp() sets a crypto policy
+ * structure to the appropriate value for RTCP based on an srtp_profile_t
+ *
+ * @param p is a pointer to the policy structure to be set 
+ * 
+ * The function call crypto_policy_set_rtcp_default(&policy, profile)
+ * sets the crypto_policy_t at location policy to the policy for RTCP
+ * protection, as defined by the srtp_profile_t profile.
+ * 
+ * This function is a convenience that helps to avoid dealing directly
+ * with the policy data structure.  You are encouraged to initialize
+ * policy elements with this function call.  Doing so may allow your
+ * code to be forward compatible with later versions of libSRTP that
+ * include more elements in the crypto_policy_t datatype.
+ * 
+ * @return values
+ *     - err_status_ok         no problems were encountered
+ *     - err_status_bad_param  the profile is not supported 
+ * 
+ */
+err_status_t
+crypto_policy_set_from_profile_for_rtcp(crypto_policy_t *policy, 
+                                      srtp_profile_t profile);
+
+/**
+ * @brief returns the master key length for a given SRTP profile
  */
+unsigned int
+srtp_profile_get_master_key_length(srtp_profile_t profile);
 
-typedef enum direction_t { 
-  dir_unknown       = 0,
-  dir_srtp_sender   = 1, 
-  dir_srtp_receiver = 2
-} direction_t;
 
-/* 
- * an srtp_stream_t has its own SSRC, encryption key, authentication
- * key, sequence number, and replay database
+/**
+ * @brief returns the master salt length for a given SRTP profile
+ */
+unsigned int
+srtp_profile_get_master_salt_length(srtp_profile_t profile);
+
+/**
+ * @brief appends the salt to the key
+ *
+ * The function call append_salt_to_key(k, klen, s, slen) 
+ * copies the string s to the location at klen bytes following
+ * the location k.  
+ *
+ * @warning There must be at least bytes_in_salt + bytes_in_key bytes
+ *          available at the location pointed to by key.
  * 
- * note that the keys might not actually be unique, in which case the
- * cipher_t and auth_t pointers will point to the same structures
  */
 
-typedef struct srtp_stream_ctx_t {
-  uint32_t   ssrc;
-  cipher_t  *rtp_cipher;
-  auth_t    *rtp_auth;
-  rdbx_t     rtp_rdbx;
-  sec_serv_t rtp_services;
-  cipher_t  *rtcp_cipher;
-  auth_t    *rtcp_auth;
-  rdb_t      rtcp_rdb;
-  sec_serv_t rtcp_services;
-  key_limit_ctx_t *limit;
-  direction_t direction;
-  struct srtp_stream_ctx_t *next;   /* linked list of streams */
-} srtp_stream_ctx_t;
+void
+append_salt_to_key(unsigned char *key, unsigned int bytes_in_key,
+                  unsigned char *salt, unsigned int bytes_in_salt);
 
 
-/*
- * an srtp_ctx_t holds a stream list and a service description
- */
 
-typedef struct srtp_ctx_t {
-  srtp_stream_ctx_t *stream_list;     /* linked list of streams            */
-  srtp_stream_ctx_t *stream_template; /* act as template for other streams */
-} srtp_ctx_t;
+/**
+ * @}
+ */
 
 
 
@@ -867,137 +993,12 @@ srtp_install_event_handler(srtp_event_handler_func_t func);
 /**
  * @}
  */
-
-/*
- * srtp_handle_event(srtp, srtm, evnt) calls the event handling
- * function, if there is one.
- *
- * This macro is not included in the documentation as it is 
- * an internal-only function.
- */
-
-#define srtp_handle_event(srtp, strm, evnt)         \
-   if(srtp_event_handler) {                         \
-      srtp_event_data_t data;                       \
-      data.session = srtp;                          \
-      data.stream  = strm;                          \
-      data.event   = evnt;                          \
-      srtp_event_handler(&data);                    \
-}   
-
-/*
- * an srtp_hdr_t represents the srtp header
- *
- * in this implementation, an srtp_hdr_t is assumed to be 32-bit aligned
- * 
- * (note that this definition follows that of RFC 1889 Appendix A, but
- * is not identical)
- */
-#ifdef _MSC_VER
-#pragma pack(push, r1, 1)
-#endif
-
-#ifndef WORDS_BIGENDIAN
-
-typedef struct {
-  unsigned cc:4;       /* CSRC count             */
-  unsigned x:1;                /* header extension flag  */
-  unsigned p:1;                /* padding flag           */
-  unsigned version:2;  /* protocol version       */
-  unsigned pt:7;       /* payload type           */
-  unsigned m:1;                /* marker bit             */
-  unsigned seq:16;             /* sequence number        */
-  unsigned ts:32;              /* timestamp              */
-  unsigned ssrc:32;    /* synchronization source */
-} srtp_hdr_t;
-
-#else /*  BIG_ENDIAN */
-
-typedef struct {
-  unsigned version:2;  /* protocol version       */
-  unsigned p:1;                /* padding flag           */
-  unsigned x:1;                /* header extension flag  */
-  unsigned cc:4;       /* CSRC count             */
-  unsigned m:1;                /* marker bit             */
-  unsigned pt:7;       /* payload type           */
-  unsigned seq:16;             /* sequence number        */
-  unsigned ts:32;              /* timestamp              */
-  unsigned ssrc:32;    /* synchronization source */
-} srtp_hdr_t;
-
-#endif
-
-typedef struct {
-  uint16_t profile_specific;    /* profile-specific info               */
-  uint16_t length;              /* number of 32-bit words in extension */
-} srtp_hdr_xtnd_t;
-
-
-/*
- * srtcp_hdr_t represents a secure rtcp header 
- *
- * in this implementation, an srtcp header is assumed to be 32-bit
- * alinged
- */
-
-#ifndef WORDS_BIGENDIAN
-
-typedef struct {
-  unsigned rc:5;               /* reception report count */
-  unsigned p:1;                /* padding flag           */
-  unsigned version:2;  /* protocol version       */
-  unsigned pt:8;               /* payload type           */
-  unsigned len:16;                     /* length                 */
-  unsigned ssrc:32;            /* synchronization source */
-} srtcp_hdr_t;
-
-typedef struct {
-  unsigned int index:31;    /* srtcp packet index in network order! */
-  unsigned int e:1;         /* encrypted? 1=yes */
-  /* optional mikey/etc go here */
-  /* and then the variable-length auth tag */
-} srtcp_trailer_t;
-
-
-#else /*  BIG_ENDIAN */
-
-typedef struct {
-  unsigned version:2;  /* protocol version       */
-  unsigned p:1;                /* padding flag           */
-  unsigned rc:5;               /* reception report count */
-  unsigned pt:8;               /* payload type           */
-  unsigned len:16;                     /* length                 */
-  unsigned ssrc:32;            /* synchronization source */
-} srtcp_hdr_t;
-
-typedef struct {
-  unsigned int version:2;  /* protocol version                     */
-  unsigned int p:1;        /* padding flag                         */
-  unsigned int count:5;    /* varies by packet type                */
-  unsigned int pt:8;       /* payload type                         */
-  unsigned length:16;         /* len of uint32s of packet less header */
-} rtcp_common_t;
-
-typedef struct {
-  unsigned int e:1;         /* encrypted? 1=yes */
-  unsigned int index:31;    /* srtcp packet index */
-  /* optional mikey/etc go here */
-  /* and then the variable-length auth tag */
-} srtcp_trailer_t;
-
-#endif
-
 /* in host order, so outside the #if */
 #define SRTCP_E_BIT      0x80000000
 /* for byte-access */
 #define SRTCP_E_BYTE_BIT 0x80
 #define SRTCP_INDEX_MASK 0x7fffffff
 
-#ifdef _MSC_VER
-#pragma pack(pop, r1)
-#endif
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/srtp/include/srtp_priv.h b/libs/srtp/include/srtp_priv.h
new file mode 100644 (file)
index 0000000..180a51b
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * srtp_priv.h
+ *
+ * private internal data structures and functions for libSRTP
+ *
+ * David A. McGrew
+ * Cisco Systems, Inc.
+ */
+/*
+ *     
+ * Copyright (c) 2001-2006 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_PRIV_H
+#define SRTP_PRIV_H
+
+#include "srtp.h"
+#include "rdbx.h"
+#include "rdb.h"
+#include "integers.h"
+
+/*
+ * an srtp_hdr_t represents the srtp header
+ *
+ * in this implementation, an srtp_hdr_t is assumed to be 32-bit aligned
+ * 
+ * (note that this definition follows that of RFC 1889 Appendix A, but
+ * is not identical)
+ */
+#ifndef WORDS_BIGENDIAN
+
+/*
+ * srtp_hdr_t represents an RTP or SRTP header.  The bit-fields in
+ * this structure should be declared "unsigned int" instead of 
+ * "unsigned char", but doing so causes the MS compiler to not
+ * fully pack the bit fields.
+ */
+
+typedef struct {
+  unsigned cc:4;       /* CSRC count             */
+  unsigned x:1;        /* header extension flag  */
+  unsigned p:1;        /* padding flag           */
+  unsigned version:2; /* protocol version    */
+  unsigned pt:7;       /* payload type           */
+  unsigned m:1;        /* marker bit             */
+  unsigned seq:16;             /* sequence number        */
+  unsigned ts:32;              /* timestamp              */
+  unsigned ssrc:32;    /* synchronization source */
+} srtp_hdr_t;
+
+#else /*  BIG_ENDIAN */
+
+typedef struct {
+  unsigned char version:2; /* protocol version    */
+  unsigned char p:1;   /* padding flag           */
+  unsigned char x:1;   /* header extension flag  */
+  unsigned char cc:4;  /* CSRC count             */
+  unsigned char m:1;   /* marker bit             */
+  unsigned pt:7;       /* payload type           */
+  unsigned seq:16;             /* sequence number        */
+  unsigned ts:32;              /* timestamp              */
+  unsigned ssrc:32;    /* synchronization source */
+} srtp_hdr_t;
+
+#endif
+
+typedef struct {
+  uint16_t profile_specific;    /* profile-specific info               */
+  uint16_t length;              /* number of 32-bit words in extension */
+} srtp_hdr_xtnd_t;
+
+
+/*
+ * srtcp_hdr_t represents a secure rtcp header 
+ *
+ * in this implementation, an srtcp header is assumed to be 32-bit
+ * alinged
+ */
+
+#ifndef WORDS_BIGENDIAN
+
+typedef struct {
+  unsigned rc:5;               /* reception report count */
+  unsigned p:1;                /* padding flag           */
+  unsigned version:2;  /* protocol version       */
+  unsigned pt:8;               /* payload type           */
+  unsigned len:16;                     /* length                 */
+  unsigned ssrc:32;            /* synchronization source */
+} srtcp_hdr_t;
+
+typedef struct {
+  unsigned int index:31;    /* srtcp packet index in network order! */
+  unsigned int e:1;         /* encrypted? 1=yes */
+  /* optional mikey/etc go here */
+  /* and then the variable-length auth tag */
+} srtcp_trailer_t;
+
+
+#else /*  BIG_ENDIAN */
+
+typedef struct {
+  unsigned char version:2;     /* protocol version       */
+  unsigned char p:1;           /* padding flag           */
+  unsigned char rc:5;          /* reception report count */
+  unsigned char pt:8;          /* payload type           */
+  uint16_t len;                        /* length                 */
+  uint32_t ssrc;               /* synchronization source */
+} srtcp_hdr_t;
+
+typedef struct {
+  unsigned int version:2;  /* protocol version                     */
+  unsigned int p:1;        /* padding flag                         */
+  unsigned int count:5;    /* varies by packet type                */
+  unsigned int pt:8;       /* payload type                         */
+  uint16_t length;         /* len of uint32s of packet less header */
+} rtcp_common_t;
+
+typedef struct {
+  unsigned int e:1;         /* encrypted? 1=yes */
+  unsigned int index:31;    /* srtcp packet index */
+  /* optional mikey/etc go here */
+  /* and then the variable-length auth tag */
+} srtcp_trailer_t;
+
+#endif
+
+
+/*
+ * the following declarations are libSRTP internal functions 
+ */
+
+/*
+ * srtp_get_stream(ssrc) returns a pointer to the stream corresponding
+ * to ssrc, or NULL if no stream exists for that ssrc
+ */
+
+srtp_stream_t 
+srtp_get_stream(srtp_t srtp, uint32_t ssrc);
+
+
+/*
+ * srtp_stream_init_keys(s, k) (re)initializes the srtp_stream_t s by
+ * deriving all of the needed keys using the KDF and the key k.
+ */
+
+
+err_status_t
+srtp_stream_init_keys(srtp_stream_t srtp, const void *key);
+
+/*
+ * srtp_stream_init(s, p) initializes the srtp_stream_t s to 
+ * use the policy at the location p
+ */
+err_status_t
+srtp_stream_init(srtp_stream_t srtp, 
+                const srtp_policy_t *p);
+
+
+/*
+ * libsrtp internal datatypes 
+ */
+
+typedef enum direction_t { 
+  dir_unknown       = 0,
+  dir_srtp_sender   = 1, 
+  dir_srtp_receiver = 2
+} direction_t;
+
+/* 
+ * an srtp_stream_t has its own SSRC, encryption key, authentication
+ * key, sequence number, and replay database
+ * 
+ * note that the keys might not actually be unique, in which case the
+ * cipher_t and auth_t pointers will point to the same structures
+ */
+
+typedef struct srtp_stream_ctx_t {
+  uint32_t   ssrc;
+  cipher_t  *rtp_cipher;
+  auth_t    *rtp_auth;
+  rdbx_t     rtp_rdbx;
+  sec_serv_t rtp_services;
+  cipher_t  *rtcp_cipher;
+  auth_t    *rtcp_auth;
+  rdb_t      rtcp_rdb;
+  sec_serv_t rtcp_services;
+  key_limit_ctx_t *limit;
+  direction_t direction;
+  int        allow_repeat_tx;
+  ekt_stream_t ekt; 
+  struct srtp_stream_ctx_t *next;   /* linked list of streams */
+} srtp_stream_ctx_t;
+
+
+/*
+ * an srtp_ctx_t holds a stream list and a service description
+ */
+
+typedef struct srtp_ctx_t {
+  srtp_stream_ctx_t *stream_list;     /* linked list of streams            */
+  srtp_stream_ctx_t *stream_template; /* act as template for other streams */
+} srtp_ctx_t;
+
+
+
+/*
+ * srtp_handle_event(srtp, srtm, evnt) calls the event handling
+ * function, if there is one.
+ *
+ * This macro is not included in the documentation as it is 
+ * an internal-only function.
+ */
+
+#define srtp_handle_event(srtp, strm, evnt)         \
+   if(srtp_event_handler) {                         \
+      srtp_event_data_t data;                       \
+      data.session = srtp;                          \
+      data.stream  = strm;                          \
+      data.event   = evnt;                          \
+      srtp_event_handler(&data);                    \
+}   
+
+
+#endif /* SRTP_PRIV_H */
index deed553b5437a6f4d283317645ad8cf64e0dc207..c25feeb654ae6b46077d0cae4fc850b3fca67df8 100644 (file)
@@ -10,7 +10,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
index ea6908aba633eda59117cd0c83a16246659eb12d..6fc94da0be843182f63fa2ffd184a134eb50ab8d 100644 (file)
@@ -1,91 +1,91 @@
-EXPORTS\r
-srtp_init\r
-srtp_protect\r
-srtp_unprotect\r
-srtp_create\r
-srtp_add_stream\r
-srtp_remove_stream\r
-crypto_policy_set_rtp_default\r
-crypto_policy_set_rtcp_default\r
-crypto_policy_set_aes_cm_128_hmac_sha1_32\r
-crypto_policy_set_aes_cm_128_null_auth\r
-crypto_policy_set_null_cipher_hmac_sha1_80\r
-srtp_dealloc\r
-srtp_get_stream\r
-srtp_protect_rtcp\r
-srtp_unprotect_rtcp\r
-srtp_install_event_handler\r
-crypto_kernel_init\r
-crypto_kernel_shutdown\r
-crypto_kernel_status\r
-crypto_kernel_list_debug_modules\r
-crypto_kernel_load_cipher_type\r
-crypto_kernel_load_auth_type\r
-crypto_kernel_load_debug_module\r
-crypto_kernel_alloc_cipher\r
-crypto_kernel_alloc_auth\r
-crypto_kernel_set_debug_module\r
-crypto_get_random\r
-rand_source_init\r
-rand_source_get_octet_string\r
-rand_source_deinit\r
-x917_prng_init\r
-x917_prng_get_octet_string\r
-ctr_prng_init\r
-ctr_prng_get_octet_string\r
-cipher_output\r
-cipher_get_key_length\r
-cipher_type_self_test\r
-cipher_bits_per_second\r
-auth_get_key_length\r
-auth_get_tag_length\r
-auth_get_prefix_length\r
-auth_type_self_test\r
-auth_type_get_ref_count\r
-stat_test_monobit\r
-stat_test_poker\r
-stat_test_runs\r
-stat_test_rand_source\r
-stat_test_rand_source_with_repetition\r
-err_reporting_init\r
-err_report\r
-key_limit_set\r
-key_limit_clone\r
-key_limit_check\r
-key_limit_update\r
-rdbx_init\r
-rdbx_estimate_index\r
-rdbx_check\r
-rdbx_add_index\r
-index_init\r
-index_advance\r
-index_guess\r
-octet_get_weight\r
-octet_string_hex_string\r
-v128_bit_string\r
-v128_hex_string\r
-nibble_to_hex_char\r
-hex_string_to_octet_string\r
-v128_copy_octet_string\r
-v128_left_shift\r
-v128_right_shift\r
-octet_string_is_eq\r
-octet_string_set_to_zero\r
-rdb_init\r
-rdb_check\r
-rdb_add_index\r
-rdb_increment\r
-rdb_get_value\r
-aes_expand_encryption_key\r
-aes_expand_decryption_key\r
-aes_encrypt\r
-aes_decrypt\r
-aes_icm_context_init\r
-aes_icm_set_iv\r
-aes_icm_encrypt\r
-aes_icm_output\r
-aes_icm_dealloc\r
-aes_icm_encrypt_ismacryp\r
-aes_icm_alloc_ismacryp\r
-crypto_alloc\r
-crypto_free\r
+EXPORTS
+srtp_init
+srtp_protect
+srtp_unprotect
+srtp_create
+srtp_add_stream
+srtp_remove_stream
+crypto_policy_set_rtp_default
+crypto_policy_set_rtcp_default
+crypto_policy_set_aes_cm_128_hmac_sha1_32
+crypto_policy_set_aes_cm_128_null_auth
+crypto_policy_set_null_cipher_hmac_sha1_80
+srtp_dealloc
+srtp_get_stream
+srtp_protect_rtcp
+srtp_unprotect_rtcp
+srtp_install_event_handler
+crypto_kernel_init
+crypto_kernel_shutdown
+crypto_kernel_status
+crypto_kernel_list_debug_modules
+crypto_kernel_load_cipher_type
+crypto_kernel_load_auth_type
+crypto_kernel_load_debug_module
+crypto_kernel_alloc_cipher
+crypto_kernel_alloc_auth
+crypto_kernel_set_debug_module
+crypto_get_random
+rand_source_init
+rand_source_get_octet_string
+rand_source_deinit
+x917_prng_init
+x917_prng_get_octet_string
+ctr_prng_init
+ctr_prng_get_octet_string
+cipher_output
+cipher_get_key_length
+cipher_type_self_test
+cipher_bits_per_second
+auth_get_key_length
+auth_get_tag_length
+auth_get_prefix_length
+auth_type_self_test
+auth_type_get_ref_count
+stat_test_monobit
+stat_test_poker
+stat_test_runs
+stat_test_rand_source
+stat_test_rand_source_with_repetition
+err_reporting_init
+err_report
+key_limit_set
+key_limit_clone
+key_limit_check
+key_limit_update
+rdbx_init
+rdbx_estimate_index
+rdbx_check
+rdbx_add_index
+index_init
+index_advance
+index_guess
+octet_get_weight
+octet_string_hex_string
+v128_bit_string
+v128_hex_string
+nibble_to_hex_char
+hex_string_to_octet_string
+v128_copy_octet_string
+v128_left_shift
+v128_right_shift
+octet_string_is_eq
+octet_string_set_to_zero
+rdb_init
+rdb_check
+rdb_add_index
+rdb_increment
+rdb_get_value
+aes_expand_encryption_key
+aes_expand_decryption_key
+aes_encrypt
+aes_decrypt
+aes_icm_context_init
+aes_icm_set_iv
+aes_icm_encrypt
+aes_icm_output
+aes_icm_dealloc
+aes_icm_encrypt_ismacryp
+aes_icm_alloc_ismacryp
+crypto_alloc
+crypto_free
diff --git a/libs/srtp/srtp/ekt.c b/libs/srtp/srtp/ekt.c
new file mode 100644 (file)
index 0000000..9ae7f7e
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * ekt.c
+ *
+ * Encrypted Key Transport for SRTP
+ * 
+ * David McGrew
+ * Cisco Systems, Inc.
+ */
+/*
+ *     
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *   Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 
+ *   Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ * 
+ *   Neither the name of the Cisco Systems, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include "err.h"
+#include "srtp_priv.h"
+#include "ekt.h"
+
+extern debug_module_t mod_srtp;
+
+/*
+ *  The EKT Authentication Tag format.
+ *
+ *    0                   1                   2                   3
+ *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   :                   Base Authentication Tag                     :
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   :                     Encrypted Master Key                      :
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                       Rollover Counter                        |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |    Initial Sequence Number    |   Security Parameter Index    |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */                     
+
+#define EKT_OCTETS_AFTER_BASE_TAG 24
+#define EKT_OCTETS_AFTER_EMK       8
+#define EKT_OCTETS_AFTER_ROC       4
+#define EKT_SPI_LEN                2
+
+unsigned
+ekt_octets_after_base_tag(ekt_stream_t ekt) {
+  /*
+   * if the pointer ekt is NULL, then EKT is not in effect, so we
+   * indicate this by returning zero
+   */
+  if (!ekt)
+    return 0;
+
+  switch(ekt->data->ekt_cipher_type) {
+  case EKT_CIPHER_AES_128_ECB:
+    return 16 + EKT_OCTETS_AFTER_EMK;
+    break;
+  default:
+    break;
+  }
+  return 0;
+}
+
+static inline ekt_spi_t
+srtcp_packet_get_ekt_spi(const uint8_t *packet_start, unsigned pkt_octet_len) {
+  const uint8_t *spi_location;
+  
+  spi_location = packet_start + (pkt_octet_len - EKT_SPI_LEN);
+  
+  return *((const ekt_spi_t *)spi_location);
+}
+
+static inline uint32_t
+srtcp_packet_get_ekt_roc(const uint8_t *packet_start, unsigned pkt_octet_len) {
+  const uint8_t *roc_location;
+  
+  roc_location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_ROC);
+  
+  return *((const uint32_t *)roc_location);
+}
+
+static inline const uint8_t *
+srtcp_packet_get_emk_location(const uint8_t *packet_start, 
+                             unsigned pkt_octet_len) {
+  const uint8_t *location;
+  
+  location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_BASE_TAG);
+
+  return location;
+}
+
+
+err_status_t 
+ekt_alloc(ekt_stream_t *stream_data, ekt_policy_t policy) {
+
+  /*
+   * if the policy pointer is NULL, then EKT is not in use
+   * so we just set the EKT stream data pointer to NULL
+   */
+  if (!policy) {
+    *stream_data = NULL;
+    return err_status_ok;
+  }
+
+  /* TODO */
+  *stream_data = NULL;
+
+  return err_status_ok;
+}
+
+err_status_t
+ekt_stream_init_from_policy(ekt_stream_t stream_data, ekt_policy_t policy) {
+  if (!stream_data)
+    return err_status_ok;
+
+  return err_status_ok;
+}
+
+
+void
+aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len) {
+  aes_expanded_key_t expanded_key;
+
+  aes_expand_decryption_key(key, key_len, &expanded_key);
+  aes_decrypt(ciphertext, &expanded_key);
+}
+
+/*
+ * The function srtp_stream_init_from_ekt() initializes a stream using
+ * the EKT data from an SRTCP trailer.  
+ */
+
+err_status_t
+srtp_stream_init_from_ekt(srtp_stream_t stream,                          
+                         const void *srtcp_hdr,
+                         unsigned pkt_octet_len) {
+  err_status_t err;
+  const uint8_t *master_key;
+  srtp_policy_t srtp_policy;
+  unsigned master_key_len;
+  uint32_t roc;
+
+  /*
+   * NOTE: at present, we only support a single ekt_policy at a time.  
+   */
+  if (stream->ekt->data->spi != 
+      srtcp_packet_get_ekt_spi(srtcp_hdr, pkt_octet_len))
+    return err_status_no_ctx;
+
+  if (stream->ekt->data->ekt_cipher_type != EKT_CIPHER_AES_128_ECB)
+    return err_status_bad_param;
+  master_key_len = 16;
+
+  /* decrypt the Encrypted Master Key field */
+  master_key = srtcp_packet_get_emk_location(srtcp_hdr, pkt_octet_len);
+  /* FIX!? This decrypts the master key in-place, and never uses it */
+  /* FIX!? It's also passing to ekt_dec_key (which is an aes_expanded_key_t)
+   * to a function which expects a raw (unexpanded) key */
+  aes_decrypt_with_raw_key((void*)master_key, &stream->ekt->data->ekt_dec_key, 16);
+
+  /* set the SRTP ROC */
+  roc = srtcp_packet_get_ekt_roc(srtcp_hdr, pkt_octet_len);
+  err = rdbx_set_roc(&stream->rtp_rdbx, roc);
+  if (err) return err;
+
+  err = srtp_stream_init(stream, &srtp_policy);
+  if (err) return err;
+
+  return err_status_ok;
+}
+
+void
+ekt_write_data(ekt_stream_t ekt,
+              uint8_t *base_tag, 
+              unsigned base_tag_len, 
+              int *packet_len,
+              xtd_seq_num_t pkt_index) {
+  uint32_t roc;
+  uint16_t isn;
+  unsigned emk_len;
+  uint8_t *packet;
+
+  /* if the pointer ekt is NULL, then EKT is not in effect */
+  if (!ekt) {
+    debug_print(mod_srtp, "EKT not in use", NULL);
+    return;
+  }
+
+  /* write zeros into the location of the base tag */
+  octet_string_set_to_zero(base_tag, base_tag_len);
+  packet = base_tag + base_tag_len;
+
+  /* copy encrypted master key into packet */
+  emk_len = ekt_octets_after_base_tag(ekt);
+  memcpy(packet, ekt->encrypted_master_key, emk_len);
+  debug_print(mod_srtp, "writing EKT EMK: %s,", 
+             octet_string_hex_string(packet, emk_len));
+  packet += emk_len;
+
+  /* copy ROC into packet */
+  roc = (uint32_t)(pkt_index >> 16);
+  *((uint32_t *)packet) = be32_to_cpu(roc);
+  debug_print(mod_srtp, "writing EKT ROC: %s,", 
+             octet_string_hex_string(packet, sizeof(roc)));
+  packet += sizeof(roc);
+
+  /* copy ISN into packet */
+  isn = (uint16_t)pkt_index;
+  *((uint16_t *)packet) = htons(isn);
+  debug_print(mod_srtp, "writing EKT ISN: %s,", 
+             octet_string_hex_string(packet, sizeof(isn)));
+  packet += sizeof(isn);
+
+  /* copy SPI into packet */
+  *((uint16_t *)packet) = htons(ekt->data->spi);
+  debug_print(mod_srtp, "writing EKT SPI: %s,", 
+             octet_string_hex_string(packet, sizeof(ekt->data->spi)));
+
+  /* increase packet length appropriately */
+  *packet_len += EKT_OCTETS_AFTER_EMK + emk_len;
+}
+
+
+/*
+ * The function call srtcp_ekt_trailer(ekt, auth_len, auth_tag   )
+ * 
+ * If the pointer ekt is NULL, then the other inputs are unaffected.
+ *
+ * auth_tag is a pointer to the pointer to the location of the
+ * authentication tag in the packet.  If EKT is in effect, then the
+ * auth_tag pointer is set to the location 
+ */
+
+void
+srtcp_ekt_trailer(ekt_stream_t ekt,
+                 unsigned *auth_len,
+                 void **auth_tag,
+                 void *tag_copy) {
+  
+  /* 
+   * if there is no EKT policy, then the other inputs are unaffected
+   */
+  if (!ekt) 
+    return;
+      
+  /* copy auth_tag into temporary location */
+  
+}
+
index 2db745d2bbcbe294da07bfdfe727e562835563d1..163d0d1f3faeafe8add17723f3b4247575828e85 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,7 @@
 
 
 #include "srtp.h"
-#include "aes_icm.h"         /* aes_icm is used in the KDF  */
+#include "ekt.h"             /* for SRTP Encrypted Key Transport */
 #include "alloc.h"           /* for crypto_alloc()          */
 
 #ifndef SRTP_KERNEL
@@ -57,9 +57,6 @@
 #endif /* ! SRTP_KERNEL */
 
 
-extern cipher_type_t aes_icm;
-extern auth_type_t   tmmhv2;
-
 /* the debug module for srtp */
 
 debug_module_t mod_srtp = {
@@ -114,7 +111,7 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
   }
   
   /* allocate key limit structure */
-  str->limit = crypto_alloc(sizeof(key_limit_ctx_t));
+  str->limit = (key_limit_ctx_t*) crypto_alloc(sizeof(key_limit_ctx_t));
   if (str->limit == NULL) {
     auth_dealloc(str->rtp_auth);
     cipher_dealloc(str->rtp_cipher);
@@ -151,6 +148,18 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr,
    return stat;
   }  
 
+  /* allocate ekt data associated with stream */
+  stat = ekt_alloc(&str->ekt, p->ekt);
+  if (stat) {
+    auth_dealloc(str->rtcp_auth);
+    cipher_dealloc(str->rtcp_cipher);
+    auth_dealloc(str->rtp_auth);
+    cipher_dealloc(str->rtp_cipher);
+    crypto_free(str->limit);
+    crypto_free(str);
+   return stat;    
+  }
+
   return err_status_ok;
 }
 
@@ -217,6 +226,12 @@ srtp_stream_dealloc(srtp_t session, srtp_stream_ctx_t *stream) {
     if (status)
       return status;
   }
+
+  status = rdbx_dealloc(&stream->rtp_rdbx);
+  if (status)
+    return status;
+
+  /* DAM - need to deallocate EKT here */
   
   /* deallocate srtp stream context */
   crypto_free(stream);
@@ -260,8 +275,12 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
     return status;
 
   /* initialize replay databases */
-  rdbx_init(&str->rtp_rdbx);
+  status = rdbx_init(&str->rtp_rdbx,
+                    rdbx_get_window_size(&stream_template->rtp_rdbx));
+  if (status)
+    return status;
   rdb_init(&str->rtcp_rdb);
+  str->allow_repeat_tx = stream_template->allow_repeat_tx;
   
   /* set ssrc to that provided */
   str->ssrc = ssrc;
@@ -271,6 +290,9 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
   str->rtp_services  = stream_template->rtp_services;
   str->rtcp_services = stream_template->rtcp_services;
 
+  /* set pointer to EKT data associated with stream */
+  str->ekt = stream_template->ekt;
+
   /* defensive coding */
   str->next = NULL;
 
@@ -283,14 +305,15 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template,
  *
  * srtp_kdf_t is a key derivation context
  *
- * srtp_kdf_init(&kdf, k) initializes kdf with the key k
+ * srtp_kdf_init(&kdf, cipher_id, k, keylen) initializes kdf to use cipher
+ * described by cipher_id, with the master key k with length in octets keylen.
  * 
  * srtp_kdf_generate(&kdf, l, kl, keylen) derives the key
  * corresponding to label l and puts it into kl; the length
  * of the key in octets is provided as keylen.  this function
  * should be called once for each subkey that is derived.
  *
- * srtp_kdf_clear(&kdf) zeroizes the kdf state
+ * srtp_kdf_clear(&kdf) zeroizes and deallocates the kdf state
  */
 
 typedef enum {
@@ -309,40 +332,57 @@ typedef enum {
  */
 
 typedef struct { 
-  aes_icm_ctx_t c;    /* cipher used for key derivation  */  
+  cipher_t *cipher;    /* cipher used for key derivation  */  
 } srtp_kdf_t;
 
 err_status_t
-srtp_kdf_init(srtp_kdf_t *kdf, const uint8_t key[30]) {
+srtp_kdf_init(srtp_kdf_t *kdf, cipher_type_id_t cipher_id, const uint8_t *key, int length) {
+
+  err_status_t stat;
+  stat = crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, length);
+  if (stat)
+    return stat;
 
-  aes_icm_context_init(&kdf->c, key);
+  stat = cipher_init(kdf->cipher, key, direction_encrypt);
+  if (stat) {
+    cipher_dealloc(kdf->cipher);
+    return stat;
+  }
 
   return err_status_ok;
 }
 
 err_status_t
 srtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label,
-                 uint8_t *key, int length) {
+                 uint8_t *key, unsigned length) {
 
   v128_t nonce;
+  err_status_t status;
   
   /* set eigth octet of nonce to <label>, set the rest of it to zero */
   v128_set_to_zero(&nonce);
   nonce.v8[7] = label;
  
-  aes_icm_set_iv(&kdf->c, &nonce);  
+  status = cipher_set_iv(kdf->cipher, &nonce);
+  if (status)
+    return status;
   
   /* generate keystream output */
-  aes_icm_output(&kdf->c, key, length);
+  octet_string_set_to_zero(key, length);
+  status = cipher_encrypt(kdf->cipher, key, &length);
+  if (status)
+    return status;
 
   return err_status_ok;
 }
 
 err_status_t
 srtp_kdf_clear(srtp_kdf_t *kdf) {
-  
-  /* zeroize aes context */
-  octet_string_set_to_zero((uint8_t *)kdf, sizeof(srtp_kdf_t));
+  err_status_t status;
+  status = cipher_dealloc(kdf->cipher);
+  if (status)
+    return status;
+  kdf->cipher = NULL;
 
   return err_status_ok;  
 }
@@ -354,20 +394,208 @@ srtp_kdf_clear(srtp_kdf_t *kdf) {
 #define MAX_SRTP_KEY_LEN 256
 
 
+/* Get the base key length corresponding to a given combined key+salt
+ * length for the given cipher.
+ * Assumption is that for AES-ICM a key length < 30 is Ismacryp using
+ * AES-128 and short salts; everything else uses a salt length of 14.
+ * TODO: key and salt lengths should be separate fields in the policy.  */
+static inline int base_key_length(const cipher_type_t *cipher, int key_length)
+{
+  if (cipher->id != AES_ICM)
+    return key_length;
+  else if (key_length > 16 && key_length < 30)
+    return 16;
+  return key_length - 14;
+}
+
+err_status_t
+srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) {
+  err_status_t stat;
+  srtp_kdf_t kdf;
+  uint8_t tmp_key[MAX_SRTP_KEY_LEN];
+  int kdf_keylen = 30, rtp_keylen, rtcp_keylen;
+  int rtp_base_key_len, rtp_salt_len;
+  int rtcp_base_key_len, rtcp_salt_len;
+
+  /* If RTP or RTCP have a key length > AES-128, assume matching kdf. */
+  /* TODO: kdf algorithm, master key length, and master salt length should
+   * be part of srtp_policy_t. */
+  rtp_keylen = cipher_get_key_length(srtp->rtp_cipher);
+  if (rtp_keylen > kdf_keylen)
+    kdf_keylen = rtp_keylen;
+
+  rtcp_keylen = cipher_get_key_length(srtp->rtcp_cipher);
+  if (rtcp_keylen > kdf_keylen)
+    kdf_keylen = rtcp_keylen;
+
+  /* initialize KDF state     */
+  stat = srtp_kdf_init(&kdf, AES_ICM, (const uint8_t *)key, kdf_keylen);
+  if (stat) {
+    return err_status_init_fail;
+  }
+
+  rtp_base_key_len = base_key_length(srtp->rtp_cipher->type, rtp_keylen);
+  rtp_salt_len = rtp_keylen - rtp_base_key_len;
+  
+  /* generate encryption key  */
+  stat = srtp_kdf_generate(&kdf, label_rtp_encryption, 
+                          tmp_key, rtp_base_key_len);
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
+  /* 
+   * if the cipher in the srtp context uses a salt, then we need
+   * to generate the salt value
+   */
+  if (rtp_salt_len > 0) {
+    debug_print(mod_srtp, "found rtp_salt_len > 0, generating salt", NULL);
+
+    /* generate encryption salt, put after encryption key */
+    stat = srtp_kdf_generate(&kdf, label_rtp_salt, 
+                            tmp_key + rtp_base_key_len, rtp_salt_len);
+    if (stat) {
+      /* zeroize temp buffer */
+      octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+      return err_status_init_fail;
+    }
+  }
+  debug_print(mod_srtp, "cipher key: %s", 
+             octet_string_hex_string(tmp_key, rtp_base_key_len));
+  if (rtp_salt_len > 0) {
+    debug_print(mod_srtp, "cipher salt: %s",
+               octet_string_hex_string(tmp_key + rtp_base_key_len, rtp_salt_len));
+  }
+
+  /* initialize cipher */
+  stat = cipher_init(srtp->rtp_cipher, tmp_key, direction_any);
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
+  /* generate authentication key */
+  stat = srtp_kdf_generate(&kdf, label_rtp_msg_auth,
+                          tmp_key, auth_get_key_length(srtp->rtp_auth));
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+  debug_print(mod_srtp, "auth key:   %s",
+             octet_string_hex_string(tmp_key, 
+                                     auth_get_key_length(srtp->rtp_auth))); 
+
+  /* initialize auth function */
+  stat = auth_init(srtp->rtp_auth, tmp_key);
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
+  /*
+   * ...now initialize SRTCP keys
+   */
+
+  rtcp_base_key_len = base_key_length(srtp->rtcp_cipher->type, rtcp_keylen);
+  rtcp_salt_len = rtcp_keylen - rtcp_base_key_len;
+  
+  /* generate encryption key  */
+  stat = srtp_kdf_generate(&kdf, label_rtcp_encryption, 
+                          tmp_key, rtcp_base_key_len);
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
+  /* 
+   * if the cipher in the srtp context uses a salt, then we need
+   * to generate the salt value
+   */
+  if (rtcp_salt_len > 0) {
+    debug_print(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt",
+               NULL);
+
+    /* generate encryption salt, put after encryption key */
+    stat = srtp_kdf_generate(&kdf, label_rtcp_salt, 
+                            tmp_key + rtcp_base_key_len, rtcp_salt_len);
+    if (stat) {
+      /* zeroize temp buffer */
+      octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+      return err_status_init_fail;
+    }
+  }
+  debug_print(mod_srtp, "rtcp cipher key: %s", 
+             octet_string_hex_string(tmp_key, rtcp_base_key_len));  
+  if (rtcp_salt_len > 0) {
+    debug_print(mod_srtp, "rtcp cipher salt: %s",
+               octet_string_hex_string(tmp_key + rtcp_base_key_len, rtcp_salt_len));
+  }
+
+  /* initialize cipher */
+  stat = cipher_init(srtp->rtcp_cipher, tmp_key, direction_any);
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
+  /* generate authentication key */
+  stat = srtp_kdf_generate(&kdf, label_rtcp_msg_auth,
+                          tmp_key, auth_get_key_length(srtp->rtcp_auth));
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
+  debug_print(mod_srtp, "rtcp auth key:   %s",
+             octet_string_hex_string(tmp_key, 
+                    auth_get_key_length(srtp->rtcp_auth))); 
+
+  /* initialize auth function */
+  stat = auth_init(srtp->rtcp_auth, tmp_key);
+  if (stat) {
+    /* zeroize temp buffer */
+    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
+    return err_status_init_fail;
+  }
+
+  /* clear memory then return */
+  stat = srtp_kdf_clear(&kdf);
+  octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);  
+  if (stat)
+    return err_status_init_fail;
+
+  return err_status_ok;
+}
 
 err_status_t
 srtp_stream_init(srtp_stream_ctx_t *srtp, 
                  const srtp_policy_t *p) {
-   err_status_t stat;
-   srtp_kdf_t kdf;
-   uint8_t tmp_key[MAX_SRTP_KEY_LEN];
-   uint8_t *key = p->key;
+  err_status_t err;
 
    debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)", 
               p->ssrc.value);
 
    /* initialize replay database */
-   rdbx_init(&srtp->rtp_rdbx);
+   /* window size MUST be at least 64.  MAY be larger.  Values more than
+    * 2^15 aren't meaningful due to how extended sequence numbers are
+    * calculated.   Let a window size of 0 imply the default value. */
+
+   if (p->window_size != 0 && (p->window_size < 64 || p->window_size >= 0x8000))
+     return err_status_bad_param;
+
+   if (p->window_size != 0)
+     err = rdbx_init(&srtp->rtp_rdbx, p->window_size);
+   else
+     err = rdbx_init(&srtp->rtp_rdbx, 128);
+   if (err) return err;
 
    /* initialize key limit to maximum value */
 #ifdef NO_64BIT_MATH
@@ -394,111 +622,36 @@ srtp_stream_init(srtp_stream_ctx_t *srtp,
     */
    srtp->direction = dir_unknown;
 
-   /* initialize KDF state     */
-   srtp_kdf_init(&kdf, key);
-
-   /* generate encryption key  */
-   srtp_kdf_generate(&kdf, label_rtp_encryption, 
-                    tmp_key, cipher_get_key_length(srtp->rtp_cipher));
-   /* 
-    * if the cipher in the srtp context is aes_icm, then we need
-    * to generate the salt value
-    */
-   if (srtp->rtp_cipher->type == &aes_icm) {
-          /* FIX!!! this is really the cipher key length; rest is salt */
-     int base_key_len = 16;
-     int salt_len = cipher_get_key_length(srtp->rtp_cipher) - base_key_len;
-
-     debug_print(mod_srtp, "found aes_icm, generating salt", NULL);
-
-     /* generate encryption salt, put after encryption key */
-     srtp_kdf_generate(&kdf, label_rtp_salt, 
-                      tmp_key + base_key_len, salt_len);
-   }
-   debug_print(mod_srtp, "cipher key: %s", 
-              octet_string_hex_string(tmp_key, 
-                   cipher_get_key_length(srtp->rtp_cipher)));  
-
-   /* initialize cipher */
-   stat = cipher_init(srtp->rtp_cipher, tmp_key, direction_any);
-   if (stat) {
-     /* zeroize temp buffer */
-     octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
-     return err_status_init_fail;
-   }
+   /* initialize SRTCP replay database */
+   rdb_init(&srtp->rtcp_rdb);
 
-   /* generate authentication key */
-   srtp_kdf_generate(&kdf, label_rtp_msg_auth,
-                    tmp_key, auth_get_key_length(srtp->rtp_auth));
-   debug_print(mod_srtp, "auth key:   %s",
-              octet_string_hex_string(tmp_key, 
-                  auth_get_key_length(srtp->rtp_auth))); 
-
-   /* initialize auth function */
-   stat = auth_init(srtp->rtp_auth, tmp_key);
-   if (stat) {
-     /* zeroize temp buffer */
-     octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
-     return err_status_init_fail;
+   /* initialize allow_repeat_tx */
+   /* guard against uninitialized memory: allow only 0 or 1 here */
+   if (p->allow_repeat_tx != 0 && p->allow_repeat_tx != 1) {
+     rdbx_dealloc(&srtp->rtp_rdbx);
+     return err_status_bad_param;
    }
-
-   /*
-    * ...now initialize RTCP-specific structures   
-    */
-
-   /* initialize replay database */
-   rdb_init(&srtp->rtcp_rdb);
+   srtp->allow_repeat_tx = p->allow_repeat_tx;
 
    /* DAM - no RTCP key limit at present */
 
-   /* generate encryption key  */
-   srtp_kdf_generate(&kdf, label_rtcp_encryption, 
-                    tmp_key, cipher_get_key_length(srtp->rtcp_cipher));
-   /* 
-    * if the cipher in the srtp context is aes_icm, then we need
-    * to generate the salt value
-    */
-   if (srtp->rtcp_cipher->type == &aes_icm) {
-          /* FIX!!! this is really the cipher key length; rest is salt */
-     int base_key_len = 16;
-     int salt_len = cipher_get_key_length(srtp->rtcp_cipher) - base_key_len;
-
-     debug_print(mod_srtp, "found aes_icm, generating rtcp salt", NULL);
-
-     /* generate encryption salt, put after encryption key */
-     srtp_kdf_generate(&kdf, label_rtcp_salt, 
-                      tmp_key + base_key_len, salt_len);
-   }
-   debug_print(mod_srtp, "rtcp cipher key: %s", 
-              octet_string_hex_string(tmp_key, 
-                   cipher_get_key_length(srtp->rtcp_cipher)));  
-
-   /* initialize cipher */
-   stat = cipher_init(srtp->rtcp_cipher, tmp_key, direction_any);
-   if (stat) {
-     /* zeroize temp buffer */
-     octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
-     return err_status_init_fail;
+   /* initialize keys */
+   err = srtp_stream_init_keys(srtp, p->key);
+   if (err) {
+     rdbx_dealloc(&srtp->rtp_rdbx);
+     return err;
    }
 
-   /* generate authentication key */
-   srtp_kdf_generate(&kdf, label_rtcp_msg_auth,
-                    tmp_key, auth_get_key_length(srtp->rtcp_auth));
-   debug_print(mod_srtp, "rtcp auth key:   %s",
-              octet_string_hex_string(tmp_key, 
-                  auth_get_key_length(srtp->rtcp_auth))); 
-
-   /* initialize auth function */
-   stat = auth_init(srtp->rtcp_auth, tmp_key);
-   if (stat) {
-     /* zeroize temp buffer */
-     octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
-     return err_status_init_fail;
+   /* 
+    * if EKT is in use, then initialize the EKT data associated with
+    * the stream
+    */
+   err = ekt_stream_init_from_policy(srtp->ekt, p->ekt);
+   if (err) {
+     rdbx_dealloc(&srtp->rtp_rdbx);
+     return err;
    }
 
-   /* clear memory then return */
-   srtp_kdf_clear(&kdf);
-   octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);
    return err_status_ok;  
  }
 
@@ -560,7 +713,7 @@ srtp_stream_init(srtp_stream_ctx_t *srtp,
 
  err_status_t
  srtp_protect(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len) {
-   srtp_hdr_t *hdr = rtp_hdr;
+   srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr;
    uint32_t *enc_start;        /* pointer to start of encrypted portion  */
    uint32_t *auth_start;       /* pointer to start of auth. portion      */
    unsigned enc_octet_len = 0; /* number of octets in encrypted portion  */
@@ -662,7 +815,8 @@ srtp_stream_init(srtp_stream_ctx_t *srtp,
        srtp_hdr_xtnd_t *xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
        enc_start += (ntohs(xtn_hdr->length) + 1);
      }
-     enc_octet_len = (unsigned int)(*pkt_octet_len - ((enc_start - (uint32_t *)hdr) << 2));
+     enc_octet_len = (unsigned int)(*pkt_octet_len 
+                                   - ((enc_start - (uint32_t *)hdr) << 2));
    } else {
      enc_start = NULL;
    }
@@ -684,11 +838,14 @@ srtp_stream_init(srtp_stream_ctx_t *srtp,
     * estimate the packet index using the start of the replay window   
     * and the sequence number from the header
     */
-   delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs((uint16_t)hdr->seq));
+   delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
    status = rdbx_check(&stream->rtp_rdbx, delta);
-   if (status)
-     return status;  /* we've been asked to reuse an index */
-   rdbx_add_index(&stream->rtp_rdbx, delta);
+   if (status) {
+     if (status != err_status_replay_fail || !stream->allow_repeat_tx)
+       return status;  /* we've been asked to reuse an index */
+   }
+   else
+     rdbx_add_index(&stream->rtp_rdbx, delta);
 
 #ifdef NO_64BIT_MATH
    debug_print2(mod_srtp, "estimated packet index: %08x%08x", 
@@ -700,7 +857,7 @@ srtp_stream_init(srtp_stream_ctx_t *srtp,
    /* 
     * if we're using rindael counter mode, set nonce and seq 
     */
-   if (stream->rtp_cipher->type == &aes_icm) {
+   if (stream->rtp_cipher->type->id == AES_ICM) {
      v128_t iv;
 
      iv.v32[0] = 0;
@@ -799,10 +956,10 @@ srtp_stream_init(srtp_stream_ctx_t *srtp,
 
 err_status_t
 srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
-  srtp_hdr_t *hdr = srtp_hdr;
+  srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr;
   uint32_t *enc_start;      /* pointer to start of encrypted portion  */
   uint32_t *auth_start;     /* pointer to start of auth. portion      */
-  uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
+  unsigned enc_octet_len = 0;/* number of octets in encrypted portion */
   uint8_t *auth_tag = NULL; /* location of auth_tag within packet     */
   xtd_seq_num_t est;        /* estimated xtd_seq_num_t of *hdr        */
   int delta;                /* delta of local pkt idx and that in hdr */
@@ -842,7 +999,7 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
       est = (xtd_seq_num_t) make64(0,ntohs(hdr->seq));
       delta = low32(est);
 #else
-      est = (xtd_seq_num_t) ntohs((uint16_t)hdr->seq);
+      est = (xtd_seq_num_t) ntohs(hdr->seq);
       delta = (int)est;
 #endif
     } else {
@@ -856,7 +1013,7 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
   } else {
   
     /* estimate packet index from seq. num. in header */
-    delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs((uint16_t)hdr->seq));
+    delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));
     
     /* check replay database */
     status = rdbx_check(&stream->rtp_rdbx, delta);
@@ -877,7 +1034,7 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
    * set the cipher's IV properly, depending on whatever cipher we
    * happen to be using
    */
-  if (stream->rtp_cipher->type == &aes_icm) {
+  if (stream->rtp_cipher->type->id == AES_ICM) {
 
     /* aes counter mode */
     iv.v32[0] = 0;
@@ -888,7 +1045,7 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
 #else
     iv.v64[1] = be64_to_cpu(est << 16);
 #endif
-    status = aes_icm_set_iv(stream->rtp_cipher->state, &iv);
+    status = cipher_set_iv(stream->rtp_cipher, &iv);
   } else {  
     
     /* no particular format - set the iv to the pakcet index */  
@@ -927,7 +1084,8 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
       srtp_hdr_xtnd_t *xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
       enc_start += (ntohs(xtn_hdr->length) + 1);
     }  
-    enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - ((enc_start - (uint32_t *)hdr) << 2));
+    enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len 
+                              - ((enc_start - (uint32_t *)hdr) << 2));
   } else {
     enc_start = NULL;
   }
@@ -1008,9 +1166,9 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {
     break;
   }
 
-  /* if we're encrypting, add keystream into ciphertext */
+  /* if we're decrypting, add keystream into ciphertext */
   if (enc_start) {
-    status = cipher_encrypt(stream->rtp_cipher, 
+    status = cipher_decrypt(stream->rtp_cipher, 
                            (uint8_t *)enc_start, &enc_octet_len);
     if (status)
       return err_status_cipher_fail;
@@ -1090,6 +1248,21 @@ srtp_init() {
   return err_status_ok;
 }
 
+err_status_t
+srtp_shutdown() {
+  err_status_t status;
+
+  /* shut down crypto kernel */
+  status = crypto_kernel_shutdown();
+  if (status) 
+    return status;
+
+  /* shutting down crypto kernel frees the srtp debug module as well */
+
+  return err_status_ok;
+}
+
+
 /* 
  * The following code is under consideration for removal.  See
  * SRTP_MAX_TRAILER_LEN 
@@ -1166,6 +1339,9 @@ srtp_dealloc(srtp_t session) {
     if (status) 
       return status; 
     status = auth_dealloc(session->stream_template->rtp_auth);
+    if (status)
+      return status;
+    status = rdbx_dealloc(&session->stream_template->rtp_rdbx);
     if (status)
       return status;
     crypto_free(session->stream_template);
@@ -1296,7 +1472,11 @@ srtp_remove_stream(srtp_t session, uint32_t ssrc) {
     return err_status_no_ctx;
 
   /* remove stream from the list */
-  last_stream->next = stream->next;
+  if (last_stream == stream)
+    /* stream was first in list */
+    session->stream_list = stream->next;
+  else
+    last_stream->next = stream->next;
 
   /* deallocate the stream */
   status = srtp_stream_dealloc(session, stream);
@@ -1324,7 +1504,7 @@ srtp_remove_stream(srtp_t session, uint32_t ssrc) {
 void
 crypto_policy_set_rtp_default(crypto_policy_t *p) {
 
-  p->cipher_type     = AES_128_ICM;           
+  p->cipher_type     = AES_ICM;           
   p->cipher_key_len  = 30;                /* default 128 bits per RFC 3711 */
   p->auth_type       = HMAC_SHA1;             
   p->auth_key_len    = 20;                /* default 160 bits per RFC 3711 */
@@ -1336,7 +1516,7 @@ crypto_policy_set_rtp_default(crypto_policy_t *p) {
 void
 crypto_policy_set_rtcp_default(crypto_policy_t *p) {
 
-  p->cipher_type     = AES_128_ICM;           
+  p->cipher_type     = AES_ICM;           
   p->cipher_key_len  = 30;                 /* default 128 bits per RFC 3711 */
   p->auth_type       = HMAC_SHA1;             
   p->auth_key_len    = 20;                 /* default 160 bits per RFC 3711 */
@@ -1349,12 +1529,12 @@ void
 crypto_policy_set_aes_cm_128_hmac_sha1_32(crypto_policy_t *p) {
 
   /*
-   * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
+   * corresponds to RFC 4568
    *
    * note that this crypto policy is intended for SRTP, but not SRTCP
    */
 
-  p->cipher_type     = AES_128_ICM;           
+  p->cipher_type     = AES_ICM;           
   p->cipher_key_len  = 30;                /* 128 bit key, 112 bit salt */
   p->auth_type       = HMAC_SHA1;             
   p->auth_key_len    = 20;                /* 160 bit key               */
@@ -1368,12 +1548,12 @@ void
 crypto_policy_set_aes_cm_128_null_auth(crypto_policy_t *p) {
 
   /*
-   * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
+   * corresponds to RFC 4568
    *
    * note that this crypto policy is intended for SRTP, but not SRTCP
    */
 
-  p->cipher_type     = AES_128_ICM;           
+  p->cipher_type     = AES_ICM;           
   p->cipher_key_len  = 30;                /* 128 bit key, 112 bit salt */
   p->auth_type       = NULL_AUTH;             
   p->auth_key_len    = 0; 
@@ -1387,7 +1567,7 @@ void
 crypto_policy_set_null_cipher_hmac_sha1_80(crypto_policy_t *p) {
 
   /*
-   * corresponds to draft-ietf-mmusic-sdescriptions-12.txt
+   * corresponds to RFC 4568
    */
 
   p->cipher_type     = NULL_CIPHER;           
@@ -1400,17 +1580,51 @@ crypto_policy_set_null_cipher_hmac_sha1_80(crypto_policy_t *p) {
 }
 
 
+void
+crypto_policy_set_aes_cm_256_hmac_sha1_80(crypto_policy_t *p) {
+
+  /*
+   * corresponds to draft-ietf-avt-big-aes-03.txt
+   */
+
+  p->cipher_type     = AES_ICM;           
+  p->cipher_key_len  = 46;
+  p->auth_type       = HMAC_SHA1;             
+  p->auth_key_len    = 20;                /* default 160 bits per RFC 3711 */
+  p->auth_tag_len    = 10;                /* default 80 bits per RFC 3711 */
+  p->sec_serv        = sec_serv_conf_and_auth;
+}
+
+
+void
+crypto_policy_set_aes_cm_256_hmac_sha1_32(crypto_policy_t *p) {
+
+  /*
+   * corresponds to draft-ietf-avt-big-aes-03.txt
+   *
+   * note that this crypto policy is intended for SRTP, but not SRTCP
+   */
+
+  p->cipher_type     = AES_ICM;           
+  p->cipher_key_len  = 46;
+  p->auth_type       = HMAC_SHA1;             
+  p->auth_key_len    = 20;                /* default 160 bits per RFC 3711 */
+  p->auth_tag_len    = 4;                 /* default 80 bits per RFC 3711 */
+  p->sec_serv        = sec_serv_conf_and_auth;
+}
+
+
 /* 
  * secure rtcp functions
  */
 
 err_status_t 
 srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) {
-  srtcp_hdr_t *hdr = rtcp_hdr;
+  srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr;
   uint32_t *enc_start;      /* pointer to start of encrypted portion  */
   uint32_t *auth_start;     /* pointer to start of auth. portion      */
   uint32_t *trailer;        /* pointer to start of trailer            */
-  uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
+  unsigned enc_octet_len = 0;/* number of octets in encrypted portion */
   uint8_t *auth_tag = NULL; /* location of auth_tag within packet     */
   err_status_t status;   
   int tag_len;
@@ -1497,6 +1711,10 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) {
   auth_start = (uint32_t *)hdr;
   auth_tag = (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t); 
 
+  /* perform EKT processing if needed */
+  ekt_write_data(stream->ekt, auth_tag, tag_len, pkt_octet_len, 
+                rdbx_get_packet_index(&stream->rtp_rdbx));
+
   /* 
    * check sequence number for overruns, and copy it into the packet
    * if its value isn't too big
@@ -1511,14 +1729,14 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) {
   /* 
    * if we're using rindael counter mode, set nonce and seq 
    */
-  if (stream->rtcp_cipher->type == &aes_icm) {
+  if (stream->rtcp_cipher->type->id == AES_ICM) {
     v128_t iv;
     
     iv.v32[0] = 0;
     iv.v32[1] = hdr->ssrc;  /* still in network order! */
     iv.v32[2] = htonl(seq_num >> 16);
     iv.v32[3] = htonl(seq_num << 16);
-    status = aes_icm_set_iv(stream->rtcp_cipher->state, &iv);
+    status = cipher_set_iv(stream->rtcp_cipher, &iv);
 
   } else {  
     v128_t iv;
@@ -1563,10 +1781,14 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) {
   /* initialize auth func context */
   auth_start(stream->rtcp_auth);
 
-  /* per spec, do auth after encryption */
-  /* run auth func over packet, put result into auth_tag */
+  /* 
+   * run auth func over packet (including trailer), and write the
+   * result at auth_tag 
+   */
   status = auth_compute(stream->rtcp_auth, 
-                       (uint8_t *)auth_start,  *pkt_octet_len, auth_tag);
+                       (uint8_t *)auth_start, 
+                       (*pkt_octet_len) + sizeof(srtcp_trailer_t), 
+                       auth_tag);
   debug_print(mod_srtp, "srtcp auth tag:    %s", 
              octet_string_hex_string(auth_tag, tag_len));
   if (status)
@@ -1581,14 +1803,16 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) {
 
 err_status_t 
 srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
-  srtcp_hdr_t *hdr = srtcp_hdr;
+  srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
   uint32_t *enc_start;      /* pointer to start of encrypted portion  */
   uint32_t *auth_start;     /* pointer to start of auth. portion      */
   uint32_t *trailer;        /* pointer to start of trailer            */
-  uint32_t enc_octet_len = 0;/* number of octets in encrypted portion */
+  unsigned enc_octet_len = 0;/* number of octets in encrypted portion */
   uint8_t *auth_tag = NULL; /* location of auth_tag within packet     */
   uint8_t tmp_tag[SRTP_MAX_TAG_LEN];
+  uint8_t tag_copy[SRTP_MAX_TAG_LEN];
   err_status_t status;   
+  unsigned auth_len;
   int tag_len;
   srtp_stream_ctx_t *stream;
   int prefix_len;
@@ -1606,6 +1830,23 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
   if (stream == NULL) {
     if (ctx->stream_template != NULL) {
       stream = ctx->stream_template;
+
+      /* 
+       * check to see if stream_template has an EKT data structure, in
+       * which case we initialize the template using the EKT policy
+       * referenced by that data (which consists of decrypting the
+       * master key from the EKT field)
+       *
+       * this function initializes a *provisional* stream, and this
+       * stream should not be accepted until and unless the packet
+       * passes its authentication check
+       */ 
+      if (stream->ekt != NULL) {
+       status = srtp_stream_init_from_ekt(stream, srtcp_hdr, *pkt_octet_len);
+       if (status)
+         return status;
+      }
+
       debug_print(mod_srtp, "srtcp using provisional stream (SSRC: 0x%08x)", 
                  hdr->ssrc);
     } else {
@@ -1645,29 +1886,45 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
    * (note that srtcp *always* uses authentication, unlike srtp)
    */
   auth_start = (uint32_t *)hdr;
-  auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;
+  auth_len = *pkt_octet_len - tag_len;
+  auth_tag = (uint8_t *)hdr + auth_len;
+
+  /* 
+   * if EKT is in use, then we make a copy of the tag from the packet,
+   * and then zeroize the location of the base tag
+   *
+   * we first re-position the auth_tag pointer so that it points to
+   * the base tag
+   */
+  if (stream->ekt) {
+    auth_tag -= ekt_octets_after_base_tag(stream->ekt);
+    memcpy(tag_copy, auth_tag, tag_len);
+    octet_string_set_to_zero(auth_tag, tag_len);
+    auth_tag = tag_copy;
+    auth_len += tag_len;
+  }
 
   /* 
    * check the sequence number for replays
    */
   /* this is easier than dealing with bitfield access */
   seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK;
+  debug_print(mod_srtp, "srtcp index: %x", seq_num);
   status = rdb_check(&stream->rtcp_rdb, seq_num);
   if (status)
     return status;
-  debug_print(mod_srtp, "srtcp index: %x", seq_num);
 
   /* 
    * if we're using aes counter mode, set nonce and seq 
    */
-  if (stream->rtcp_cipher->type == &aes_icm) {
+  if (stream->rtcp_cipher->type->id == AES_ICM) {
     v128_t iv;
 
     iv.v32[0] = 0;
     iv.v32[1] = hdr->ssrc; /* still in network order! */
     iv.v32[2] = htonl(seq_num >> 16);
     iv.v32[3] = htonl(seq_num << 16);
-    status = aes_icm_set_iv(stream->rtcp_cipher->state, &iv);
+    status = cipher_set_iv(stream->rtcp_cipher, &iv);
 
   } else {  
     v128_t iv;
@@ -1688,8 +1945,7 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
 
   /* run auth func over packet, put result into tmp_tag */
   status = auth_compute(stream->rtcp_auth, (uint8_t *)auth_start,  
-                       *pkt_octet_len - (tag_len + sizeof(srtcp_trailer_t)),
-                       tmp_tag);
+                       auth_len, tmp_tag);
   debug_print(mod_srtp, "srtcp computed tag:       %s", 
              octet_string_hex_string(tmp_tag, tag_len));
   if (status)
@@ -1716,15 +1972,21 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
 
   /* if we're decrypting, exor keystream into the message */
   if (enc_start) {
-    status = cipher_encrypt(stream->rtcp_cipher, 
+    status = cipher_decrypt(stream->rtcp_cipher, 
                            (uint8_t *)enc_start, &enc_octet_len);
     if (status)
       return err_status_cipher_fail;
   }
 
-  /* decrease the packet length by the length of the auth tag and seq_num*/
+  /* decrease the packet length by the length of the auth tag and seq_num */
   *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t));
 
+  /*
+   * if EKT is in effect, subtract the EKT data out of the packet
+   * length
+   */
+  *pkt_octet_len -= ekt_octets_after_base_tag(stream->ekt);
+
   /* 
    * verify that stream is for received traffic - this check will
    * detect SSRC collisions, since a stream that appears in both
@@ -1776,3 +2038,134 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {
     
   return err_status_ok;  
 }
+
+
+
+/*
+ * dtls keying for srtp 
+ */
+
+err_status_t
+crypto_policy_set_from_profile_for_rtp(crypto_policy_t *policy, 
+                                      srtp_profile_t profile) {
+
+  /* set SRTP policy from the SRTP profile in the key set */
+  switch(profile) {
+  case srtp_profile_aes128_cm_sha1_80:
+    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
+    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_aes128_cm_sha1_32:
+    crypto_policy_set_aes_cm_128_hmac_sha1_32(policy);
+    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_null_sha1_80:
+    crypto_policy_set_null_cipher_hmac_sha1_80(policy);
+    crypto_policy_set_null_cipher_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_aes256_cm_sha1_80:
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_aes256_cm_sha1_32:
+    crypto_policy_set_aes_cm_256_hmac_sha1_32(policy);
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    break;
+    /* the following profiles are not (yet) supported */
+  case srtp_profile_null_sha1_32:
+  default:
+    return err_status_bad_param;
+  }
+
+  return err_status_ok;
+}
+
+err_status_t
+crypto_policy_set_from_profile_for_rtcp(crypto_policy_t *policy, 
+                                       srtp_profile_t profile) {
+
+  /* set SRTP policy from the SRTP profile in the key set */
+  switch(profile) {
+  case srtp_profile_aes128_cm_sha1_80:
+    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_aes128_cm_sha1_32:
+    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_null_sha1_80:
+    crypto_policy_set_null_cipher_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_aes256_cm_sha1_80:
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    break;
+  case srtp_profile_aes256_cm_sha1_32:
+    crypto_policy_set_aes_cm_256_hmac_sha1_80(policy);
+    break;
+    /* the following profiles are not (yet) supported */
+  case srtp_profile_null_sha1_32:
+  default:
+    return err_status_bad_param;
+  }
+
+  return err_status_ok;
+}
+
+void
+append_salt_to_key(uint8_t *key, unsigned int bytes_in_key,
+                  uint8_t *salt, unsigned int bytes_in_salt) {
+
+  memcpy(key + bytes_in_key, salt, bytes_in_salt);
+
+}
+
+unsigned int
+srtp_profile_get_master_key_length(srtp_profile_t profile) {
+
+  switch(profile) {
+  case srtp_profile_aes128_cm_sha1_80:
+    return 16;
+    break;
+  case srtp_profile_aes128_cm_sha1_32:
+    return 16;
+    break;
+  case srtp_profile_null_sha1_80:
+    return 16;
+    break;
+  case srtp_profile_aes256_cm_sha1_80:
+    return 32;
+    break;
+  case srtp_profile_aes256_cm_sha1_32:
+    return 32;
+    break;
+    /* the following profiles are not (yet) supported */
+  case srtp_profile_null_sha1_32:
+  default:
+    return 0;  /* indicate error by returning a zero */
+  }
+}
+
+unsigned int
+srtp_profile_get_master_salt_length(srtp_profile_t profile) {
+
+  switch(profile) {
+  case srtp_profile_aes128_cm_sha1_80:
+    return 14;
+    break;
+  case srtp_profile_aes128_cm_sha1_32:
+    return 14;
+    break;
+  case srtp_profile_null_sha1_80:
+    return 14;
+    break;
+  case srtp_profile_aes256_cm_sha1_80:
+    return 14;
+    break;
+  case srtp_profile_aes256_cm_sha1_32:
+    return 14;
+    break;
+    /* the following profiles are not (yet) supported */
+  case srtp_profile_null_sha1_32:
+  default:
+    return 0;  /* indicate error by returning a zero */
+  }
+}
index 2beedfd5639a063b695a209369d0901c137cea4f..b2bc1d78d1ab45e295a0b57a667068b42b216dc9 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright(c) 2001-2005 Cisco Systems, Inc.
+ * Copyright(c) 2001-2006 Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
diff --git a/libs/srtp/test/dtls_srtp_driver.c b/libs/srtp/test/dtls_srtp_driver.c
new file mode 100644 (file)
index 0000000..48e72fb
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * dtls_srtp_driver.c
+ *
+ * test driver for DTLS-SRTP functions
+ *
+ * David McGrew
+ * Cisco Systems, Inc.
+ */
+/*
+ *     
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *   Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 
+ *   Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ * 
+ *   Neither the name of the Cisco Systems, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>    /* for printf()          */
+#include "getopt_s.h" /* for local getopt()    */
+#include "srtp_priv.h"
+
+err_status_t 
+test_dtls_srtp(void);
+
+srtp_hdr_t *
+srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc);
+
+void
+usage(char *prog_name) {
+  printf("usage: %s [ -t ][ -c ][ -v ][-d <debug_module> ]* [ -l ]\n"
+         "  -d <mod>   turn on debugging module <mod>\n"
+         "  -l         list debugging modules\n", prog_name);
+  exit(1);
+}
+
+int
+main(int argc, char *argv[]) {
+  unsigned do_list_mods      = 0;
+  int q;
+  err_status_t err;
+
+  printf("dtls_srtp_driver\n");
+
+  /* initialize srtp library */
+  err = srtp_init();
+  if (err) {
+    printf("error: srtp init failed with error code %d\n", err);
+    exit(1);
+  }
+
+  /* process input arguments */
+  while (1) {
+    q = getopt_s(argc, argv, "ld:");
+    if (q == -1) 
+      break;
+    switch (q) {
+    case 'l':
+      do_list_mods = 1;
+      break;
+    case 'd':
+      err = crypto_kernel_set_debug_module(optarg_s, 1);
+      if (err) {
+        printf("error: set debug module (%s) failed\n", optarg_s);
+        exit(1);
+      }  
+      break;
+    default:
+      usage(argv[0]);
+    }    
+  }
+
+  if (do_list_mods) {
+    err = crypto_kernel_list_debug_modules();
+    if (err) {
+      printf("error: list of debug modules failed\n");
+      exit(1);
+    }
+  }
+
+  printf("testing dtls_srtp...");
+  err = test_dtls_srtp();
+  if (err) {
+    printf("\nerror (code %d)\n", err);
+    exit(1);
+  }
+  printf("passed\n");
+  
+  /* shut down srtp library */
+  err = srtp_shutdown();
+  if (err) {
+    printf("error: srtp shutdown failed with error code %d\n", err);
+    exit(1);
+  }
+
+  return 0;
+}
+
+
+err_status_t
+test_dtls_srtp(void) {
+  srtp_hdr_t *test_packet;
+  int test_packet_len = 80;
+  srtp_t s;
+  srtp_policy_t policy;
+  uint8_t key[SRTP_MAX_KEY_LEN];
+  uint8_t salt[SRTP_MAX_KEY_LEN];
+  unsigned int key_len, salt_len;
+  srtp_profile_t profile;
+  err_status_t err;
+
+  /* create a 'null' SRTP session */
+  err = srtp_create(&s, NULL);
+  if (err) 
+    return err;
+
+  /* 
+   * verify that packet-processing functions behave properly - we
+   * expect that these functions will return err_status_no_ctx
+   */
+  test_packet = srtp_create_test_packet(80, 0xa5a5a5a5);
+  if (test_packet == NULL) 
+    return err_status_alloc_fail;
+  err = srtp_protect(s, test_packet, &test_packet_len);
+  if (err != err_status_no_ctx) {
+    printf("wrong return value from srtp_protect() (got code %d)\n", 
+          err);
+    return err_status_fail;
+  }
+  err = srtp_unprotect(s, test_packet, &test_packet_len);
+  if (err != err_status_no_ctx) {
+    printf("wrong return value from srtp_unprotect() (got code %d)\n", 
+          err);
+    return err_status_fail;
+  }
+  err = srtp_protect_rtcp(s, test_packet, &test_packet_len);
+  if (err != err_status_no_ctx) {
+    printf("wrong return value from srtp_protect_rtcp() (got code %d)\n", 
+          err);
+    return err_status_fail;
+  }
+  err = srtp_unprotect_rtcp(s, test_packet, &test_packet_len);
+  if (err != err_status_no_ctx) {
+    printf("wrong return value from srtp_unprotect_rtcp() (got code %d)\n", 
+          err);
+    return err_status_fail;
+  }
+
+
+  /* 
+   * set keys to known values for testing
+   */
+  profile = srtp_profile_aes128_cm_sha1_80;
+  key_len = srtp_profile_get_master_key_length(profile);
+  salt_len = srtp_profile_get_master_salt_length(profile);
+  memset(key, 0xff, key_len);
+  memset(salt, 0xee, salt_len);
+  append_salt_to_key(key, key_len, salt, salt_len);
+  policy.key  = key;
+
+  /* initialize SRTP policy from profile  */
+  err = crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile);
+  if (err) return err;
+  err = crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile);
+  if (err) return err;
+  policy.ssrc.type  = ssrc_any_inbound;
+  policy.ekt = NULL;
+  policy.window_size = 128;
+  policy.allow_repeat_tx = 0;
+  policy.next = NULL;
+    
+  err = srtp_add_stream(s, &policy);
+  if (err)
+    return err;
+  
+  err = srtp_dealloc(s);
+  if (err)
+    return err;
+
+  free(test_packet);
+
+  return err_status_ok;
+}
+
+
+
+/*
+ * srtp_create_test_packet(len, ssrc) returns a pointer to a
+ * (malloced) example RTP packet whose data field has the length given
+ * by pkt_octet_len and the SSRC value ssrc.  The total length of the
+ * packet is twelve octets longer, since the header is at the
+ * beginning.  There is room at the end of the packet for a trailer,
+ * and the four octets following the packet are filled with 0xff
+ * values to enable testing for overwrites.
+ *
+ * note that the location of the test packet can (and should) be
+ * deallocated with the free() call once it is no longer needed.
+ */
+
+srtp_hdr_t *
+srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc) {
+  int i;
+  uint8_t *buffer;
+  srtp_hdr_t *hdr;
+  int bytes_in_hdr = 12;
+
+  /* allocate memory for test packet */
+  hdr = malloc(pkt_octet_len + bytes_in_hdr
+              + SRTP_MAX_TRAILER_LEN + 4);
+  if (!hdr)
+    return NULL;
+  
+  hdr->version = 2;              /* RTP version two     */
+  hdr->p    = 0;                 /* no padding needed   */
+  hdr->x    = 0;                 /* no header extension */
+  hdr->cc   = 0;                 /* no CSRCs            */
+  hdr->m    = 0;                 /* marker bit          */
+  hdr->pt   = 0xf;               /* payload type        */
+  hdr->seq  = htons(0x1234);     /* sequence number     */
+  hdr->ts   = htonl(0xdecafbad); /* timestamp           */
+  hdr->ssrc = htonl(ssrc);       /* synch. source       */
+
+  buffer = (uint8_t *)hdr;
+  buffer += bytes_in_hdr;
+
+  /* set RTP data to 0xab */
+  for (i=0; i < pkt_octet_len; i++)
+    *buffer++ = 0xab;
+
+  /* set post-data value to 0xffff to enable overrun checking */
+  for (i=0; i < SRTP_MAX_TRAILER_LEN+4; i++)
+    *buffer++ = 0xff;
+
+  return hdr;
+}
diff --git a/libs/srtp/test/getopt_s.c b/libs/srtp/test/getopt_s.c
new file mode 100644 (file)
index 0000000..243ad6e
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * getopt.c
+ *
+ * a minimal implementation of the getopt() function, written so that
+ * test applications that use that function can run on non-POSIX
+ * platforms 
+ *
+ */
+/*
+ *     
+ * Copyright (c) 2001-2006 Cisco Systems, Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *   Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 
+ *   Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ * 
+ *   Neither the name of the Cisco Systems, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdlib.h>  /* for NULL */
+
+int optind_s = 0;
+
+char *optarg_s;
+
+#define GETOPT_FOUND_WITHOUT_ARGUMENT    2
+#define GETOPT_FOUND_WITH_ARGUMENT       1
+#define GETOPT_NOT_FOUND                 0 
+
+static int 
+getopt_check_character(char c, const char *string) {
+  unsigned int max_string_len = 128;
+
+  while (*string != 0) {
+    if (max_string_len == 0) {
+      return '?';
+    }
+    if (*string++ == c) {
+      if (*string == ':') {
+       return GETOPT_FOUND_WITH_ARGUMENT;
+      } else {
+       return GETOPT_FOUND_WITHOUT_ARGUMENT;
+      }
+    }
+  }
+  return GETOPT_NOT_FOUND;
+}
+
+int
+getopt_s(int argc, 
+       char * const argv[], 
+       const char *optstring) {
+
+
+  while (optind_s + 1 < argc) {
+    char *string;
+    
+    /* move 'string' on to next argument */
+    optind_s++;
+    string = argv[optind_s];
+
+    if (string == NULL)
+      return '?'; /* NULL argument string */
+
+    if (string[0] != '-')
+      return -1; /* found an unexpected character */
+
+    switch(getopt_check_character(string[1], optstring)) {
+    case GETOPT_FOUND_WITH_ARGUMENT:
+      if (optind_s + 1 < argc) {
+       optind_s++;
+       optarg_s = argv[optind_s];
+       return string[1]; 
+      } else {
+       return '?';  /* argument missing */
+      }
+    case GETOPT_FOUND_WITHOUT_ARGUMENT:
+      return string[1];
+    case GETOPT_NOT_FOUND:
+    default:
+      return '?'; /* didn't find expected character */
+      break;
+    }
+  }
+
+  return -1;
+}
diff --git a/libs/srtp/test/rdbx_driver b/libs/srtp/test/rdbx_driver
new file mode 100755 (executable)
index 0000000..575cd5d
Binary files /dev/null and b/libs/srtp/test/rdbx_driver differ
index 5107ecf22977f00388da3ed2fd83692336267f19..838cc43a8458d5e819a4d893051323981a0d71a2 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -43,8 +43,8 @@
  *
  */
 
-#include <stdio.h>        /* for printf() */
-#include <unistd.h>       /* for getopt() */
+#include <stdio.h>    /* for printf()          */
+#include "getopt_s.h" /* for local getopt()    */
 
 #include "rdbx.h"
 
 #include "ut_sim.h"
 
 err_status_t 
-test_replay_dbx(int num_trials);
+test_replay_dbx(int num_trials, unsigned long ws);
 
 double
-rdbx_check_adds_per_second(int num_trials);
+rdbx_check_adds_per_second(int num_trials, unsigned long ws);
 
 void
 usage(char *prog_name) {
@@ -70,13 +70,13 @@ int
 main (int argc, char *argv[]) {
   double rate;
   err_status_t status;
-  char q;
+  int q;
   unsigned do_timing_test = 0;
   unsigned do_validation = 0;
 
   /* process input arguments */
   while (1) {
-    q = getopt(argc, argv, "tv");
+    q = getopt_s(argc, argv, "tv");
     if (q == -1) 
       break;
     switch (q) {
@@ -99,9 +99,18 @@ main (int argc, char *argv[]) {
     usage(argv[0]);
 
   if (do_validation) {
-  printf("testing rdbx_t...\n");
+    printf("testing rdbx_t (ws=128)...\n");
 
-    status = test_replay_dbx(1 << 12);
+    status = test_replay_dbx(1 << 12, 128);
+    if (status) {
+      printf("failed\n");
+      exit(1);
+    }
+    printf("passed\n");
+
+    printf("testing rdbx_t (ws=1024)...\n");
+
+    status = test_replay_dbx(1 << 12, 1024);
     if (status) {
       printf("failed\n");
       exit(1);
@@ -110,8 +119,10 @@ main (int argc, char *argv[]) {
   }
 
   if (do_timing_test) {
-    rate = rdbx_check_adds_per_second(1 << 18);
-    printf("rdbx_check/replay_adds per second: %e\n", rate);
+    rate = rdbx_check_adds_per_second(1 << 18, 128);
+    printf("rdbx_check/replay_adds per second (ws=128): %e\n", rate);
+    rate = rdbx_check_adds_per_second(1 << 18, 1024);
+    printf("rdbx_check/replay_adds per second (ws=1024): %e\n", rate);
   }
   
   return 0;
@@ -119,8 +130,11 @@ main (int argc, char *argv[]) {
 
 void
 print_rdbx(rdbx_t *rdbx) {
+  char buf[2048];
   printf("rdbx: {%llu, %s}\n",
-        (unsigned long long)(rdbx->index), v128_bit_string(&rdbx->bitmask));
+        (unsigned long long)(rdbx->index),
+        bitvector_bit_string(&rdbx->bitmask, buf, sizeof(buf))
+);
 }
 
 
@@ -183,28 +197,38 @@ rdbx_check_expect_failure(rdbx_t *rdbx, uint32_t idx) {
 }
 
 err_status_t
-rdbx_check_unordered(rdbx_t *rdbx, uint32_t idx) {
+rdbx_check_add_unordered(rdbx_t *rdbx, uint32_t idx) {
+  int delta;
+  xtd_seq_num_t est;
   err_status_t rstat;
 
-  rstat = rdbx_check(rdbx, idx);
+  delta = index_guess(&rdbx->index, &est, idx);
+
+  rstat = rdbx_check(rdbx, delta);
   if ((rstat != err_status_ok) && (rstat != err_status_replay_old)) {
-    printf("replay_check_unordered failed at index %u\n", idx);
+    printf("replay_check_add_unordered failed at index %u\n", idx);
     return err_status_algo_fail;
   }
+  if (rstat == err_status_replay_old) {
+       return err_status_ok;
+  }
+  if (rdbx_add_index(rdbx, delta) != err_status_ok) {
+    printf("rdbx_add_index failed at index %u\n", idx);
+    return err_status_algo_fail;
+  }  
+
   return err_status_ok;
 }
 
-#define MAX_IDX 160
-
 err_status_t
-test_replay_dbx(int num_trials) {
+test_replay_dbx(int num_trials, unsigned long ws) {
   rdbx_t rdbx;
   uint32_t idx, ircvd;
   ut_connection utc;
   err_status_t status;
   int num_fp_trials;
 
-  status = rdbx_init(&rdbx);
+  status = rdbx_init(&rdbx, ws);
   if (status) {
     printf("replay_init failed with error code %d\n", status);
     exit(1);
@@ -241,7 +265,9 @@ test_replay_dbx(int num_trials) {
   printf("passed\n");
 
   /* re-initialize */
-  if (rdbx_init(&rdbx) != err_status_ok) {
+  rdbx_dealloc(&rdbx);
+
+  if (rdbx_init(&rdbx, ws) != err_status_ok) {
     printf("replay_init failed\n");
     return err_status_init_fail;
   }
@@ -257,12 +283,40 @@ test_replay_dbx(int num_trials) {
   printf("\ttesting non-sequential insertion...");  
   for (idx=0; idx < num_trials; idx++) {
     ircvd = ut_next_index(&utc);
-    status = rdbx_check_unordered(&rdbx, ircvd);
+    status = rdbx_check_add_unordered(&rdbx, ircvd);
+    if (status)
+      return status;
+       status = rdbx_check_expect_failure(&rdbx, ircvd);
+       if (status)
+               return status;
+  }
+  printf("passed\n");
+
+  /* re-initialize */
+  rdbx_dealloc(&rdbx);
+
+  if (rdbx_init(&rdbx, ws) != err_status_ok) {
+    printf("replay_init failed\n");
+    return err_status_init_fail;
+  }
+
+  /*
+   * test insertion with large gaps.
+   * check for false positives for each insertion.
+   */
+  printf("\ttesting insertion with large gaps...");  
+  for (idx=0, ircvd=0; idx < num_trials; idx++, ircvd += (1 << (rand() % 12))) {
+    status = rdbx_check_add(&rdbx, ircvd);
+    if (status)
+      return status;
+    status = rdbx_check_expect_failure(&rdbx, ircvd);
     if (status)
       return status;
   }
   printf("passed\n");
 
+  rdbx_dealloc(&rdbx);
+
   return err_status_ok;
 }
 
@@ -272,7 +326,7 @@ test_replay_dbx(int num_trials) {
 #include <stdlib.h>     /* for random() */
 
 double
-rdbx_check_adds_per_second(int num_trials) {
+rdbx_check_adds_per_second(int num_trials, unsigned long ws) {
   uint32_t i;
   int delta;
   rdbx_t rdbx;
@@ -280,7 +334,7 @@ rdbx_check_adds_per_second(int num_trials) {
   clock_t timer;
   int failures;                    /* count number of failures        */
   
-  if (rdbx_init(&rdbx) != err_status_ok) {
+  if (rdbx_init(&rdbx, ws) != err_status_ok) {
     printf("replay_init failed\n");
     exit(1);
   }  
@@ -301,6 +355,8 @@ rdbx_check_adds_per_second(int num_trials) {
 
   printf("number of failures: %d \n", failures);
 
+  rdbx_dealloc(&rdbx);
+
   return (double) CLOCKS_PER_SEC * num_trials / timer;
 }
 
diff --git a/libs/srtp/test/replay_driver b/libs/srtp/test/replay_driver
new file mode 100755 (executable)
index 0000000..5342460
Binary files /dev/null and b/libs/srtp/test/replay_driver differ
index 4aa2b021585114469cb4fc5a208bc92a744352fc..b11a68ca89707a201b3e6798c2ad1e23e905fce5 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 #include "rdb.h"
 #include "ut_sim.h"
 
-void
+/*
+ * num_trials defines the number of trials that are used in the
+ * validation functions below
+ */
+
+unsigned num_trials = 1 << 16;
+
+err_status_t
 test_rdb_db(void);
 
 double
@@ -56,9 +63,14 @@ rdb_check_adds_per_second(void);
 
 int
 main (void) {
-
+  err_status_t err;
+  
   printf("testing anti-replay database (rdb_t)...\n");
-  test_rdb_db();
+  err = test_rdb_db();
+  if (err) {
+    printf("failed\n");
+    exit(1);
+  }
   printf("done\n");
 
   printf("rdb_check/rdb_adds per second: %e\n",
@@ -73,73 +85,138 @@ print_rdb(rdb_t *rdb) {
   printf("rdb: {%u, %s}\n", rdb->window_start, v128_bit_string(&rdb->bitmask));
 }
 
-void
+err_status_t
 rdb_check_add(rdb_t *rdb, uint32_t idx) {
 
   if (rdb_check(rdb, idx) != err_status_ok) {
     printf("rdb_check failed at index %u\n", idx);
-    return;
+    return err_status_fail;
   }
-  if (rdb_add_index(rdb, idx) != err_status_ok)
+  if (rdb_add_index(rdb, idx) != err_status_ok) {
     printf("rdb_add_index failed at index %u\n", idx);
+    return err_status_fail;
+  }
 
+  return err_status_ok;
 }
 
-void
+err_status_t
 rdb_check_expect_failure(rdb_t *rdb, uint32_t idx) {
-
-  if (rdb_check(rdb, idx) != err_status_fail)
+  err_status_t err;
+  
+  err = rdb_check(rdb, idx);
+  if ((err != err_status_replay_old) && (err != err_status_replay_fail)) {
     printf("rdb_check failed at index %u (false positive)\n", idx);
+    return err_status_fail;
+  }
+
+  return err_status_ok;
 }
 
-void
-rdb_check_unordered(rdb_t *rdb, uint32_t idx) {
+err_status_t
+rdb_check_add_unordered(rdb_t *rdb, uint32_t idx) {
   err_status_t rstat;
 
+ /* printf("index: %u\n", idx); */
   rstat = rdb_check(rdb, idx);
-  if ((rstat != err_status_ok) && (rstat != err_status_replay_old))
-    printf("rdb_check_unordered failed at index %u\n", idx);
-}
-
-
+  if ((rstat != err_status_ok) && (rstat != err_status_replay_old)) {
+    printf("rdb_check_add_unordered failed at index %u\n", idx);
+    return rstat;
+  }
+  if (rstat == err_status_replay_old) {
+       return err_status_ok;
+  }
+  if (rdb_add_index(rdb, idx) != err_status_ok) {
+    printf("rdb_add_index failed at index %u\n", idx);
+    return err_status_fail;
+  }  
 
-#define MAX_IDX 160
+  return err_status_ok;
+}
 
-void
+err_status_t
 test_rdb_db() {
   rdb_t rdb;
   uint32_t idx, ircvd;
   ut_connection utc;
-  
+  err_status_t err;
+
   if (rdb_init(&rdb) != err_status_ok) {
     printf("rdb_init failed\n");
-    exit(1);
+    return err_status_init_fail;
   }
 
   /* test sequential insertion */
-  for (idx=0; idx < MAX_IDX; idx++) {
-    rdb_check_add(&rdb, idx);
+  for (idx=0; idx < num_trials; idx++) {
+    err = rdb_check_add(&rdb, idx);
+    if (err) 
+      return err;
   }
 
   /* test for false positives */
-  for (idx=0; idx < MAX_IDX; idx++) {
-    rdb_check_expect_failure(&rdb, idx);
+  for (idx=0; idx < num_trials; idx++) {
+    err = rdb_check_expect_failure(&rdb, idx);
+    if (err) 
+      return err;
   }
 
   /* re-initialize */
   if (rdb_init(&rdb) != err_status_ok) {
     printf("rdb_init failed\n");
-    exit(1);
+    return err_status_fail;
   }
 
   /* test non-sequential insertion */
   ut_init(&utc);
   
-  for (idx=0; idx < MAX_IDX; idx++) {
+  for (idx=0; idx < num_trials; idx++) {
     ircvd = ut_next_index(&utc);
-    rdb_check_unordered(&rdb, ircvd);
+    err = rdb_check_add_unordered(&rdb, ircvd);
+    if (err) 
+      return err;
+    err = rdb_check_expect_failure(&rdb, ircvd);
+    if (err) 
+      return err;
   }
-  
+
+  /* re-initialize */
+  if (rdb_init(&rdb) != err_status_ok) {
+    printf("rdb_init failed\n");
+    return err_status_fail;
+  }
+
+  /* test insertion with large gaps */
+  for (idx=0, ircvd=0; idx < num_trials; idx++, ircvd += (1 << (rand() % 10))) {
+    err = rdb_check_add(&rdb, ircvd);
+    if (err)
+      return err;
+    err = rdb_check_expect_failure(&rdb, ircvd);
+    if (err)
+      return err;
+  }
+
+  /* re-initialize */
+  if (rdb_init(&rdb) != err_status_ok) {
+    printf("rdb_init failed\n");
+    return err_status_fail;
+  }
+
+  /* test loss of first 513 packets */
+  for (idx=0; idx < num_trials; idx++) {
+    err = rdb_check_add(&rdb, idx + 513);
+    if (err) 
+      return err;
+  }
+
+  /* test for false positives */
+  for (idx=0; idx < num_trials + 513; idx++) {
+    err = rdb_check_expect_failure(&rdb, idx);
+    if (err) 
+      return err;
+  }
+
+
+  return err_status_ok;
 }
 
 #include <time.h>       /* for clock()  */
diff --git a/libs/srtp/test/roc_driver b/libs/srtp/test/roc_driver
new file mode 100755 (executable)
index 0000000..2458d8c
Binary files /dev/null and b/libs/srtp/test/roc_driver differ
index 42f4185f0fd2897a0999a671cf09174804e57478..0ecab4bd9142f0f581845a1ba0d0f84b93369e6d 100644 (file)
@@ -9,7 +9,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -138,6 +138,12 @@ roc_test(int num_trials) {
           ref, local, est, ircvd, delta);
 #endif
     
+    if (local + delta != est) {
+      printf(" *bad delta*: local %llu + delta %d != est %llu\n",
+            (unsigned long long)local, delta, (unsigned long long)est);
+      return err_status_algo_fail;
+    }
+
     /* now update local xtd_seq_num_t as necessary */
     if (delta > 0) 
       index_advance(&local, delta);
index 8804238d78535dadaac7e9c96db64f0807fdbfe9..8f656983f7f06851d3c1234ee6c303f15107e943 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 
-#include "rtp.h"
+#include "rtp_priv.h"
 
 #include <stdio.h>
 #include <string.h>
 #define PRINT_DEBUG    0    /* set to 1 to print out debugging data */
 #define VERBOSE_DEBUG  0    /* set to 1 to print out more data      */
 
-ssize_t
-rtp_sendto(rtp_sender_t *sender, const void* msg, int len) {
+int
+rtp_sendto(rtp_sender_t sender, const void* msg, int len) {
   int octets_sent;
   err_status_t stat;
-  int pkt_len = len + rtp_header_len;
+  int pkt_len = len + RTP_HEADER_LEN;
 
   /* marshal data */
   strncpy(sender->message.body, msg, len);
@@ -61,14 +61,19 @@ rtp_sendto(rtp_sender_t *sender, const void* msg, int len) {
   return octets_sent;
 }
 
-ssize_t
-rtp_recvfrom(rtp_receiver_t *receiver, void *msg, int *len) {
+int
+rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len) {
   int octets_recvd;
   err_status_t stat;
   
   octets_recvd = recvfrom(receiver->socket, (void *)&receiver->message,
                         *len, 0, (struct sockaddr *) NULL, 0);
 
+  if (octets_recvd == -1) {
+    *len = 0;
+    return -1;
+  }
+
   /* verify rtp header */
   if (receiver->message.header.version != 2) {
     *len = 0;
@@ -99,10 +104,10 @@ rtp_recvfrom(rtp_receiver_t *receiver, void *msg, int *len) {
 }
 
 int
-rtp_sender_init(rtp_sender_t *sender, 
-               int socket
+rtp_sender_init(rtp_sender_t sender, 
+               int sock, 
                struct sockaddr_in addr,
-               uint32_t ssrc) {
+               unsigned int ssrc) {
 
   /* set header values */
   sender->message.header.ssrc    = htonl(ssrc);
@@ -116,17 +121,17 @@ rtp_sender_init(rtp_sender_t *sender,
   sender->message.header.cc      = 0;
 
   /* set other stuff */
-  sender->socket = socket;
+  sender->socket = sock;
   sender->addr = addr;
 
   return 0;
 }
 
 int
-rtp_receiver_init(rtp_receiver_t *rcvr, 
-                 int socket
+rtp_receiver_init(rtp_receiver_t rcvr, 
+                 int sock, 
                  struct sockaddr_in addr,
-                 uint32_t ssrc) {
+                 unsigned int ssrc) {
   
   /* set header values */
   rcvr->message.header.ssrc    = htonl(ssrc);
@@ -140,11 +145,48 @@ rtp_receiver_init(rtp_receiver_t *rcvr,
   rcvr->message.header.cc      = 0;
 
   /* set other stuff */
-  rcvr->socket = socket;
+  rcvr->socket = sock;
   rcvr->addr = addr;
 
   return 0;
 }
 
+int
+rtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy) {
+  return srtp_create(&sender->srtp_ctx, policy);
+}
 
+int
+rtp_sender_deinit_srtp(rtp_sender_t sender) {
+  return srtp_dealloc(sender->srtp_ctx);
+}
 
+int
+rtp_receiver_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy) {
+  return srtp_create(&sender->srtp_ctx, policy);
+}
+
+int
+rtp_receiver_deinit_srtp(rtp_receiver_t sender) {
+  return srtp_dealloc(sender->srtp_ctx);
+}
+
+rtp_sender_t 
+rtp_sender_alloc(void) {
+  return (rtp_sender_t)malloc(sizeof(rtp_sender_ctx_t));
+}
+
+void
+rtp_sender_dealloc(rtp_sender_t rtp_ctx) {
+  free(rtp_ctx);
+}
+
+rtp_receiver_t 
+rtp_receiver_alloc(void) {
+  return (rtp_receiver_t)malloc(sizeof(rtp_receiver_ctx_t));
+}
+
+void
+rtp_receiver_dealloc(rtp_receiver_t rtp_ctx) {
+  return free(rtp_ctx);
+}
index 906080de1e8b96c7df88900b8e6a541d305f1bae..f18d42045e0e4eac7c1d17afb6acbb773b9d80fc 100644 (file)
@@ -16,7 +16,7 @@
 
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
 
 
 #include "datatypes.h"
+#include "getopt_s.h"       /* for local getopt()  */
 
 #include <stdio.h>          /* for printf, fprintf */
 #include <stdlib.h>         /* for atoi()          */
 #include <errno.h>
-#include <unistd.h>         /* for close()         */
+#include <signal.h>         /* for signal()        */
+
 #include <string.h>         /* for strncpy()       */
 #include <time.h>          /* for usleep()        */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>         /* for close()         */
+#endif
 #ifdef HAVE_SYS_SOCKET_H
 # include <sys/socket.h>
 #endif
@@ -113,6 +119,18 @@ void
 leave_group(int sock, struct ip_mreq mreq, char *name);
 
 
+/*
+ * setup_signal_handler() sets up a signal handler to trigger
+ * cleanups after an interrupt
+ */
+int setup_signal_handler(char* name);
+
+/*
+ * handle_signal(...) handles interrupt signal to trigger cleanups
+ */
+
+volatile int interrupted = 0;
+
 /*
  * program_type distinguishes the [s]rtp sender and receiver cases
  */
@@ -156,6 +174,10 @@ main (int argc, char *argv[]) {
   }
 #endif
 
+  if (setup_signal_handler(argv[0]) != 0) {
+    exit(1);
+  }
+
   /* initialize srtp library */
   status = srtp_init();
   if (status) {
@@ -165,13 +187,13 @@ main (int argc, char *argv[]) {
 
   /* check args */
   while (1) {
-    c = getopt(argc, argv, "k:rsaeld:");
+    c = getopt_s(argc, argv, "k:rsaeld:");
     if (c == -1) {
       break;
     }
     switch (c) {
     case 'k':
-      input_key = optarg;
+      input_key = optarg_s;
       break;
     case 'e':
       sec_servs |= sec_serv_conf;
@@ -186,9 +208,9 @@ main (int argc, char *argv[]) {
       prog_type = sender;
       break;
     case 'd':
-      status = crypto_kernel_set_debug_module(optarg, 1);
+      status = crypto_kernel_set_debug_module(optarg_s, 1);
       if (status) {
-        printf("error: set debug module (%s) failed\n", optarg);
+        printf("error: set debug module (%s) failed\n", optarg_s);
         exit(1);
       }
       break;
@@ -222,16 +244,16 @@ main (int argc, char *argv[]) {
     usage(argv[0]);
   }
     
-  if (argc != optind + 2) {
+  if (argc != optind_s + 2) {
     /* wrong number of arguments */
     usage(argv[0]);
   }
 
   /* get address from arg */
-  address = argv[optind++];
+  address = argv[optind_s++];
 
   /* get port from arg */
-  port = atoi(argv[optind++]);
+  port = atoi(argv[optind_s++]);
 
   /* set address */
 #ifdef HAVE_INET_ATON
@@ -261,7 +283,7 @@ main (int argc, char *argv[]) {
     err = errno;
 #endif
     fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err);
-    exit(1);
+   exit(1);
   }
 
   name.sin_addr   = rcvr_addr;    
@@ -327,7 +349,10 @@ main (int argc, char *argv[]) {
     policy.ssrc.type  = ssrc_specific;
     policy.ssrc.value = ssrc;
     policy.key  = (uint8_t *) key;
+    policy.ekt  = NULL;
     policy.next = NULL;
+    policy.window_size = 128;
+    policy.allow_repeat_tx = 0;
     policy.rtp.sec_serv = sec_servs;
     policy.rtcp.sec_serv = sec_serv_none;  /* we don't do RTCP anyway */
 
@@ -380,6 +405,9 @@ main (int argc, char *argv[]) {
     policy.rtcp.auth_key_len   = 0;
     policy.rtcp.auth_tag_len   = 0;
     policy.rtcp.sec_serv       = sec_serv_none;   
+    policy.window_size         = 0;
+    policy.allow_repeat_tx     = 0;
+    policy.ekt                 = NULL;
     policy.next                = NULL;
   }
 
@@ -399,8 +427,13 @@ main (int argc, char *argv[]) {
 #endif /* BEW */
 
     /* initialize sender's rtp and srtp contexts */
-    rtp_sender_init(&snd, sock, name, ssrc); 
-    status = srtp_create(&snd.srtp_ctx, &policy);
+    snd = rtp_sender_alloc();
+    if (snd == NULL) {
+      fprintf(stderr, "error: malloc() failed\n");
+      exit(1);
+    }
+    rtp_sender_init(snd, sock, name, ssrc); 
+    status = rtp_sender_init_srtp(snd, &policy);
     if (status) {
       fprintf(stderr, 
              "error: srtp_create() failed with code %d\n", 
@@ -419,18 +452,22 @@ main (int argc, char *argv[]) {
     }
           
     /* read words from dictionary, then send them off */
-    while (fgets(word, MAX_WORD_LEN, dict) != NULL) { 
+    while (!interrupted && fgets(word, MAX_WORD_LEN, dict) != NULL) { 
       len = strlen(word) + 1;  /* plus one for null */
       
       if (len > MAX_WORD_LEN) 
        printf("error: word %s too large to send\n", word);
       else {
-       rtp_sendto(&snd, word, len);
+       rtp_sendto(snd, word, len);
         printf("sending word: %s", word);
       }
       usleep(USEC_RATE);
     }
-    
+
+    rtp_sender_deinit_srtp(snd);
+    rtp_sender_dealloc(snd);
+
+    fclose(dict);
   } else  { /* prog_type == receiver */
     rtp_receiver_t rcvr;
         
@@ -444,8 +481,13 @@ main (int argc, char *argv[]) {
       exit(1);
     }
 
-    rtp_receiver_init(&rcvr, sock, name, ssrc);
-    status = srtp_create(&rcvr.srtp_ctx, &policy);
+    rcvr = rtp_receiver_alloc();
+    if (rcvr == NULL) {
+      fprintf(stderr, "error: malloc() failed\n");
+      exit(1);
+    }
+    rtp_receiver_init(rcvr, sock, name, ssrc);
+    status = rtp_receiver_init_srtp(rcvr, &policy);
     if (status) {
       fprintf(stderr, 
              "error: srtp_create() failed with code %d\n", 
@@ -454,18 +496,36 @@ main (int argc, char *argv[]) {
     }
 
     /* get next word and loop */
-    while (1) {
+    while (!interrupted) {
       len = MAX_WORD_LEN;
-      if (rtp_recvfrom(&rcvr, word, &len) > -1)
-       printf("\tword: %s", word);
+      if (rtp_recvfrom(rcvr, word, &len) > -1)
+       printf("\tword: %s\n", word);
     }
       
+    rtp_receiver_deinit_srtp(rcvr);
+    rtp_receiver_dealloc(rcvr);
   } 
 
   if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
     leave_group(sock, mreq, argv[0]);
   }
 
+#ifdef RTPW_USE_WINSOCK2
+  ret = closesocket(sock);
+#else
+  ret = close(sock);
+#endif
+  if (ret < 0) {
+    fprintf(stderr, "%s: Failed to close socket", argv[0]);
+    perror("");
+  }
+
+  status = srtp_shutdown();
+  if (status) {
+    printf("error: srtp shutdown failed with error code %d\n", status);
+    exit(1);
+  }
+
 #ifdef RTPW_USE_WINSOCK2
   WSACleanup();
 #endif
@@ -505,3 +565,41 @@ leave_group(int sock, struct ip_mreq mreq, char *name) {
   }
 }
 
+void handle_signal(int signum)
+{
+  interrupted = 1;
+  /* Reset handler explicitly, in case we don't have sigaction() (and signal()
+     has BSD semantics), or we don't have SA_RESETHAND */
+  signal(signum, SIG_DFL);
+}
+
+int setup_signal_handler(char* name)
+{
+#if HAVE_SIGACTION
+  struct sigaction act;
+  memset(&act, 0, sizeof(act));
+
+  act.sa_handler = handle_signal;
+  sigemptyset(&act.sa_mask);
+#if defined(SA_RESETHAND)
+  act.sa_flags = SA_RESETHAND;
+#else
+  act.sa_flags = 0;
+#endif
+  /* Note that we're not setting SA_RESTART; we want recvfrom to return
+   * EINTR when we signal the receiver. */
+  
+  if (sigaction(SIGTERM, &act, NULL) != 0) {
+    fprintf(stderr, "%s: error setting up signal handler", name);
+    perror("");
+    return -1;
+  }
+#else
+  if (signal(SIGTERM, handle_signal) == SIG_ERR) {
+    fprintf(stderr, "%s: error setting up signal handler", name);
+    perror("");
+    return -1;
+  }
+#endif
+  return 0;
+}
diff --git a/libs/srtp/test/rtpw_test.sh b/libs/srtp/test/rtpw_test.sh
new file mode 100755 (executable)
index 0000000..b5d66ee
--- /dev/null
@@ -0,0 +1,80 @@
+#!/bin/sh
+# 
+# usage: rtpw_test <rtpw_commands>
+# 
+# tests the rtpw sender and receiver functions
+
+RTPW=./rtpw
+DEST_PORT=9999
+DURATION=3
+
+key=2b2edc5034f61a72345ca5986d7bfd0189aa6dc2ecab32fd9af74df6dfc6
+
+ARGS="-k $key -ae"
+
+# First, we run "killall" to get rid of all existing rtpw processes.
+# This step also enables this script to clean up after itself; if this
+# script is interrupted after the rtpw processes are started but before
+# they are killed, those processes will linger.  Re-running the script
+# will get rid of them.
+
+killall rtpw 2>/dev/null
+
+if test -x $RTPW; then
+
+echo  $0 ": starting rtpw receiver process... "
+
+$RTPW $* $ARGS -r 0.0.0.0 $DEST_PORT  &
+
+receiver_pid=$!
+
+echo $0 ": receiver PID = $receiver_pid"
+
+sleep 1 
+
+# verify that the background job is running
+ps | grep -q $receiver_pid
+retval=$?
+echo $retval
+if [ $retval != 0 ]; then
+    echo $0 ": error"
+    exit 254
+fi
+
+echo  $0 ": starting rtpw sender process..."
+
+$RTPW $* $ARGS -s 127.0.0.1 $DEST_PORT  &
+
+sender_pid=$!
+
+echo $0 ": sender PID = $sender_pid"
+
+# verify that the background job is running
+ps | grep -q $sender_pid
+retval=$?
+echo $retval
+if [ $retval != 0 ]; then
+    echo $0 ": error"
+    exit 255
+fi
+
+sleep $DURATION
+
+kill $receiver_pid
+kill $sender_pid
+
+wait $receiver_pid
+wait $sender_pid
+
+echo $0 ": done (test passed)"
+
+else 
+
+echo "error: can't find executable" $RTPW
+exit 1
+
+fi
+
+# EOF
+
+
index 363c5ed688f48412be5323c60d079da54046a178..a1b48661f0a5611b8d4e296ce81548ce8a054dc4 100644 (file)
@@ -8,7 +8,7 @@
  */
 /*
  *     
- * Copyright (c) 2001-2005, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -47,9 +47,9 @@
 #include <time.h>     /* for clock()           */
 #include <stdlib.h>   /* for malloc(), free()  */
 #include <stdio.h>    /* for print(), fflush() */
-#include <unistd.h>   /* for getopt()          */
+#include "getopt_s.h" /* for local getopt()    */
 
-#include "srtp.h"
+#include "srtp_priv.h"
 
 #ifdef HAVE_NETINET_IN_H
 # include <netinet/in.h>
 err_status_t
 srtp_validate(void);
 
+err_status_t
+srtp_validate_aes_256(void);
+
 err_status_t
 srtp_create_big_policy(srtp_policy_t **list);
 
+err_status_t
+srtp_dealloc_big_policy(srtp_policy_t *list);
+
 err_status_t
 srtp_test_remove_stream(void);
 
@@ -83,6 +89,9 @@ srtp_do_rejection_timing(const srtp_policy_t *policy);
 err_status_t
 srtp_test(const srtp_policy_t *policy);
 
+err_status_t
+srtcp_test(const srtp_policy_t *policy);
+
 err_status_t
 srtp_session_print_policy(srtp_t srtp);
 
@@ -135,7 +144,7 @@ debug_module_t mod_driver = {
 
 int
 main (int argc, char *argv[]) {
-  char q;
+  int q;
   unsigned do_timing_test    = 0;
   unsigned do_rejection_test = 0;
   unsigned do_codec_timing   = 0;
@@ -148,7 +157,9 @@ main (int argc, char *argv[]) {
    * structure srtp_hdr_t correctly
    */
   if (sizeof(srtp_hdr_t) != 12) {
-    printf("error: srtp_hdr_t has incorrect size\n");
+     printf("error: srtp_hdr_t has incorrect size"
+           "(size is %ld bytes, expected 12)\n", 
+           (long)sizeof(srtp_hdr_t));
     exit(1);
   }
 
@@ -169,7 +180,7 @@ main (int argc, char *argv[]) {
 
   /* process input arguments */
   while (1) {
-    q = getopt(argc, argv, "trcvld:");
+    q = getopt_s(argc, argv, "trcvld:");
     if (q == -1) 
       break;
     switch (q) {
@@ -189,9 +200,9 @@ main (int argc, char *argv[]) {
       do_list_mods = 1;
       break;
     case 'd':
-      status = crypto_kernel_set_debug_module(optarg, 1);
+      status = crypto_kernel_set_debug_module(optarg_s, 1);
       if (status) {
-        printf("error: set debug module (%s) failed\n", optarg);
+        printf("error: set debug module (%s) failed\n", optarg_s);
         exit(1);
       }  
       break;
@@ -216,7 +227,7 @@ main (int argc, char *argv[]) {
     const srtp_policy_t **policy = policy_array;
     srtp_policy_t *big_policy;
 
-    /* loop over policy array, testing srtp for each policy */
+    /* loop over policy array, testing srtp and srtcp for each policy */
     while (*policy != NULL) {
       printf("testing srtp_protect and srtp_unprotect\n");
       if (srtp_test(*policy) == err_status_ok)
@@ -225,6 +236,13 @@ main (int argc, char *argv[]) {
        printf("failed\n");
        exit(1);
       }
+      printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n");
+      if (srtcp_test(*policy) == err_status_ok)
+       printf("passed\n\n");
+      else {
+       printf("failed\n");
+       exit(1);
+      }
       policy++;
     }
 
@@ -241,6 +259,11 @@ main (int argc, char *argv[]) {
       printf("failed\n");
       exit(1);
     }
+    status = srtp_dealloc_big_policy(big_policy);
+    if (status) {
+      printf("unexpected failure with error code %d\n", status);
+      exit(1);
+    }
 
     /* run test on wildcard policy */
     printf("testing srtp_protect and srtp_unprotect on "
@@ -265,6 +288,19 @@ main (int argc, char *argv[]) {
        exit(1); 
     }
 
+    /*
+     * run validation test against the reference packets for
+     * AES-256
+     */
+    printf("testing srtp_protect and srtp_unprotect against "
+          "reference packets (AES-256)\n");
+    if (srtp_validate_aes_256() == err_status_ok) 
+      printf("passed\n\n");
+    else {
+      printf("failed\n");
+       exit(1); 
+    }
+
     /*
      * test the function srtp_remove_stream()
      */
@@ -309,6 +345,9 @@ main (int argc, char *argv[]) {
     policy.ssrc.type  = ssrc_specific;
     policy.ssrc.value = 0xdecafbad;
     policy.key  = test_key;
+    policy.ekt = NULL;
+    policy.window_size = 128;
+    policy.allow_repeat_tx = 0;
     policy.next = NULL;
 
     printf("mips estimate: %e\n", mips);
@@ -333,6 +372,18 @@ main (int argc, char *argv[]) {
     printf("G.729\t\t%d\t\t\t%e\n", 20, 
            (double) mips * (20 * 8) /
           srtp_bits_per_second(20, &policy) / .02 );
+    printf("Wideband\t%d\t\t\t%e\n", 320, 
+           (double) mips * (320 * 8) /
+          srtp_bits_per_second(320, &policy) / .01 );
+    printf("Wideband\t%d\t\t\t%e\n", 640, 
+           (double) mips * (640 * 8) /
+          srtp_bits_per_second(640, &policy) / .02 );
+  }
+
+  status = srtp_shutdown();
+  if (status) {
+    printf("error: srtp shutdown failed with error code %d\n", status);
+    exit(1);
   }
 
   return 0;  
@@ -361,7 +412,7 @@ srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc) {
   int bytes_in_hdr = 12;
 
   /* allocate memory for test packet */
-  hdr = malloc(pkt_octet_len + bytes_in_hdr
+  hdr = (srtp_hdr_t*) malloc(pkt_octet_len + bytes_in_hdr
               + SRTP_MAX_TRAILER_LEN + 4);
   if (!hdr)
     return NULL;
@@ -474,7 +525,6 @@ srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) {
   
   timer = clock();
   for (i=0; i < num_trials; i++) {
-    err_status_t status;
     len = msg_len_octets + 12;  /* add in rtp header length */
     
     /* srtp protect message */
@@ -485,12 +535,21 @@ srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) {
     }
 
     /* increment message number */
-    mesg->seq = htons(ntohs(mesg->seq) + 1);
-
+    {
+      /* hack sequence to avoid problems with macros for htons/ntohs on some systems */
+      short new_seq = ntohs(mesg->seq) + 1;
+      mesg->seq = htons(new_seq);
+    }
   }
   timer = clock() - timer;
 
   free(mesg);
+
+  status = srtp_dealloc(srtp);
+  if (status) {
+    printf("error: srtp_dealloc() failed with error code %d\n", status);
+    exit(1);
+  }
   
   return (double) (msg_len_octets) * 8 *
                   num_trials * CLOCKS_PER_SEC / timer;   
@@ -531,7 +590,13 @@ srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy) {
   timer = clock() - timer;
 
   free(mesg);
-  
+
+  status = srtp_dealloc(srtp);
+  if (status) {
+    printf("error: srtp_dealloc() failed with error code %d\n", status);
+    exit(1);
+  }
+
   return (double) num_trials * CLOCKS_PER_SEC / timer;   
 }
 
@@ -659,9 +724,12 @@ srtp_test(const srtp_policy_t *policy) {
    * we always copy the policy into the rcvr_policy, since otherwise
    * the compiler would fret about the constness of the policy
    */
-  rcvr_policy = malloc(sizeof(srtp_policy_t));
-  if (rcvr_policy == NULL)
+  rcvr_policy = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
+  if (rcvr_policy == NULL) {
+    free(hdr);
+    free(hdr2);
     return err_status_alloc_fail;
+  }
   memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
   if (policy->ssrc.type == ssrc_any_outbound) {
     rcvr_policy->ssrc.type = ssrc_any_inbound;       
@@ -683,6 +751,7 @@ srtp_test(const srtp_policy_t *policy) {
   if (status) {
     free(hdr);
     free(hdr2);
+    free(rcvr_policy);
     return status;
   }
 
@@ -703,6 +772,7 @@ srtp_test(const srtp_policy_t *policy) {
       printf("failed with error code %d\n", status);
       free(hdr); 
       free(hdr2);
+      free(rcvr_policy);
       return status;
     } else {
       printf("passed\n");
@@ -728,6 +798,7 @@ srtp_test(const srtp_policy_t *policy) {
       printf("failed\n");
       free(hdr); 
       free(hdr2);
+      free(rcvr_policy);
       return status;
     } else {
       printf("passed\n");
@@ -740,6 +811,210 @@ srtp_test(const srtp_policy_t *policy) {
 
   free(hdr);
   free(hdr2);
+  free(rcvr_policy);
+  return err_status_ok;
+}
+
+
+err_status_t
+srtcp_test(const srtp_policy_t *policy) {
+  int i;
+  srtp_t srtcp_sender;
+  srtp_t srtcp_rcvr;
+  err_status_t status = err_status_ok;
+  srtp_hdr_t *hdr, *hdr2;
+  uint8_t hdr_enc[64];
+  uint8_t *pkt_end;
+  int msg_len_octets, msg_len_enc;
+  int len;
+  int tag_length = policy->rtp.auth_tag_len; 
+  uint32_t ssrc;
+  srtp_policy_t *rcvr_policy;
+
+  err_check(srtp_create(&srtcp_sender, policy));
+
+  /* print out policy */
+  err_check(srtp_session_print_policy(srtcp_sender)); 
+
+  /*
+   * initialize data buffer, using the ssrc in the policy unless that
+   * value is a wildcard, in which case we'll just use an arbitrary
+   * one
+   */
+  if (policy->ssrc.type != ssrc_specific)
+    ssrc = 0xdecafbad;
+  else
+    ssrc = policy->ssrc.value;
+  msg_len_octets = 28;
+  hdr = srtp_create_test_packet(msg_len_octets, ssrc);
+
+  if (hdr == NULL)
+    return err_status_alloc_fail;
+  hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
+  if (hdr2 == NULL) {
+    free(hdr);
+    return err_status_alloc_fail;
+  }
+
+  /* set message length */
+  len = msg_len_octets;
+
+  debug_print(mod_driver, "before protection:\n%s",          
+             srtp_packet_to_string(hdr, len));
+
+#if PRINT_REFERENCE_PACKET
+  debug_print(mod_driver, "reference packet before protection:\n%s",         
+             octet_string_hex_string((uint8_t *)hdr, len));
+#endif
+  err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
+
+  debug_print(mod_driver, "after protection:\n%s",           
+             srtp_packet_to_string(hdr, len));
+#if PRINT_REFERENCE_PACKET
+  debug_print(mod_driver, "after protection:\n%s",           
+             octet_string_hex_string((uint8_t *)hdr, len));
+#endif
+
+  /* save protected message and length */
+  memcpy(hdr_enc, hdr, len);
+  msg_len_enc = len;
+
+  /* 
+   * check for overrun of the srtp_protect() function
+   *
+   * The packet is followed by a value of 0xfffff; if the value of the
+   * data following the packet is different, then we know that the
+   * protect function is overwriting the end of the packet.
+   */
+  pkt_end = (uint8_t *)hdr + sizeof(srtp_hdr_t) 
+    + msg_len_octets + tag_length;
+  for (i = 0; i < 4; i++)
+    if (pkt_end[i] != 0xff) {
+      fprintf(stdout, "overwrite in srtp_protect_rtcp() function "
+              "(expected %x, found %x in trailing octet %d)\n",
+              0xff, ((uint8_t *)hdr)[i], i);
+      free(hdr);
+      free(hdr2);
+      return err_status_algo_fail;
+    }  
+
+  /*
+   * if the policy includes confidentiality, check that ciphertext is
+   * different than plaintext
+   * 
+   * Note that this check will give false negatives, with some small
+   * probability, especially if the packets are short.  For that
+   * reason, we skip this check if the plaintext is less than four
+   * octets long.
+   */
+  if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
+    printf("testing that ciphertext is distinct from plaintext...");
+    status = err_status_algo_fail;
+    for (i=12; i < msg_len_octets+12; i++)
+      if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
+       status = err_status_ok;
+      }
+    if (status) {
+      printf("failed\n");
+      free(hdr);
+      free(hdr2);
+      return status;
+    }
+    printf("passed\n");
+  }
+  
+  /*
+   * if the policy uses a 'wildcard' ssrc, then we need to make a copy
+   * of the policy that changes the direction to inbound
+   *
+   * we always copy the policy into the rcvr_policy, since otherwise
+   * the compiler would fret about the constness of the policy
+   */
+  rcvr_policy = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
+  if (rcvr_policy == NULL)
+    return err_status_alloc_fail;
+  memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
+  if (policy->ssrc.type == ssrc_any_outbound) {
+    rcvr_policy->ssrc.type = ssrc_any_inbound;       
+  } 
+
+  err_check(srtp_create(&srtcp_rcvr, rcvr_policy));
+   
+  err_check(srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len));
+
+  debug_print(mod_driver, "after unprotection:\n%s",         
+             srtp_packet_to_string(hdr, len));
+
+  /* verify that the unprotected packet matches the origial one */
+  for (i=0; i < msg_len_octets; i++)
+    if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
+      fprintf(stdout, "mismatch at octet %d\n", i);
+      status = err_status_algo_fail;
+    }
+  if (status) {
+    free(hdr);
+    free(hdr2);
+    free(rcvr_policy);
+    return status;
+  }
+
+  /* 
+   * if the policy includes authentication, then test for false positives
+   */  
+  if (policy->rtp.sec_serv & sec_serv_auth) {
+    char *data = ((char *)hdr) + 12;
+    
+    printf("testing for false positives in replay check...");
+
+    /* set message length */
+    len = msg_len_enc;
+
+    /* unprotect a second time - should fail with a replay error */
+    status = srtp_unprotect_rtcp(srtcp_rcvr, hdr_enc, &len);
+    if (status != err_status_replay_fail) {
+      printf("failed with error code %d\n", status);
+      free(hdr); 
+      free(hdr2);
+      free(rcvr_policy);
+      return status;
+    } else {
+      printf("passed\n");
+    }
+
+    printf("testing for false positives in auth check...");
+
+    /* increment sequence number in header */
+    hdr->seq++; 
+
+    /* set message length */
+    len = msg_len_octets;
+
+    /* apply protection */
+    err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
+    
+    /* flip bits in packet */
+    data[0] ^= 0xff;
+
+    /* unprotect, and check for authentication failure */
+    status = srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len);
+    if (status != err_status_auth_fail) {
+      printf("failed\n");
+      free(hdr); 
+      free(hdr2);
+      free(rcvr_policy);
+      return status;
+    } else {
+      printf("passed\n");
+    }
+            
+  }
+
+  err_check(srtp_dealloc(srtcp_sender));
+  err_check(srtp_dealloc(srtcp_rcvr));
+
+  free(hdr);
+  free(hdr2);
+  free(rcvr_policy);
   return err_status_ok;
 }
 
@@ -772,14 +1047,18 @@ srtp_session_print_policy(srtp_t srtp) {
           "# rtp services:  %s\r\n" 
            "# rtcp cipher:   %s\r\n"
           "# rtcp auth:     %s\r\n"
-          "# rtcp services: %s\r\n",
+          "# rtcp services: %s\r\n"
+          "# window size:   %lu\r\n"
+          "# tx rtx allowed:%s\r\n",
           direction[stream->direction],
           stream->rtp_cipher->type->description,
           stream->rtp_auth->type->description,
           serv_descr[stream->rtp_services],
           stream->rtcp_cipher->type->description,
           stream->rtcp_auth->type->description,
-          serv_descr[stream->rtcp_services]);
+          serv_descr[stream->rtcp_services],
+          rdbx_get_window_size(&stream->rtp_rdbx),
+          stream->allow_repeat_tx ? "true" : "false");
   }
 
   /* loop over streams in session, printing the policy of each */
@@ -794,14 +1073,18 @@ srtp_session_print_policy(srtp_t srtp) {
           "# rtp services:  %s\r\n" 
            "# rtcp cipher:   %s\r\n"
           "# rtcp auth:     %s\r\n"
-          "# rtcp services: %s\r\n",
+          "# rtcp services: %s\r\n"
+          "# window size:   %lu\r\n"
+          "# tx rtx allowed:%s\r\n",
           stream->ssrc,
           stream->rtp_cipher->type->description,
           stream->rtp_auth->type->description,
           serv_descr[stream->rtp_services],
           stream->rtcp_cipher->type->description,
           stream->rtcp_auth->type->description,
-          serv_descr[stream->rtcp_services]);
+          serv_descr[stream->rtcp_services],
+          rdbx_get_window_size(&stream->rtp_rdbx),
+          stream->allow_repeat_tx ? "true" : "false");
 
     /* advance to next stream in the list */
     stream = stream->next;
@@ -891,7 +1174,7 @@ srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) {
 double
 mips_estimate(int num_trials, int *ignore) {
   clock_t t;
-  int i, sum;
+  volatile int i, sum;
 
   sum = 0;
   t = clock();
@@ -915,12 +1198,6 @@ mips_estimate(int num_trials, int *ignore) {
 
 err_status_t
 srtp_validate() {
-  unsigned char test_key[30] = {
-    0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
-    0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
-    0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
-    0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
-  };
   uint8_t srtp_plaintext_ref[28] = {
     0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
     0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
@@ -955,6 +1232,117 @@ srtp_validate() {
   policy.ssrc.type  = ssrc_specific;
   policy.ssrc.value = 0xcafebabe;
   policy.key  = test_key;
+  policy.ekt = NULL;
+  policy.window_size = 128;
+  policy.allow_repeat_tx = 0;
+  policy.next = NULL;
+
+  status = srtp_create(&srtp_snd, &policy);
+  if (status)
+    return status;
+  /* 
+   * protect plaintext, then compare with ciphertext 
+   */
+  len = 28;
+  status = srtp_protect(srtp_snd, srtp_plaintext, &len);
+  if (status || (len != 38))
+    return err_status_fail;
+
+  debug_print(mod_driver, "ciphertext:\n  %s",               
+             octet_string_hex_string(srtp_plaintext, len));
+  debug_print(mod_driver, "ciphertext reference:\n  %s",             
+             octet_string_hex_string(srtp_ciphertext, len));
+
+  if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
+    return err_status_fail;
+  
+  /*
+   * create a receiver session context comparable to the one created
+   * above - we need to do this so that the replay checking doesn't
+   * complain
+   */
+  status = srtp_create(&srtp_recv, &policy);
+  if (status)
+    return status;
+
+  /*
+   * unprotect ciphertext, then compare with plaintext 
+   */
+  status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
+  if (status || (len != 28))
+    return status;
+  
+  if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
+    return err_status_fail;
+
+  status = srtp_dealloc(srtp_snd);
+  if (status)
+    return status;
+
+  status = srtp_dealloc(srtp_recv);
+  if (status)
+    return status;
+
+  return err_status_ok;
+}
+
+
+/*
+ * srtp_validate_aes_256() verifies the correctness of libsrtp by comparing
+ * some computed packets against some pre-computed reference values.
+ * These packets were made with the AES-CM-256/HMAC-SHA-1-80 policy.
+ */
+
+
+err_status_t
+srtp_validate_aes_256() {
+  unsigned char aes_256_test_key[46] = {
+    0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76,
+    0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29,
+    0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1,
+    0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6,
+
+    0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9,
+    0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2
+  };
+  uint8_t srtp_plaintext_ref[28] = {
+    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
+    0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
+    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
+    0xab, 0xab, 0xab, 0xab
+  };
+  uint8_t srtp_plaintext[38] = {
+    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
+    0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
+    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
+    0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  };
+  uint8_t srtp_ciphertext[38] = {
+    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
+    0xca, 0xfe, 0xba, 0xbe, 0xf1, 0xd9, 0xde, 0x17, 
+    0xff, 0x25, 0x1f, 0xf1, 0xaa, 0x00, 0x77, 0x74, 
+    0xb0, 0xb4, 0xb4, 0x0d, 0xa0, 0x8d, 0x9d, 0x9a, 
+    0x5b, 0x3a, 0x55, 0xd8, 0x87, 0x3b
+  };
+  srtp_t srtp_snd, srtp_recv;
+  err_status_t status;
+  int len;
+  srtp_policy_t policy;
+  
+  /*
+   * create a session with a single stream using the default srtp
+   * policy and with the SSRC value 0xcafebabe
+   */
+  crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
+  crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtcp);
+  policy.ssrc.type  = ssrc_specific;
+  policy.ssrc.value = 0xcafebabe;
+  policy.key  = aes_256_test_key;
+  policy.ekt = NULL;
+  policy.window_size = 128;
+  policy.allow_repeat_tx = 0;
   policy.next = NULL;
 
   status = srtp_create(&srtp_snd, &policy);
@@ -996,6 +1384,14 @@ srtp_validate() {
   if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
     return err_status_fail;
 
+  status = srtp_dealloc(srtp_snd);
+  if (status)
+    return status;
+
+  status = srtp_dealloc(srtp_recv);
+  if (status)
+    return status;
+
   return err_status_ok;
 }
 
@@ -1017,7 +1413,7 @@ srtp_create_big_policy(srtp_policy_t **list) {
    */
   tmp = NULL;
   while (policy_array[i] != NULL) {
-    p = malloc(sizeof(srtp_policy_t));
+    p  = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
     if (p == NULL)
       return err_status_bad_param;
     memcpy(p, policy_array[i], sizeof(srtp_policy_t));
@@ -1032,10 +1428,23 @@ srtp_create_big_policy(srtp_policy_t **list) {
   return err_status_ok;
 }
 
+err_status_t
+srtp_dealloc_big_policy(srtp_policy_t *list) {
+  srtp_policy_t *p, *next;
+
+  for (p = list; p != NULL; p = next) {
+    next = p->next;
+    free(p);
+  }
+
+  return err_status_ok;
+}
+
+
 err_status_t
 srtp_test_remove_stream() { 
   err_status_t status;
-  srtp_policy_t *policy_list;
+  srtp_policy_t *policy_list, policy;
   srtp_t session;
   srtp_stream_t stream;
   /* 
@@ -1076,6 +1485,41 @@ srtp_test_remove_stream() {
   if (stream == NULL)
     return err_status_fail;  
 
+  status = srtp_dealloc(session);
+  if (status != err_status_ok)
+    return status;
+
+  status = srtp_dealloc_big_policy(policy_list);
+  if (status != err_status_ok)
+    return status;
+
+  /* Now test adding and removing a single stream */
+  crypto_policy_set_rtp_default(&policy.rtp);
+  crypto_policy_set_rtcp_default(&policy.rtcp);
+  policy.ssrc.type  = ssrc_specific;
+  policy.ssrc.value = 0xcafebabe;
+  policy.key  = test_key;
+  policy.ekt = NULL;
+  policy.window_size = 128;
+  policy.allow_repeat_tx = 0;
+  policy.next = NULL;
+
+  status = srtp_create(&session, NULL);
+  if (status != err_status_ok)
+    return status;
+  
+  status = srtp_add_stream(session, &policy);
+  if (status != err_status_ok)
+    return status;
+
+  status = srtp_remove_stream(session, htonl(0xcafebabe));
+  if (status != err_status_ok)
+    return status;
+
+  status = srtp_dealloc(session);
+  if (status != err_status_ok)
+    return status;
+
   return err_status_ok;  
 }
 
@@ -1110,6 +1554,9 @@ const srtp_policy_t default_policy = {
     sec_serv_conf_and_auth  /* security services flag      */
   },
   test_key,
+  NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
+  0,           /* retransmission not allowed */
   NULL
 };
 
@@ -1132,6 +1579,9 @@ const srtp_policy_t aes_tmmh_policy = {
     sec_serv_conf_and_auth  /* security services flag      */
   },
   test_key,
+  NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
+  0,           /* retransmission not allowed */
   NULL
 };
 
@@ -1154,6 +1604,9 @@ const srtp_policy_t tmmh_only_policy = {
     sec_serv_auth           /* security services flag      */
   },
   test_key,
+  NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
+  0,           /* retransmission not allowed */
   NULL
 };
 
@@ -1176,6 +1629,9 @@ const srtp_policy_t aes_only_policy = {
     sec_serv_conf           /* security services flag      */
   },
   test_key,
+  NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
+  0,           /* retransmission not allowed */
   NULL
 };
 
@@ -1198,6 +1654,9 @@ const srtp_policy_t hmac_only_policy = {
     sec_serv_auth           /* security services flag      */
   },
   test_key,
+  NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
+  0,           /* retransmission not allowed */
   NULL
 };
 
@@ -1220,6 +1679,83 @@ const srtp_policy_t null_policy = {
     sec_serv_none           /* security services flag      */  
   },
   test_key,
+  NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
+  0,           /* retransmission not allowed */
+  NULL
+};
+
+unsigned char test_256_key[46] = {
+       0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76,
+       0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29,
+       0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1,
+       0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6,
+
+       0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9,
+       0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2
+};
+
+const srtp_policy_t aes_256_hmac_policy = {
+  { ssrc_any_outbound, 0 },  /* SSRC                           */
+  {                      /* SRTP policy                    */                  
+    AES_ICM,                /* cipher type                 */
+    46,                     /* cipher key length in octets */
+    HMAC_SHA1,              /* authentication func type    */
+    20,                     /* auth key length in octets   */
+    10,                     /* auth tag length in octets   */
+    sec_serv_conf_and_auth  /* security services flag      */
+  },
+  {                      /* SRTCP policy                   */
+    AES_ICM,                /* cipher type                 */
+    46,                     /* cipher key length in octets */
+    HMAC_SHA1,              /* authentication func type    */
+    20,                     /* auth key length in octets   */
+    10,                     /* auth tag length in octets   */
+    sec_serv_conf_and_auth  /* security services flag      */
+  },
+  test_256_key,
+  NULL,        /* indicates that EKT is not in use */
+  128,         /* replay window size */
+  0,           /* retransmission not allowed */
+  NULL
+};
+
+uint8_t ekt_test_key[16] = {
+  0x77, 0x26, 0x9d, 0xac, 0x16, 0xa3, 0x28, 0xca, 
+  0x8e, 0xc9, 0x68, 0x4b, 0xcc, 0xc4, 0xd2, 0x1b
+};
+
+#include "ekt.h"
+
+ekt_policy_ctx_t ekt_test_policy = {
+  0xa5a5,                   /* SPI */
+  EKT_CIPHER_AES_128_ECB,
+  ekt_test_key,
+  NULL
+};
+
+const srtp_policy_t hmac_only_with_ekt_policy = {
+  { ssrc_any_outbound, 0 },     /* SSRC                        */
+  {
+    NULL_CIPHER,            /* cipher type                 */
+    0,                      /* cipher key length in octets */
+    HMAC_SHA1,              /* authentication func type    */
+    20,                     /* auth key length in octets   */
+    4,                      /* auth tag length in octets   */
+    sec_serv_auth           /* security services flag      */
+  },  
+  {
+    NULL_CIPHER,            /* cipher type                 */
+    0,                      /* cipher key length in octets */
+    HMAC_SHA1,              /* authentication func type    */
+    20,                     /* auth key length in octets   */
+    4,                      /* auth tag length in octets   */
+    sec_serv_auth           /* security services flag      */
+  },
+  test_key,
+  &ekt_test_policy,        /* indicates that EKT is not in use */
+  128,                     /* replay window size */
+  0,                       /* retransmission not allowed */
   NULL
 };
 
@@ -1248,6 +1784,8 @@ policy_array[] = {
 #endif
   &default_policy,
   &null_policy,
+  &aes_256_hmac_policy,
+  &hmac_only_with_ekt_policy,
   NULL
 };
 
@@ -1270,5 +1808,8 @@ const srtp_policy_t wildcard_policy = {
     sec_serv_conf_and_auth  /* security services flag      */
   },
   test_key,
+  NULL,
+  128,                   /* replay window size */
+  0,                     /* retransmission not allowed */
   NULL
 };
index d116f82925c0c05a1199f8e4c7b29ca95b21f977..595b647f3ded657f5e25e17dd153212ef6925b85 100755 (executable)
@@ -6,7 +6,7 @@
 
 a=`find . -name "*.[ch]"`
 for x in $a; do 
-    sed 's/(c) 2001-2004/(c) 2001-2005/' $x > $x.tmp; 
+    sed 's/(c) 2001-2005/(c) 2001-2006/' $x > $x.tmp; 
     mv $x.tmp $x; 
 done
 
index 54753db643bb8022edea8e1b6c565fdde548b055..449ce2daabe6d3f87f8d4b570a51a4731afa80f6 100644 (file)
@@ -47,6 +47,7 @@
 #undef inline
 #include <datatypes.h>
 #include <srtp.h>
+#include <srtp_priv.h>
 #include <switch_version.h>
 
 #define READ_INC(rtp_session) switch_mutex_lock(rtp_session->read_mutex); rtp_session->reading++