diff --git a/libs/srtp/.update b/libs/srtp/.update index 0269e52854..e69de29bb2 100644 --- a/libs/srtp/.update +++ b/libs/srtp/.update @@ -1 +0,0 @@ -Fri Mar 16 17:20:27 EDT 2007 diff --git a/libs/srtp/LICENSE b/libs/srtp/LICENSE index d1ff4e8559..dd43240cae 100644 --- a/libs/srtp/LICENSE +++ b/libs/srtp/LICENSE @@ -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 diff --git a/libs/srtp/README b/libs/srtp/README index 02dc1f8eb5..08fafaedbc 100644 --- a/libs/srtp/README +++ b/libs/srtp/README @@ -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: diff --git a/libs/srtp/VERSION b/libs/srtp/VERSION index 9df886c42a..1c99cf0e80 100644 --- a/libs/srtp/VERSION +++ b/libs/srtp/VERSION @@ -1 +1 @@ -1.4.2 +1.4.4 diff --git a/libs/srtp/config.hw b/libs/srtp/config.hw index 32f5ed9196..39d4e07364 100644 --- a/libs/srtp/config.hw +++ b/libs/srtp/config.hw @@ -1,195 +1,196 @@ -/* crypto/include/config.h. Generated by configure. */ -/* config_in.h. Generated from configure.in by autoheader. */ - -/* 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 header file. */ -/* #undef HAVE_ARPA_INET_H */ - -/* Define to 1 if you have the 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 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 header file. */ -/* #undef HAVE_MACHINE_TYPES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the 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 header file. */ -/* #undef HAVE_STDINT_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYSLOG_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_INT_TYPES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the 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 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 header file. */ -#define HAVE_WINDOWS_H 1 - -/* Define to 1 if you have the 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 to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#define inline __inline -#endif - -/* Define to `unsigned' if 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 +/* 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 header file. */ +/* #undef HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the 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 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 header file. */ +/* #undef HAVE_MACHINE_TYPES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the 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 header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYSLOG_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_INT_TYPES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the 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 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 header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the 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 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 diff --git a/libs/srtp/configure.in b/libs/srtp/configure.in index 2495a55f95..dc471c5b14 100644 --- a/libs/srtp/configure.in +++ b/libs/srtp/configure.in @@ -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 index 0000000000..f3c7a7c5da --- /dev/null +++ b/libs/srtp/crypto/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/libs/srtp/crypto/Makefile.in b/libs/srtp/crypto/Makefile.in index c14dba50c5..9d52104210 100644 --- a/libs/srtp/crypto/Makefile.in +++ b/libs/srtp/crypto/Makefile.in @@ -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 diff --git a/libs/srtp/crypto/ae_xfm/xfm.c b/libs/srtp/crypto/ae_xfm/xfm.c index 05ff710f90..7aa338830f 100644 --- a/libs/srtp/crypto/ae_xfm/xfm.c +++ b/libs/srtp/crypto/ae_xfm/xfm.c @@ -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; } diff --git a/libs/srtp/crypto/cipher/aes.c b/libs/srtp/crypto/cipher/aes.c index c736e17102..a17b9e4993 100644 --- a/libs/srtp/crypto/cipher/aes.c +++ b/libs/srtp/crypto/cipher/aes.c @@ -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; - aes_expand_encryption_key(key, expanded_key); + /* 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; + + 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); + v128_xor_eq(plaintext, &exp_key->round[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); + /* 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); + v128_xor_eq(plaintext, &exp_key->round[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); + /* 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]); + } } diff --git a/libs/srtp/crypto/cipher/aes_cbc.c b/libs/srtp/crypto/cipher/aes_cbc.c index fbfce629e6..ed33f5b01c 100644 --- a/libs/srtp/crypto/cipher/aes_cbc.c +++ b/libs/srtp/crypto/cipher/aes_cbc.c @@ -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 }; diff --git a/libs/srtp/crypto/cipher/aes_icm.c b/libs/srtp/crypto/cipher/aes_icm.c index 152e4c93b7..1f9bcbd97c 100644 --- a/libs/srtp/crypto/cipher/aes_icm.c +++ b/libs/srtp/crypto/cipher/aes_icm.c @@ -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); + 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) + /* + * 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 }; diff --git a/libs/srtp/crypto/cipher/cipher.c b/libs/srtp/crypto/cipher/cipher.c index 761918bf5b..27da651c72 100644 --- a/libs/srtp/crypto/cipher/cipher.c +++ b/libs/srtp/crypto/cipher/cipher.c @@ -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 */ diff --git a/libs/srtp/crypto/cipher/null_cipher.c b/libs/srtp/crypto/cipher/null_cipher.c index 988f6a56af..724f4df3a8 100644 --- a/libs/srtp/crypto/cipher/null_cipher.c +++ b/libs/srtp/crypto/cipher/null_cipher.c @@ -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 @@ -48,10 +48,6 @@ #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 }; diff --git a/libs/srtp/crypto/hash/auth.c b/libs/srtp/crypto/hash/auth.c index 2773c16cc3..aaf0269c71 100644 --- a/libs/srtp/crypto/hash/auth.c +++ b/libs/srtp/crypto/hash/auth.c @@ -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); +} + diff --git a/libs/srtp/crypto/hash/hmac.c b/libs/srtp/crypto/hash/hmac.c index a786523c50..4f389fe18e 100644 --- a/libs/srtp/crypto/hash/hmac.c +++ b/libs/srtp/crypto/hash/hmac.c @@ -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 }; diff --git a/libs/srtp/crypto/hash/null_auth.c b/libs/srtp/crypto/hash/null_auth.c index 1d8c556310..103444bc53 100644 --- a/libs/srtp/crypto/hash/null_auth.c +++ b/libs/srtp/crypto/hash/null_auth.c @@ -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 @@ -48,10 +48,6 @@ #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 }; diff --git a/libs/srtp/crypto/hash/sha1.c b/libs/srtp/crypto/hash/sha1.c index d4eba3cc26..b9a8d10509 100644 --- a/libs/srtp/crypto/hash/sha1.c +++ b/libs/srtp/crypto/hash/sha1.c @@ -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 index 0000000000..0e56cf2f8c --- /dev/null +++ b/libs/srtp/crypto/include/.cvsignore @@ -0,0 +1 @@ +config.h diff --git a/libs/srtp/crypto/include/aes.h b/libs/srtp/crypto/include/aes.h index e59fdadb77..288133743f 100644 --- a/libs/srtp/crypto/include/aes.h +++ b/libs/srtp/crypto/include/aes.h @@ -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 @@ -50,24 +50,30 @@ #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; + +err_status_t +aes_expand_encryption_key(const uint8_t *key, + int key_len, + 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_expand_encryption_key(const v128_t *key, - aes_expanded_key_t expanded_key); +aes_encrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key); void -aes_expand_decryption_key(const v128_t *key, - aes_expanded_key_t expanded_key); - -void -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 /* diff --git a/libs/srtp/crypto/include/aes_cbc.h b/libs/srtp/crypto/include/aes_cbc.h index 9fb6682bd0..bc4e41a4c1 100644 --- a/libs/srtp/crypto/include/aes_cbc.h +++ b/libs/srtp/crypto/include/aes_cbc.h @@ -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); diff --git a/libs/srtp/crypto/include/aes_icm.h b/libs/srtp/crypto/include/aes_icm.h index 67f2359315..dac0cdccc6 100644 --- a/libs/srtp/crypto/include/aes_icm.h +++ b/libs/srtp/crypto/include/aes_icm.h @@ -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); diff --git a/libs/srtp/crypto/include/alloc.h b/libs/srtp/crypto/include/alloc.h index 5eb508c719..5980eed6c1 100644 --- a/libs/srtp/crypto/include/alloc.h +++ b/libs/srtp/crypto/include/alloc.h @@ -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/include/auth.h b/libs/srtp/crypto/include/auth.h index 6e32480daa..5b5e4b21d4 100644 --- a/libs/srtp/crypto/include/auth.h +++ b/libs/srtp/crypto/include/auth.h @@ -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 diff --git a/libs/srtp/crypto/include/cipher.h b/libs/srtp/crypto/include/cipher.h index 5c37c38413..eff6dd154b 100644 --- a/libs/srtp/crypto/include/cipher.h +++ b/libs/srtp/crypto/include/cipher.h @@ -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 diff --git a/libs/srtp/crypto/include/crypto.h b/libs/srtp/crypto/include/crypto.h index dc52821e43..0e9667da57 100644 --- a/libs/srtp/crypto/include/crypto.h +++ b/libs/srtp/crypto/include/crypto.h @@ -10,7 +10,33 @@ #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 */ diff --git a/libs/srtp/crypto/include/crypto_kernel.h b/libs/srtp/crypto/include/crypto_kernel.h index 029f1c885a..1acf4978d0 100644 --- a/libs/srtp/crypto/include/crypto_kernel.h +++ b/libs/srtp/crypto/include/crypto_kernel.h @@ -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); diff --git a/libs/srtp/crypto/include/crypto_math.h b/libs/srtp/crypto/include/crypto_math.h index be6558f638..52f083721d 100644 --- a/libs/srtp/crypto/include/crypto_math.h +++ b/libs/srtp/crypto/include/crypto_math.h @@ -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 */ diff --git a/libs/srtp/crypto/include/crypto_types.h b/libs/srtp/crypto/include/crypto_types.h index e20c7715b0..35317108c3 100644 --- a/libs/srtp/crypto/include/crypto_types.h +++ b/libs/srtp/crypto/include/crypto_types.h @@ -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 @@ -97,12 +97,19 @@ #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_128_ICM 1 +#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 AES_ICM /** * @brief SEAL 3.0 @@ -113,19 +120,26 @@ #define SEAL 2 /** - * @brief AES-128 Integer Counter Mode (AES ICM) + * @brief AES 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 CBC is the AES Cipher Block Chaining mode. + * This cipher uses a 16-, 24-, or 32-octet key. */ -#define AES_128_CBC 3 +#define AES_CBC 3 + +/** + * @brief AES-128 Cipher Block Chaining mode (AES CBC) + * + * AES-128 CBC is a deprecated alternate name for AES CBC. + */ +#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 /** * @} diff --git a/libs/srtp/crypto/include/cryptoalg.h b/libs/srtp/crypto/include/cryptoalg.h index 9024a71117..d9f0441e0e 100644 --- a/libs/srtp/crypto/include/cryptoalg.h +++ b/libs/srtp/crypto/include/cryptoalg.h @@ -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/include/datatypes.h b/libs/srtp/crypto/include/datatypes.h index 17b531beb6..e16d895bb5 100644 --- a/libs/srtp/crypto/include/datatypes.h +++ b/libs/srtp/crypto/include/datatypes.h @@ -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 # elif defined HAVE_WINSOCK2_H # include # 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 */ diff --git a/libs/srtp/crypto/include/err.h b/libs/srtp/crypto/include/err.h index 37d3cb93e8..1a6e170182 100644 --- a/libs/srtp/crypto/include/err.h +++ b/libs/srtp/crypto/include/err.h @@ -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; /** diff --git a/libs/srtp/crypto/include/gf2_8.h b/libs/srtp/crypto/include/gf2_8.h index ea40a4412b..098d37c9e2 100644 --- a/libs/srtp/crypto/include/gf2_8.h +++ b/libs/srtp/crypto/include/gf2_8.h @@ -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 diff --git a/libs/srtp/crypto/include/hmac.h b/libs/srtp/crypto/include/hmac.h index 6abfdf8d51..262c0e2d6e 100644 --- a/libs/srtp/crypto/include/hmac.h +++ b/libs/srtp/crypto/include/hmac.h @@ -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 diff --git a/libs/srtp/crypto/include/integers.h b/libs/srtp/crypto/include/integers.h index 8b55720a91..7010efdde3 100644 --- a/libs/srtp/crypto/include/integers.h +++ b/libs/srtp/crypto/include/integers.h @@ -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) \ { \ diff --git a/libs/srtp/crypto/include/key.h b/libs/srtp/crypto/include/key.h index 6e89697a0d..e7e07448e7 100644 --- a/libs/srtp/crypto/include/key.h +++ b/libs/srtp/crypto/include/key.h @@ -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/include/null_auth.h b/libs/srtp/crypto/include/null_auth.h index cebb86b1a5..44f9a4a2ba 100644 --- a/libs/srtp/crypto/include/null_auth.h +++ b/libs/srtp/crypto/include/null_auth.h @@ -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/include/null_cipher.h b/libs/srtp/crypto/include/null_cipher.h index 7f348be5ff..39da59a812 100644 --- a/libs/srtp/crypto/include/null_cipher.h +++ b/libs/srtp/crypto/include/null_cipher.h @@ -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, diff --git a/libs/srtp/crypto/include/rand_source.h b/libs/srtp/crypto/include/rand_source.h index 19a3f94b1b..b4c21103ac 100644 --- a/libs/srtp/crypto/include/rand_source.h +++ b/libs/srtp/crypto/include/rand_source.h @@ -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/include/rdb.h b/libs/srtp/crypto/include/rdb.h index 5a26c5e303..2ccb1448e2 100644 --- a/libs/srtp/crypto/include/rdb.h +++ b/libs/srtp/crypto/include/rdb.h @@ -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 diff --git a/libs/srtp/crypto/include/rdbx.h b/libs/srtp/crypto/include/rdbx.h index ce9ecf6f47..146fb42f25 100644 --- a/libs/srtp/crypto/include/rdbx.h +++ b/libs/srtp/crypto/include/rdbx.h @@ -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) */ diff --git a/libs/srtp/crypto/include/sha1.h b/libs/srtp/crypto/include/sha1.h index 1d61c5832c..e3af4d4b4b 100644 --- a/libs/srtp/crypto/include/sha1.h +++ b/libs/srtp/crypto/include/sha1.h @@ -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 diff --git a/libs/srtp/crypto/include/stat.h b/libs/srtp/crypto/include/stat.h index 1fe4f2f481..e28b1314a8 100644 --- a/libs/srtp/crypto/include/stat.h +++ b/libs/srtp/crypto/include/stat.h @@ -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 diff --git a/libs/srtp/crypto/kernel/alloc.c b/libs/srtp/crypto/kernel/alloc.c index 9ff5898f06..5dd0947490 100644 --- a/libs/srtp/crypto/kernel/alloc.c +++ b/libs/srtp/crypto/kernel/alloc.c @@ -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/kernel/crypto_kernel.c b/libs/srtp/crypto/kernel/crypto_kernel.c index 23131c9c54..0e969bc860 100644 --- a/libs/srtp/crypto/kernel/crypto_kernel.c +++ b/libs/srtp/crypto/kernel/crypto_kernel.c @@ -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) { diff --git a/libs/srtp/crypto/kernel/err.c b/libs/srtp/crypto/kernel/err.c index f68a629975..4a3a8589e9 100644 --- a/libs/srtp/crypto/kernel/err.c +++ b/libs/srtp/crypto/kernel/err.c @@ -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 @@ -42,10 +42,6 @@ * */ -#ifdef _MSC_VER -#pragma warning(disable:4100) -#endif - #include "err.h" #ifdef ERR_REPORTING_SYSLOG diff --git a/libs/srtp/crypto/kernel/key.c b/libs/srtp/crypto/kernel/key.c index 8c86b89f26..9f63b22c21 100644 --- a/libs/srtp/crypto/kernel/key.c +++ b/libs/srtp/crypto/kernel/key.c @@ -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/math/datatypes.c b/libs/srtp/crypto/math/datatypes.c index 58c7502176..21c0dc0782 100644 --- a/libs/srtp/crypto/math/datatypes.c +++ b/libs/srtp/crypto/math/datatypes.c @@ -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) diff --git a/libs/srtp/crypto/math/gf2_8.c b/libs/srtp/crypto/math/gf2_8.c index 7bd5a0dea2..f1f45bdd56 100644 --- a/libs/srtp/crypto/math/gf2_8.c +++ b/libs/srtp/crypto/math/gf2_8.c @@ -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; diff --git a/libs/srtp/crypto/math/math.c b/libs/srtp/crypto/math/math.c index f3aaf65014..9e3e78ed12 100644 --- a/libs/srtp/crypto/math/math.c +++ b/libs/srtp/crypto/math/math.c @@ -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 /* 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 - -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! */ diff --git a/libs/srtp/crypto/math/stat.c b/libs/srtp/crypto/math/stat.c index 6f94a0c6e6..5e46c209e3 100644 --- a/libs/srtp/crypto/math/stat.c +++ b/libs/srtp/crypto/math/stat.c @@ -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 */ diff --git a/libs/srtp/crypto/replay/rdb.c b/libs/srtp/crypto/replay/rdb.c index e2e645be1b..5d204ec0e1 100644 --- a/libs/srtp/crypto/replay/rdb.c +++ b/libs/srtp/crypto/replay/rdb.c @@ -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; } diff --git a/libs/srtp/crypto/replay/rdbx.c b/libs/srtp/crypto/replay/rdbx.c index dcdb138510..54671cab0c 100644 --- a/libs/srtp/crypto/replay/rdbx.c +++ b/libs/srtp/crypto/replay/rdbx.c @@ -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 @@ -45,18 +45,17 @@ #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 */ diff --git a/libs/srtp/crypto/replay/ut_sim.c b/libs/srtp/crypto/replay/ut_sim.c index 15258c76ab..43c411e46b 100644 --- a/libs/srtp/crypto/replay/ut_sim.c +++ b/libs/srtp/crypto/replay/ut_sim.c @@ -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) { diff --git a/libs/srtp/crypto/rng/ctr_prng.c b/libs/srtp/crypto/rng/ctr_prng.c index 91effb96ab..41d46a8f55 100644 --- a/libs/srtp/crypto/rng/ctr_prng.c +++ b/libs/srtp/crypto/rng/ctr_prng.c @@ -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; diff --git a/libs/srtp/crypto/rng/prng.c b/libs/srtp/crypto/rng/prng.c index 0cd027eece..62b5e11d4e 100644 --- a/libs/srtp/crypto/rng/prng.c +++ b/libs/srtp/crypto/rng/prng.c @@ -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,11 +47,11 @@ /* 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); diff --git a/libs/srtp/crypto/rng/rand_source.c b/libs/srtp/crypto/rng/rand_source.c index aee16c03e8..1eb6fbb09c 100644 --- a/libs/srtp/crypto/rng/rand_source.c +++ b/libs/srtp/crypto/rng/rand_source.c @@ -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,18 +43,36 @@ */ #include "config.h" -#include "rand_source.h" #ifdef DEV_URANDOM # include /* for open() */ # include /* for close() */ +#elif defined(HAVE_RAND_S) +# define _CRT_RAND_S +# include #else # include #endif -/* global dev_rand_fdes is file descriptor for /dev/random */ +#include "rand_source.h" -static int dev_random_fdes = -1; + +/* + * 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. + */ + +#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 index 0000000000..888bf597e1 --- /dev/null +++ b/libs/srtp/crypto/test/.cvsignore @@ -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 index 0000000000..ddefb75bb4 Binary files /dev/null and b/libs/srtp/crypto/test/aes_calc differ diff --git a/libs/srtp/crypto/test/aes_calc.c b/libs/srtp/crypto/test/aes_calc.c index 2fac07ae35..fe3c6ad07d 100644 --- a/libs/srtp/crypto/test/aes_calc.c +++ b/libs/srtp/crypto/test/aes_calc.c @@ -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)); diff --git a/libs/srtp/crypto/test/auth_driver.c b/libs/srtp/crypto/test/auth_driver.c index 3073d49500..cd8a75dd09 100644 --- a/libs/srtp/crypto/test/auth_driver.c +++ b/libs/srtp/crypto/test/auth_driver.c @@ -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 diff --git a/libs/srtp/crypto/test/cipher_driver.c b/libs/srtp/crypto/test/cipher_driver.c index 276e775b83..ea41ff5a4c 100644 --- a/libs/srtp/crypto/test/cipher_driver.c +++ b/libs/srtp/crypto/test/cipher_driver.c @@ -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 index 0000000000..8f32a62ac2 Binary files /dev/null and b/libs/srtp/crypto/test/datatypes_driver differ diff --git a/libs/srtp/crypto/test/datatypes_driver.c b/libs/srtp/crypto/test/datatypes_driver.c index f8e34ef942..f1866524c7 100644 --- a/libs/srtp/crypto/test/datatypes_driver.c +++ b/libs/srtp/crypto/test/datatypes_driver.c @@ -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 diff --git a/libs/srtp/crypto/test/env.c b/libs/srtp/crypto/test/env.c index 07b6f51527..37a6e2731b 100644 --- a/libs/srtp/crypto/test/env.c +++ b/libs/srtp/crypto/test/env.c @@ -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/kernel_driver.c b/libs/srtp/crypto/test/kernel_driver.c index 4271f8ee68..8ef8a5f4b3 100644 --- a/libs/srtp/crypto/test/kernel_driver.c +++ b/libs/srtp/crypto/test/kernel_driver.c @@ -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/rand_gen.c b/libs/srtp/crypto/test/rand_gen.c index 8fcf89cd66..ccea097f26 100644 --- a/libs/srtp/crypto/test/rand_gen.c +++ b/libs/srtp/crypto/test/rand_gen.c @@ -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 index 0000000000..2e9b028972 Binary files /dev/null and b/libs/srtp/crypto/test/sha1_driver differ diff --git a/libs/srtp/crypto/test/sha1_driver.c b/libs/srtp/crypto/test/sha1_driver.c index f7cb6ca2a6..6036022e93 100644 --- a/libs/srtp/crypto/test/sha1_driver.c +++ b/libs/srtp/crypto/test/sha1_driver.c @@ -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 index 0000000000..753df31686 Binary files /dev/null and b/libs/srtp/crypto/test/stat_driver differ diff --git a/libs/srtp/crypto/test/stat_driver.c b/libs/srtp/crypto/test/stat_driver.c index 09cc44a646..f9d75b7656 100644 --- a/libs/srtp/crypto/test/stat_driver.c +++ b/libs/srtp/crypto/test/stat_driver.c @@ -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; } diff --git a/libs/srtp/doc/Doxyfile b/libs/srtp/doc/Doxyfile index fc6ac95e11..c6e6a6d238 100644 --- a/libs/srtp/doc/Doxyfile +++ b/libs/srtp/doc/Doxyfile @@ -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 diff --git a/libs/srtp/doc/header.template b/libs/srtp/doc/header.template index bb1200e92b..2c0b96d46f 100644 --- a/libs/srtp/doc/header.template +++ b/libs/srtp/doc/header.template @@ -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. diff --git a/libs/srtp/doc/intro.txt b/libs/srtp/doc/intro.txt index f315599255..e8607d1c13 100644 --- a/libs/srtp/doc/intro.txt +++ b/libs/srtp/doc/intro.txt @@ -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) { diff --git a/libs/srtp/doc/libsrtp.pdf b/libs/srtp/doc/libsrtp.pdf index 0538ab4551..6f5e448e89 100644 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 index 0000000000..b0d888bac9 --- /dev/null +++ b/libs/srtp/include/ekt.h @@ -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 index 0000000000..2a6ece34eb --- /dev/null +++ b/libs/srtp/include/getopt_s.h @@ -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 */ diff --git a/libs/srtp/include/rtp.h b/libs/srtp/include/rtp.h index 65975ff35b..0e0119cf7b 100644 --- a/libs/srtp/include/rtp.h +++ b/libs/srtp/include/rtp.h @@ -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 @@ -54,72 +54,86 @@ #ifndef RTP_H #define RTP_H -#include "srtp.h" - #ifdef HAVE_NETINET_IN_H # include #elif defined HAVE_WINSOCK2_H # include #endif -#define rtp_header_len 12 +#include "srtp.h" -typedef srtp_hdr_t rtp_hdr_t; +typedef struct rtp_sender_ctx_t *rtp_sender_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; - -typedef struct { - rtp_msg_t message; - int socket; - srtp_ctx_t *srtp_ctx; - struct sockaddr_in addr; /* receiver's address */ -} rtp_receiver_t; - - -ssize_t -rtp_sendto(rtp_sender_t *sender, const void* msg, int len); - -ssize_t -rtp_recvfrom(rtp_receiver_t *receiver, void *msg, int *len); +typedef struct rtp_receiver_ctx_t *rtp_receiver_t; int -rtp_receiver_init(rtp_receiver_t *rcvr, int socket, - struct sockaddr_in addr, uint32_t ssrc); +rtp_sendto(rtp_sender_t sender, const void* msg, int len); int -rtp_sender_init(rtp_sender_t *sender, int socket, - struct sockaddr_in addr, uint32_t ssrc); +rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len); + +int +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 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 index 0000000000..1421386673 --- /dev/null +++ b/libs/srtp/include/rtp_priv.h @@ -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 */ diff --git a/libs/srtp/include/srtp.h b/libs/srtp/include/srtp.h index cb78f7e9c9..eb95e7d477 100644 --- a/libs/srtp/include/srtp.h +++ b/libs/srtp/include/srtp.h @@ -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 @@ -50,14 +50,7 @@ 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,70 +679,114 @@ 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; + + +/** + * @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); + + + + +/** + * @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); + + +/** + * @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. + * + */ + +void +append_salt_to_key(unsigned char *key, unsigned int bytes_in_key, + unsigned char *salt, unsigned int bytes_in_salt); + + /** * @} */ -/* - * 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); - - - -/* - * 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; - 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; - - /** * @defgroup SRTCP Secure RTCP @@ -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 index 0000000000..180a51b9e8 --- /dev/null +++ b/libs/srtp/include/srtp_priv.h @@ -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 */ diff --git a/libs/srtp/include/ut_sim.h b/libs/srtp/include/ut_sim.h index deed553b54..c25feeb654 100644 --- a/libs/srtp/include/ut_sim.h +++ b/libs/srtp/include/ut_sim.h @@ -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 diff --git a/libs/srtp/srtp.def b/libs/srtp/srtp.def index ea6908aba6..6fc94da0be 100644 --- a/libs/srtp/srtp.def +++ b/libs/srtp/srtp.def @@ -1,91 +1,91 @@ -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 +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 index 0000000000..9ae7f7e5c8 --- /dev/null +++ b/libs/srtp/srtp/ekt.c @@ -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 */ + +} + diff --git a/libs/srtp/srtp/srtp.c b/libs/srtp/srtp/srtp.c index 2db745d2bb..163d0d1f3f 100644 --- a/libs/srtp/srtp/srtp.c +++ b/libs/srtp/srtp/srtp.c @@ -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) { - aes_icm_context_init(&kdf->c, key); + err_status_t stat; + stat = crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, length); + if (stat) + return stat; + + 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