update to cvs head srtp

This commit is contained in:
Anthony Minessale 2013-01-17 17:59:53 -06:00
parent aad4da5b71
commit 72e2d183c1
100 changed files with 4732 additions and 1509 deletions

View File

@ -1 +0,0 @@
Fri Mar 16 17:20:27 EDT 2007

View File

@ -1,6 +1,6 @@
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -1,4 +1,4 @@
Secure RTP (SRTP) and UST Reference Implementations Secure RTP (SRTP) Reference Implementation
David A. McGrew David A. McGrew
Cisco Systems, Inc. Cisco Systems, Inc.
mcgrew@cisco.com 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 a supporting cryptographic kernel. These mechanisms are documented in
the Internet Drafts in the doc/ subdirectory. The SRTP API is the Internet Drafts in the doc/ subdirectory. The SRTP API is
documented in include/srtp.h, and the library is in libsrtp.a (after 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: Installation:

View File

@ -1 +1 @@
1.4.2 1.4.4

View File

@ -1,195 +1,196 @@
/* crypto/include/config.h. Generated by configure. */ /* crypto/include/config.h. Generated by configure. */
/* config_in.h. Generated from configure.in by autoheader. */ /* config_in.h. Generated from configure.in by autoheader. */
/* Define if building for a CISC machine (e.g. Intel). */ #if (_MSC_VER >= 1400)
#define CPU_CISC 1 # define HAVE_RAND_S 1
#endif
/* Define if building for a RISC machine (assume slow byte access). */
/* #undef CPU_RISC */ /* Define if building for a CISC machine (e.g. Intel). */
#define CPU_CISC 1
/* Path to random device */
/* #define DEV_URANDOM "/dev/urandom" */ /* Define if building for a RISC machine (assume slow byte access). */
/* #undef CPU_RISC */
/* Define to compile in dynamic debugging system. */
#define ENABLE_DEBUGGING 1 /* Path to random device */
/* #define DEV_URANDOM "/dev/urandom" */
/* Report errors to this file. */
/* #undef ERR_REPORTING_FILE */ /* Define to compile in dynamic debugging system. */
#define ENABLE_DEBUGGING 1
/* Define to use logging to stdout. */
#define ERR_REPORTING_STDOUT 1 /* Report errors to this file. */
/* #undef ERR_REPORTING_FILE */
/* Define this to use ISMAcryp code. */
/* #undef GENERIC_AESICM */ /* Define to use logging to stdout. */
#define ERR_REPORTING_STDOUT 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
/* #undef HAVE_ARPA_INET_H */ /* Define this to use ISMAcryp code. */
/* #undef GENERIC_AESICM */
/* Define to 1 if you have the <byteswap.h> header file. */
/* #undef HAVE_BYTESWAP_H */ /* Define to 1 if you have the <arpa/inet.h> header file. */
/* #undef HAVE_ARPA_INET_H */
/* Define to 1 if you have the `inet_aton' function. */
/* #undef HAVE_INET_ATON */ /* Define to 1 if you have the <byteswap.h> header file. */
/* #undef HAVE_BYTESWAP_H */
/* Define to 1 if the system has the type `int16_t'. */
#define HAVE_INT16_T 1 /* Define to 1 if you have the `inet_aton' function. */
/* #undef HAVE_INET_ATON */
/* 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 `int16_t'. */
#define HAVE_INT16_T 1
/* Define to 1 if the system has the type `int8_t'. */
#define HAVE_INT8_T 1 /* Define to 1 if the system has the type `int32_t'. */
#define HAVE_INT32_T 1
/* Define to 1 if you have the <inttypes.h> header file. */
/* #undef HAVE_INTTYPES_H */ /* Define to 1 if the system has the type `int8_t'. */
#define HAVE_INT8_T 1
/* Define to 1 if you have the `socket' library (-lsocket). */
/* #undef HAVE_LIBSOCKET */ /* Define to 1 if you have the <inttypes.h> header file. */
/* #undef HAVE_INTTYPES_H */
/* Define to 1 if you have the <machine/types.h> header file. */
/* #undef HAVE_MACHINE_TYPES_H */ /* Define to 1 if you have the `socket' library (-lsocket). */
/* #undef HAVE_LIBSOCKET */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1 /* Define to 1 if you have the <machine/types.h> header file. */
/* #undef HAVE_MACHINE_TYPES_H */
/* Define to 1 if you have the <netinet/in.h> header file. */
/* #undef HAVE_NETINET_IN_H */ /* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `socket' function. */
/* #undef HAVE_SOCKET */ /* Define to 1 if you have the <netinet/in.h> header file. */
/* #undef HAVE_NETINET_IN_H */
/* Define to 1 if you have the <stdint.h> header file. */
/* #undef HAVE_STDINT_H */ /* Define to 1 if you have the `socket' function. */
/* #undef HAVE_SOCKET */
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1 /* Define to 1 if you have the <stdint.h> header file. */
/* #undef HAVE_STDINT_H */
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1 /* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1 /* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <syslog.h> header file. */
/* #undef HAVE_SYSLOG_H */ /* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/int_types.h> header file. */
/* #undef HAVE_SYS_INT_TYPES_H */ /* Define to 1 if you have the <syslog.h> header file. */
/* #undef HAVE_SYSLOG_H */
/* Define to 1 if you have the <sys/socket.h> header file. */
/* #undef HAVE_SYS_SOCKET_H */ /* Define to 1 if you have the <sys/int_types.h> header file. */
/* #undef HAVE_SYS_INT_TYPES_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the <sys/socket.h> header file. */
/* #undef HAVE_SYS_SOCKET_H */
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
/* #undef HAVE_SYS_UIO_H */ /* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if the system has the type `uint16_t'. */
#define HAVE_UINT16_T 1 /* Define to 1 if you have the <sys/uio.h> header file. */
/* #undef HAVE_SYS_UIO_H */
/* Define to 1 if the system has the type `uint32_t'. */
#define HAVE_UINT32_T 1 /* 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 `uint64_t'. */
#define HAVE_UINT64_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 `uint8_t'. */
#define HAVE_UINT8_T 1 /* Define to 1 if the system has the type `uint64_t'. */
#define HAVE_UINT64_T 1
/* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */ /* Define to 1 if the system has the type `uint8_t'. */
#define HAVE_UINT8_T 1
/* Define to 1 if you have the `usleep' function. */
/* #undef HAVE_USLEEP */ /* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* Define to 1 if you have the <windows.h> header file. */
#define HAVE_WINDOWS_H 1 /* Define to 1 if you have the `usleep' function. */
/* #undef HAVE_USLEEP */
/* Define to 1 if you have the <winsock2.h> header file. */
#define HAVE_WINSOCK2_H 1 /* Define to 1 if you have the <windows.h> header file. */
#define HAVE_WINDOWS_H 1
/* Define to use X86 inlined assembly code */
/* #undef HAVE_X86 */ /* Define to 1 if you have the <winsock2.h> header file. */
#define HAVE_WINSOCK2_H 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "" /* Define to use X86 inlined assembly code */
/* #undef HAVE_X86 */
/* Define to the full name of this package. */
#define PACKAGE_NAME "" /* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "" /* Define to the full name of this package. */
#define PACKAGE_NAME ""
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "" /* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "" /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
/* The size of a `unsigned long', as computed by sizeof. */
#define SIZEOF_UNSIGNED_LONG 4 /* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* The size of a `unsigned long long', as computed by sizeof. */
#define SIZEOF_UNSIGNED_LONG_LONG 8 /* The size of a `unsigned long', as computed by sizeof. */
#define SIZEOF_UNSIGNED_LONG 4
/* Define to use GDOI. */
/* #undef SRTP_GDOI */ /* The size of a `unsigned long long', as computed by sizeof. */
#define SIZEOF_UNSIGNED_LONG_LONG 8
/* Define to compile for kernel contexts. */
/* #undef SRTP_KERNEL */ /* Define to use GDOI. */
/* #undef SRTP_GDOI */
/* Define to compile for Linux kernel context. */
/* #undef SRTP_KERNEL_LINUX */ /* Define to compile for kernel contexts. */
/* #undef SRTP_KERNEL */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1 /* Define to compile for Linux kernel context. */
/* #undef SRTP_KERNEL_LINUX */
/* Write errors to this file */
/* #undef USE_ERR_REPORTING_FILE */ /* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to use syslog logging. */
/* #undef USE_SYSLOG */ /* Write errors to this file */
/* #undef USE_ERR_REPORTING_FILE */
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */ /* Define to use syslog logging. */
/* #undef WORDS_BIGENDIAN */ /* #undef USE_SYSLOG */
/* Define to empty if `const' does not conform to ANSI C. */ /* Define to 1 if your processor stores words with the most significant byte
/* #undef const */ first (like Motorola and SPARC, unlike Intel and VAX). */
/* #undef WORDS_BIGENDIAN */
/* 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. */ /* Define to empty if `const' does not conform to ANSI C. */
#ifndef __cplusplus /* #undef const */
#define inline __inline
#endif /* Define 'inline' to nothing, since the MSVC compiler doesn't support it. */
#define inline
/* Define to `unsigned' if <sys/types.h> does not define. */
/* #undef size_t */ /* Define to `unsigned' if <sys/types.h> does not define. */
/* #undef size_t */
#if (_MSC_VER >= 1400) // VC8+
#ifndef _CRT_SECURE_NO_DEPRECATE #if (_MSC_VER >= 1400) // VC8+
#define _CRT_SECURE_NO_DEPRECATE #ifndef _CRT_SECURE_NO_DEPRECATE
#endif #define _CRT_SECURE_NO_DEPRECATE
#ifndef _CRT_NONSTDC_NO_DEPRECATE #endif
#define _CRT_NONSTDC_NO_DEPRECATE #ifndef _CRT_NONSTDC_NO_DEPRECATE
#endif #define _CRT_NONSTDC_NO_DEPRECATE
#endif // VC8+ #endif
#endif // VC8+
#ifndef uint32_t
typedef unsigned __int8 uint8_t; #ifndef uint32_t
typedef unsigned __int16 uint16_t; typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t; typedef unsigned __int16 uint16_t;
typedef unsigned __int64 uint64_t; typedef unsigned __int32 uint32_t;
typedef __int8 int8_t; typedef unsigned __int64 uint64_t;
typedef __int16 int16_t; typedef __int8 int8_t;
typedef __int32 int32_t; typedef __int16 int16_t;
typedef __int64 int64_t; typedef __int32 int32_t;
#endif typedef __int64 int64_t;
#endif
#ifdef _MSC_VER
#pragma warning(disable:4311) #ifdef _MSC_VER
#endif #pragma warning(disable:4311)
#endif

View File

@ -144,10 +144,10 @@ fi
AC_MSG_CHECKING(which random device to use) AC_MSG_CHECKING(which random device to use)
if test "$enable_kernel_linux" = "yes"; then 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]) AC_MSG_RESULT([Linux kernel builtin])
else else
RNG_OBJS=rand_source.c RNG_OBJS=rand_source.o
if test -n "$DEV_URANDOM"; then if test -n "$DEV_URANDOM"; then
AC_DEFINE_UNQUOTED(DEV_URANDOM, "$DEV_URANDOM",[Path to random device]) AC_DEFINE_UNQUOTED(DEV_URANDOM, "$DEV_URANDOM",[Path to random device])
AC_MSG_RESULT([$DEV_URANDOM]) AC_MSG_RESULT([$DEV_URANDOM])
@ -197,7 +197,7 @@ AC_C_INLINE
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
dnl Checks for library functions. dnl Checks for library functions.
AC_CHECK_FUNCS(socket inet_aton usleep) AC_CHECK_FUNCS(socket inet_aton usleep sigaction)
dnl Find socket function if not found yet. dnl Find socket function if not found yet.
if test "x$ac_cv_func_socket" = "xno"; then if test "x$ac_cv_func_socket" = "xno"; then
@ -222,7 +222,7 @@ AC_C_BIGENDIAN
dnl check host_cpu type, set defines appropriately dnl check host_cpu type, set defines appropriately
case $host_cpu in case $host_cpu in
i*86 ) i*86 | x86_64 )
AC_DEFINE(CPU_CISC, 1, AC_DEFINE(CPU_CISC, 1,
[Define if building for a CISC machine (e.g. Intel).]) [Define if building for a CISC machine (e.g. Intel).])
AC_DEFINE(HAVE_X86, 1, AC_DEFINE(HAVE_X86, 1,

View File

@ -0,0 +1 @@
Makefile

View File

@ -41,21 +41,28 @@ dummy : all runtest
# test applications # test applications
testapp = test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \ testapp = #test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \
test/stat_driver$(EXE) test/sha1_driver$(EXE) \ #test/stat_driver$(EXE) test/sha1_driver$(EXE) \
test/kernel_driver$(EXE) test/aes_calc$(EXE) test/rand_gen$(EXE) \ #test/kernel_driver$(EXE) test/aes_calc$(EXE) test/rand_gen$(EXE) \
test/env$(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) runtest: libcryptomodule.a $(testapp)
test/env$(EXE) # print out information on the build environment test/env$(EXE) # print out information on the build environment
@echo "running libcryptomodule test applications..." @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/cipher_driver$(EXE) -v >/dev/null
test/datatypes_driver$(EXE) -v >/dev/null test/datatypes_driver$(EXE) -v >/dev/null
test/stat_driver$(EXE) >/dev/null test/stat_driver$(EXE) >/dev/null

View File

@ -63,7 +63,7 @@ aes_128_cbc_hmac_sha1_96_func(void *key,
/* perform encryption and authentication */ /* perform encryption and authentication */
/* set aes key */ /* 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; if (status) return status;
/* set iv */ /* set iv */
@ -139,7 +139,7 @@ aes_128_cbc_hmac_sha1_96_inv(void *key,
/* perform encryption and authentication */ /* perform encryption and authentication */
/* set aes key */ /* 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; if (status) return status;
/* set iv */ /* set iv */
@ -227,7 +227,7 @@ aes_128_cbc_hmac_sha1_96_enc(void *key,
/* perform encryption and authentication */ /* perform encryption and authentication */
/* set aes key */ /* 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; if (status) return status;
/* set iv */ /* set iv */
@ -397,7 +397,7 @@ aes_128_cbc_hmac_sha1_96_dec(void *key,
*opaque_len -= TAG_LEN; *opaque_len -= TAG_LEN;
/* decrypt the confidential data */ /* 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; if (status) return status;
status = aes_cbc_set_iv(&aes_ctx, iv); status = aes_cbc_set_iv(&aes_ctx, iv);
if (status) return status; if (status) return status;
@ -564,7 +564,7 @@ cryptoalg_find_by_id(int id) {
case 1: case 1:
return cryptoalg; return cryptoalg;
default: default:
return 0; break;
} }
return 0; return 0;
} }

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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; extern debug_module_t mod_aes_icm;
void static void
aes_expand_encryption_key(const v128_t *key, aes_128_expand_encryption_key(const uint8_t *key,
aes_expanded_key_t expanded_key) { aes_expanded_key_t *expanded_key) {
int i; int i;
gf2_8 rc; gf2_8 rc;
/* initialize round constant */ /* initialize round constant */
rc = 1; rc = 1;
expanded_key[0].v32[0] = key->v32[0]; expanded_key->num_rounds = 10;
expanded_key[0].v32[1] = key->v32[1];
expanded_key[0].v32[2] = key->v32[2]; v128_copy_octet_string(&expanded_key->round[0], key);
expanded_key[0].v32[3] = key->v32[3];
#if 0 #if 0
debug_print(mod_aes_icm, 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 #endif
/* loop over round keys */ /* loop over round keys */
for (i=1; i < 11; i++) { for (i=1; i < 11; i++) {
/* munge first word of round key */ /* munge first word of round key */
expanded_key[i].v8[0] = aes_sbox[expanded_key[i-1].v8[13]] ^ rc; expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[13]] ^ rc;
expanded_key[i].v8[1] = aes_sbox[expanded_key[i-1].v8[14]]; expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[14]];
expanded_key[i].v8[2] = aes_sbox[expanded_key[i-1].v8[15]]; expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[15]];
expanded_key[i].v8[3] = aes_sbox[expanded_key[i-1].v8[12]]; 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 /* set remaining 32 bit words to the exor of the one previous with
* the one four words previous */ * the one four words previous */
expanded_key[i].v32[1] = expanded_key->round[i].v32[1] =
expanded_key[i].v32[0] ^ expanded_key[i-1].v32[1]; expanded_key->round[i].v32[0] ^ expanded_key->round[i-1].v32[1];
expanded_key[i].v32[2] = expanded_key->round[i].v32[2] =
expanded_key[i].v32[1] ^ expanded_key[i-1].v32[2]; expanded_key->round[i].v32[1] ^ expanded_key->round[i-1].v32[2];
expanded_key[i].v32[3] = expanded_key->round[i].v32[3] =
expanded_key[i].v32[2] ^ expanded_key[i-1].v32[3]; expanded_key->round[i].v32[2] ^ expanded_key->round[i-1].v32[3];
#if 0 #if 0
debug_print2(mod_aes_icm, 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 #endif
/* modify round constant */ /* modify round constant */
@ -1411,19 +1410,107 @@ aes_expand_encryption_key(const v128_t *key,
} }
} }
void static void
aes_expand_decryption_key(const v128_t *key, aes_256_expand_encryption_key(const unsigned char *key,
aes_expanded_key_t expanded_key) { aes_expanded_key_t *expanded_key) {
int i; 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 */ /* 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_t tmp;
v128_copy(&tmp, &expanded_key[10-i]); v128_copy(&tmp, &expanded_key->round[num_rounds-i]);
v128_copy(&expanded_key[10-i], &expanded_key[i]); v128_copy(&expanded_key->round[num_rounds-i], &expanded_key->round[i]);
v128_copy(&expanded_key[i], &tmp); 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 * followed by the T4 table (which cancels out the use of the sbox
* in the U-tables) * in the U-tables)
*/ */
for (i=1; i < 10; i++) { for (i=1; i < num_rounds; i++) {
#ifdef CPU_RISC #ifdef CPU_RISC
uint32_t tmp; uint32_t tmp;
tmp = expanded_key[i].v32[0]; tmp = expanded_key->round[i].v32[0];
expanded_key[i].v32[0] = expanded_key->round[i].v32[0] =
U0[T4[(tmp >> 24) ] & 0xff] ^ U0[T4[(tmp >> 24) ] & 0xff] ^
U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ U1[T4[(tmp >> 16) & 0xff] & 0xff] ^
U2[T4[(tmp >> 8) & 0xff] & 0xff] ^ U2[T4[(tmp >> 8) & 0xff] & 0xff] ^
U3[T4[(tmp) & 0xff] & 0xff]; U3[T4[(tmp) & 0xff] & 0xff];
tmp = expanded_key[i].v32[1]; tmp = expanded_key->round[i].v32[1];
expanded_key[i].v32[1] = expanded_key->round[i].v32[1] =
U0[T4[(tmp >> 24) ] & 0xff] ^ U0[T4[(tmp >> 24) ] & 0xff] ^
U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ U1[T4[(tmp >> 16) & 0xff] & 0xff] ^
U2[T4[(tmp >> 8) & 0xff] & 0xff] ^ U2[T4[(tmp >> 8) & 0xff] & 0xff] ^
U3[T4[(tmp) & 0xff] & 0xff]; U3[T4[(tmp) & 0xff] & 0xff];
tmp = expanded_key[i].v32[2]; tmp = expanded_key->round[i].v32[2];
expanded_key[i].v32[2] = expanded_key->round[i].v32[2] =
U0[T4[(tmp >> 24) ] & 0xff] ^ U0[T4[(tmp >> 24) ] & 0xff] ^
U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ U1[T4[(tmp >> 16) & 0xff] & 0xff] ^
U2[T4[(tmp >> 8) & 0xff] & 0xff] ^ U2[T4[(tmp >> 8) & 0xff] & 0xff] ^
U3[T4[(tmp) & 0xff] & 0xff]; U3[T4[(tmp) & 0xff] & 0xff];
tmp = expanded_key[i].v32[3]; tmp = expanded_key->round[i].v32[3];
expanded_key[i].v32[3] = expanded_key->round[i].v32[3] =
U0[T4[(tmp >> 24) ] & 0xff] ^ U0[T4[(tmp >> 24) ] & 0xff] ^
U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ U1[T4[(tmp >> 16) & 0xff] & 0xff] ^
U2[T4[(tmp >> 8) & 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; uint32_t c0, c1, c2, c3;
c0 = U0[aes_sbox[expanded_key[i].v8[0]]] c0 = U0[aes_sbox[expanded_key->round[i].v8[0]]]
^ U1[aes_sbox[expanded_key[i].v8[1]]] ^ U1[aes_sbox[expanded_key->round[i].v8[1]]]
^ U2[aes_sbox[expanded_key[i].v8[2]]] ^ U2[aes_sbox[expanded_key->round[i].v8[2]]]
^ U3[aes_sbox[expanded_key[i].v8[3]]]; ^ U3[aes_sbox[expanded_key->round[i].v8[3]]];
c1 = U0[aes_sbox[expanded_key[i].v8[4]]] c1 = U0[aes_sbox[expanded_key->round[i].v8[4]]]
^ U1[aes_sbox[expanded_key[i].v8[5]]] ^ U1[aes_sbox[expanded_key->round[i].v8[5]]]
^ U2[aes_sbox[expanded_key[i].v8[6]]] ^ U2[aes_sbox[expanded_key->round[i].v8[6]]]
^ U3[aes_sbox[expanded_key[i].v8[7]]]; ^ U3[aes_sbox[expanded_key->round[i].v8[7]]];
c2 = U0[aes_sbox[expanded_key[i].v8[8]]] c2 = U0[aes_sbox[expanded_key->round[i].v8[8]]]
^ U1[aes_sbox[expanded_key[i].v8[9]]] ^ U1[aes_sbox[expanded_key->round[i].v8[9]]]
^ U2[aes_sbox[expanded_key[i].v8[10]]] ^ U2[aes_sbox[expanded_key->round[i].v8[10]]]
^ U3[aes_sbox[expanded_key[i].v8[11]]]; ^ U3[aes_sbox[expanded_key->round[i].v8[11]]];
c3 = U0[aes_sbox[expanded_key[i].v8[12]]] c3 = U0[aes_sbox[expanded_key->round[i].v8[12]]]
^ U1[aes_sbox[expanded_key[i].v8[13]]] ^ U1[aes_sbox[expanded_key->round[i].v8[13]]]
^ U2[aes_sbox[expanded_key[i].v8[14]]] ^ U2[aes_sbox[expanded_key->round[i].v8[14]]]
^ U3[aes_sbox[expanded_key[i].v8[15]]]; ^ U3[aes_sbox[expanded_key->round[i].v8[15]]];
expanded_key[i].v32[0] = c0; expanded_key->round[i].v32[0] = c0;
expanded_key[i].v32[1] = c1; expanded_key->round[i].v32[1] = c1;
expanded_key[i].v32[2] = c2; expanded_key->round[i].v32[2] = c2;
expanded_key[i].v32[3] = c3; expanded_key->round[i].v32[3] = c3;
#endif #endif
} }
return err_status_ok;
} }
#ifdef CPU_CISC #ifdef CPU_CISC
@ -1910,42 +1999,67 @@ aes_inv_final_round(v128_t *state, const v128_t *round_key) {
void 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 */ /* add in the subkey */
v128_xor_eq(plaintext, exp_key + 0); v128_xor_eq(plaintext, &exp_key->round[0]);
/* now do nine rounds */ /* now do the rounds */
aes_round(plaintext, exp_key + 1); aes_round(plaintext, &exp_key->round[1]);
aes_round(plaintext, exp_key + 2); aes_round(plaintext, &exp_key->round[2]);
aes_round(plaintext, exp_key + 3); aes_round(plaintext, &exp_key->round[3]);
aes_round(plaintext, exp_key + 4); aes_round(plaintext, &exp_key->round[4]);
aes_round(plaintext, exp_key + 5); aes_round(plaintext, &exp_key->round[5]);
aes_round(plaintext, exp_key + 6); aes_round(plaintext, &exp_key->round[6]);
aes_round(plaintext, exp_key + 7); aes_round(plaintext, &exp_key->round[7]);
aes_round(plaintext, exp_key + 8); aes_round(plaintext, &exp_key->round[8]);
aes_round(plaintext, exp_key + 9); aes_round(plaintext, &exp_key->round[9]);
/* the last round is different */ if (exp_key->num_rounds == 10) {
aes_final_round(plaintext, &exp_key->round[10]);
aes_final_round(plaintext, exp_key + 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 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 */ /* add in the subkey */
v128_xor_eq(plaintext, exp_key + 0); v128_xor_eq(plaintext, &exp_key->round[0]);
/* now do nine rounds */ /* now do the rounds */
aes_inv_round(plaintext, exp_key + 1); aes_inv_round(plaintext, &exp_key->round[1]);
aes_inv_round(plaintext, exp_key + 2); aes_inv_round(plaintext, &exp_key->round[2]);
aes_inv_round(plaintext, exp_key + 3); aes_inv_round(plaintext, &exp_key->round[3]);
aes_inv_round(plaintext, exp_key + 4); aes_inv_round(plaintext, &exp_key->round[4]);
aes_inv_round(plaintext, exp_key + 5); aes_inv_round(plaintext, &exp_key->round[5]);
aes_inv_round(plaintext, exp_key + 6); aes_inv_round(plaintext, &exp_key->round[6]);
aes_inv_round(plaintext, exp_key + 7); aes_inv_round(plaintext, &exp_key->round[7]);
aes_inv_round(plaintext, exp_key + 8); aes_inv_round(plaintext, &exp_key->round[8]);
aes_inv_round(plaintext, exp_key + 9); aes_inv_round(plaintext, &exp_key->round[9]);
/* the last round is different */ if (exp_key->num_rounds == 10) {
aes_inv_final_round(plaintext, exp_key + 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]);
}
} }

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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, debug_print(mod_aes_cbc,
"allocating cipher with key length %d", key_len); "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; 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)); tmp = (sizeof(aes_cbc_ctx_t) + sizeof(cipher_t));
pointer = crypto_alloc(tmp); pointer = (uint8_t*)crypto_alloc(tmp);
if (pointer == NULL) if (pointer == NULL)
return err_status_alloc_fail; return err_status_alloc_fail;
@ -104,23 +104,24 @@ aes_cbc_dealloc(cipher_t *c) {
} }
err_status_t 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) { cipher_direction_t dir) {
v128_t tmp_key; err_status_t status;
/* set tmp_key (for alignment) */
v128_copy_octet_string(&tmp_key, key);
debug_print(mod_aes_cbc, 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 */ /* expand key for the appropriate direction */
switch (dir) { switch (dir) {
case (direction_encrypt): 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; break;
case (direction_decrypt): 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; break;
default: default:
return err_status_bad_param; return err_status_bad_param;
@ -135,7 +136,7 @@ err_status_t
aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) { aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) {
int i; int i;
/* v128_t *input = iv; */ /* v128_t *input = iv; */
uint8_t *input = iv; uint8_t *input = (uint8_t*) iv;
/* set state and 'previous' block to iv */ /* set state and 'previous' block to iv */
for (i=0; i < 16; i++) 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", debug_print(mod_aes_cbc, "inblock: %s",
v128_hex_string(&c->state)); 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", debug_print(mod_aes_cbc, "outblock: %s",
v128_hex_string(&c->state)); v128_hex_string(&c->state));
@ -236,7 +237,7 @@ aes_cbc_decrypt(aes_cbc_ctx_t *c,
v128_hex_string(&state)); v128_hex_string(&state));
/* decrypt state */ /* decrypt state */
aes_decrypt(&state, c->expanded_key); aes_decrypt(&state, &c->expanded_key);
debug_print(mod_aes_cbc, "outblock: %s", debug_print(mod_aes_cbc, "outblock: %s",
v128_hex_string(&state)); v128_hex_string(&state));
@ -332,7 +333,7 @@ char
aes_cbc_description[] = "aes cipher block chaining (cbc) mode"; 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 * all-zero IV, so that the first block encryption matches the test
* case in that appendix. This property provides a check of the base * case in that appendix. This property provides a check of the base
* AES encryption and decryption algorithms; if CBC fails on some * 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 */ &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_type_t aes_cbc = {
(cipher_alloc_func_t) aes_cbc_alloc, (cipher_alloc_func_t) aes_cbc_alloc,
(cipher_dealloc_func_t) aes_cbc_dealloc, (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, (cipher_set_iv_func_t) aes_cbc_set_iv,
(char *) aes_cbc_description, (char *) aes_cbc_description,
(int) 0, /* instance count */ (int) 0, /* instance count */
(cipher_test_case_t *) &aes_cbc_test_case_0, (cipher_test_case_t *) &aes_cbc_test_case_3,
(debug_module_t *) &mod_aes_cbc (debug_module_t *) &mod_aes_cbc,
(cipher_type_id_t) AES_CBC
}; };

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -49,9 +49,6 @@
#include "aes_icm.h" #include "aes_icm.h"
#include "alloc.h" #include "alloc.h"
#ifdef _MSC_VER
#pragma warning(disable:4100)
#endif
debug_module_t mod_aes_icm = { debug_module_t mod_aes_icm = {
0, /* debugging is off by default */ 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; uint8_t *pointer;
int tmp; 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. * Ismacryp, for example, uses 16 byte key + 8 byte
The check for key_len = 30 does not apply. Our usage * salt so this function is called with key_len = 24.
of aes functions with key_len = values other than 30 * The check for key_len = 30/38/46 does not apply. Our usage
has not broken anything. Don't know what would be the * of aes functions with key_len = values other than 30
effect of skipping this check for srtp in general. * 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) */
if (!(forIsmacryp && key_len > 16 && key_len < 30) &&
key_len != 30 && key_len != 38 && key_len != 46)
return err_status_bad_param; return err_status_bad_param;
/* allocate memory a cipher of type aes_icm */ /* allocate memory a cipher of type aes_icm */
tmp = (sizeof(aes_icm_ctx_t) + sizeof(cipher_t)); tmp = (sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
pointer = crypto_alloc(tmp); pointer = (uint8_t*)crypto_alloc(tmp);
if (pointer == NULL) if (pointer == NULL)
return err_status_alloc_fail; return err_status_alloc_fail;
@ -163,30 +163,38 @@ aes_icm_dealloc(cipher_t *c) {
*/ */
err_status_t err_status_t
aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key) { aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key, int key_len) {
v128_t tmp_key; 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 */ /* set counter and initial values to 'offset' value */
/* FIX!!! this assumes the salt is at key + 16, and thus that the */ /* Note this copies past the end of the 'key' array by 2 bytes! */
/* FIX!!! cipher key length is 16! Also note this copies past the v128_copy_octet_string(&c->counter, key + base_key_len);
end of the 'key' array by 2 bytes! */ v128_copy_octet_string(&c->offset, key + base_key_len);
v128_copy_octet_string(&c->counter, key + 16);
v128_copy_octet_string(&c->offset, key + 16);
/* force last two octets of the offset to zero (for srtp compatibility) */ /* force last two octets of the offset to zero (for srtp compatibility) */
c->offset.v8[14] = c->offset.v8[15] = 0; c->offset.v8[14] = c->offset.v8[15] = 0;
c->counter.v8[14] = c->counter.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, 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, debug_print(mod_aes_icm,
"offset: %s", v128_hex_string(&c->offset)); "offset: %s", v128_hex_string(&c->offset));
/* expand key */ /* 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 */ /* indicate that the keystream_buffer is empty */
c->bytes_in_buffer = 0; c->bytes_in_buffer = 0;
@ -232,7 +240,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
/* fill keystream buffer, if needed */ /* fill keystream buffer, if needed */
if (tail_num) { if (tail_num) {
v128_copy(&c->keystream_buffer, &c->counter); 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); c->bytes_in_buffer = sizeof(v128_t);
debug_print(mod_aes_icm, "counter: %s", debug_print(mod_aes_icm, "counter: %s",
@ -259,7 +267,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
err_status_t err_status_t
aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) { 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, debug_print(mod_aes_icm,
"setting iv: %s", v128_hex_string(nonce)); "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 * this is an internal, hopefully inlined function
*/ */
inline void static inline void
aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) { aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
/* fill buffer with new keystream */ /* fill buffer with new keystream */
v128_copy(&c->keystream_buffer, &c->counter); 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); c->bytes_in_buffer = sizeof(v128_t);
debug_print(mod_aes_icm, "counter: %s", 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) { if (forIsmacryp) {
uint32_t temp; uint32_t temp;
/* alex's clock counter forward */ //alex's clock counter forward
temp = ntohl(c->counter.v32[3]); temp = ntohl(c->counter.v32[3]);
c->counter.v32[3] = htonl(++temp); c->counter.v32[3] = htonl(++temp);
} else { } 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); 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", debug_print(mod_aes_icm, "block index: %d",
htons(c->counter.v16[7])); 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 */ /* deal with odd case of small bytes_to_encr */
for (i = (sizeof(v128_t) - c->bytes_in_buffer); 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++) { for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
/* fill buffer with new keystream */ /* 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 * 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) { if ((bytes_to_encr & 0xf) != 0) {
/* fill buffer with new keystream */ /* 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++) for (i=0; i < (bytes_to_encr & 0xf); i++)
*buf++ ^= c->keystream_buffer.v8[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 */ 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 * 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, (cipher_set_iv_func_t) aes_icm_set_iv,
(char *) aes_icm_description, (char *) aes_icm_description,
(int) 0, /* instance count */ (int) 0, /* instance count */
(cipher_test_case_t *) &aes_icm_test_case_0, (cipher_test_case_t *) &aes_icm_test_case_1,
(debug_module_t *) &mod_aes_icm (debug_module_t *) &mod_aes_icm,
(cipher_type_id_t) AES_ICM
}; };

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * cipher_type_test(ct, test_data) tests a cipher of type ct against
* provided in an array of values of key, salt, xtd_seq_num_t, * test cases provided in a list test_data of values of key, salt, iv,
* plaintext, and ciphertext that is known to be good * 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 #define MAX_KEY_LEN 64
err_status_t err_status_t
cipher_type_self_test(const cipher_type_t *ct) { cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
const cipher_test_case_t *test_case = ct->test_data; const cipher_test_case_t *test_case = test_data;
cipher_t *c; cipher_t *c;
err_status_t status; err_status_t status;
uint8_t buffer[SELF_TEST_BUF_OCTETS]; 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)); test_case->ciphertext_length_octets));
/* compare the resulting ciphertext with that in the test case */ /* 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; return err_status_algo_fail;
status = err_status_ok; status = err_status_ok;
for (i=0; i < test_case->ciphertext_length_octets; i++) 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)); test_case->plaintext_length_octets));
/* compare the resulting plaintext with that in the test case */ /* 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; return err_status_algo_fail;
status = err_status_ok; status = err_status_ok;
for (i=0; i < test_case->plaintext_length_octets; i++) 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 */ /* now run some random invertibility tests */
/* allocate cipher, using paramaters from the first test case */ /* 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); status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
if (status) if (status)
return status; return status;
@ -344,7 +344,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
octet_string_hex_string(buffer, length)); octet_string_hex_string(buffer, length));
/* compare the resulting plaintext with the original one */ /* compare the resulting plaintext with the original one */
if ((int)length != plaintext_len) if (length != plaintext_len)
return err_status_algo_fail; return err_status_algo_fail;
status = err_status_ok; status = err_status_ok;
for (i=0; i < plaintext_len; i++) 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; 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 * cipher_bits_per_second(c, l, t) computes (an estimate of) the
* number of bits that a cipher implementation can encrypt in a second * 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 char *enc_buf;
unsigned int len = octets_in_buffer; 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) if (enc_buf == NULL)
return 0; /* indicate bad parameters by returning null */ return 0; /* indicate bad parameters by returning null */

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -48,10 +48,6 @@
#include "null_cipher.h" #include "null_cipher.h"
#include "alloc.h" #include "alloc.h"
#ifdef _MSC_VER
#pragma warning(disable:4100)
#endif
/* the null_cipher uses the cipher debug module */ /* the null_cipher uses the cipher debug module */
extern debug_module_t mod_cipher; 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); "allocating cipher with key length %d", key_len);
/* allocate memory a cipher of type null_cipher */ /* 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) if (pointer == NULL)
return err_status_alloc_fail; return err_status_alloc_fail;
@ -103,7 +99,7 @@ null_cipher_dealloc(cipher_t *c) {
} }
err_status_t 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); debug_print(mod_cipher, "initializing null cipher", NULL);
@ -151,6 +147,7 @@ cipher_type_t null_cipher = {
(char *) null_cipher_description, (char *) null_cipher_description,
(int) 0, (int) 0,
(cipher_test_case_t *) &null_cipher_test_0, (cipher_test_case_t *) &null_cipher_test_0,
(debug_module_t *) NULL (debug_module_t *) NULL,
(cipher_type_id_t) NULL_CIPHER
}; };

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * auth_type_test() tests an auth function of type ct against
* test cases provided in an array of values of key, data, and tag * test cases provided in a list test_data of values of key, data, and tag
* that is known to be good * 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 #define SELF_TEST_TAG_BUF_OCTETS 32
err_status_t err_status_t
auth_type_self_test(const auth_type_t *at) { auth_type_test(const auth_type_t *at, const auth_test_case_t *test_data) {
auth_test_case_t *test_case = at->test_data; const auth_test_case_t *test_case = test_data;
auth_t *a; auth_t *a;
err_status_t status; err_status_t status;
uint8_t tag[SELF_TEST_TAG_BUF_OCTETS]; 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);
}

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) { hmac_alloc(auth_t **a, int key_len, int out_len) {
extern auth_type_t hmac; extern auth_type_t hmac;
uint8_t *pointer; 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, "allocating auth func with key length %d", key_len);
debug_print(mod_hmac, " tag length %d", out_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; return err_status_bad_param;
/* allocate memory for auth and hmac_ctx_t structures */ /* 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) if (pointer == NULL)
return err_status_alloc_fail; 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)->out_len = out_len;
(*a)->key_len = key_len; (*a)->key_len = key_len;
(*a)->prefix_len = 0; (*a)->prefix_len = 0;
new_hmac_ctx = (hmac_ctx_t *)((*a)->state);
/* increment global count of all hmac uses */ /* increment global count of all hmac uses */
hmac.ref_count++; hmac.ref_count++;
@ -180,7 +178,7 @@ hmac_compute(hmac_ctx_t *state, const void *message,
return err_status_bad_param; return err_status_bad_param;
/* hash message, copy output into H */ /* 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); sha1_final(&state->ctx, H);
/* /*
@ -264,6 +262,7 @@ hmac = {
(char *) hmac_description, (char *) hmac_description,
(int) 0, /* instance count */ (int) 0, /* instance count */
(auth_test_case_t *) &hmac_test_case_0, (auth_test_case_t *) &hmac_test_case_0,
(debug_module_t *) &mod_hmac (debug_module_t *) &mod_hmac,
(auth_type_id_t) HMAC_SHA1
}; };

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -48,10 +48,6 @@
#include "null_auth.h" #include "null_auth.h"
#include "alloc.h" #include "alloc.h"
#ifdef _MSC_VER
#pragma warning(disable:4100)
#endif
/* null_auth uses the auth debug module */ /* null_auth uses the auth debug module */
extern debug_module_t mod_auth; 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); debug_print(mod_auth, " tag length %d", out_len);
/* allocate memory for auth and null_auth_ctx_t structures */ /* 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) if (pointer == NULL)
return err_status_alloc_fail; return err_status_alloc_fail;
@ -159,6 +155,8 @@ null_auth = {
(auth_start_func) null_auth_start, (auth_start_func) null_auth_start,
(char *) null_auth_description, (char *) null_auth_description,
(int) 0, /* instance count */ (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
}; };

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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]; H4 = hash_value[4];
/* copy/xor message into array */ /* copy/xor message into array */
W[0] = be32_to_cpu(M[0]); W[0] = be32_to_cpu(M[0]);
W[1] = be32_to_cpu(M[1]); W[1] = be32_to_cpu(M[1]);
W[2] = be32_to_cpu(M[2]); W[2] = be32_to_cpu(M[2]);
@ -184,7 +184,7 @@ sha1_core(const uint32_t M[16], uint32_t hash_value[5]) {
void void
sha1_init(sha1_ctx_t *ctx) { sha1_init(sha1_ctx_t *ctx) {
/* initialize state vector */ /* initialize state vector */
ctx->H[0] = 0x67452301; ctx->H[0] = 0x67452301;
ctx->H[1] = 0xefcdab89; 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 */ /* loop over 16-word blocks of M */
while (octets_in_msg > 0) { while (octets_in_msg > 0) {
if (octets_in_msg + ctx->octets_in_buffer >= 64) { 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; int tail = ctx->octets_in_buffer % 4;
/* copy/xor message into array */ /* copy/xor message into array */
for (i=0; i < (ctx->octets_in_buffer+3)/4; i++) for (i=0; i < (ctx->octets_in_buffer+3)/4; i++)
W[i] = be32_to_cpu(ctx->M[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; W[i] = 0x80000000;
break; break;
} }
/* zeroize remaining words */ /* zeroize remaining words */
for (i++ ; i < 15; i++) for (i++ ; i < 15; i++)
W[i] = 0x0; W[i] = 0x0;
@ -299,7 +299,8 @@ sha1_final(sha1_ctx_t *ctx, uint32_t *output) {
else if (ctx->octets_in_buffer < 60) else if (ctx->octets_in_buffer < 60)
W[15] = 0x0; 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]; TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
W[t] = S1(TEMP); W[t] = S1(TEMP);
} }

View File

@ -0,0 +1 @@
config.h

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,24 +50,30 @@
#include "datatypes.h" #include "datatypes.h"
#include "gf2_8.h" #include "gf2_8.h"
#include "err.h"
/* aes internals */ /* 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 void
aes_expand_encryption_key(const v128_t *key, aes_encrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key);
aes_expanded_key_t expanded_key);
void void
aes_expand_decryption_key(const v128_t *key, aes_decrypt(v128_t *plaintext, const aes_expanded_key_t *exp_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);
#if 0 #if 0
/* /*

View File

@ -31,7 +31,7 @@ aes_cbc_encrypt(aes_cbc_ctx_t *c,
err_status_t 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,
cipher_direction_t dir); int key_len, cipher_direction_t dir);
err_status_t err_status_t
aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv); aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv);

View File

@ -19,13 +19,14 @@ typedef struct {
v128_t offset; /* initial offset value */ v128_t offset; /* initial offset value */
v128_t keystream_buffer; /* buffers bytes of keystream */ v128_t keystream_buffer; /* buffers bytes of keystream */
aes_expanded_key_t expanded_key; /* the cipher key */ 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; } aes_icm_ctx_t;
err_status_t err_status_t
aes_icm_context_init(aes_icm_ctx_t *c, aes_icm_context_init(aes_icm_ctx_t *c,
const unsigned char *key); const unsigned char *key,
int key_len);
err_status_t err_status_t
aes_icm_set_iv(aes_icm_ctx_t *c, void *iv); aes_icm_set_iv(aes_icm_ctx_t *c, void *iv);

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -48,6 +48,8 @@
#include "datatypes.h" #include "datatypes.h"
#include "err.h" /* error codes */ #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_type_t *auth_type_pointer;
typedef struct auth_t *auth_pointer_t; typedef struct auth_t *auth_pointer_t;
@ -129,6 +131,7 @@ typedef struct auth_type_t {
int ref_count; int ref_count;
auth_test_case_t *test_data; auth_test_case_t *test_data;
debug_module_t *debug; debug_module_t *debug;
auth_type_id_t id;
} auth_type_t; } auth_type_t;
typedef struct auth_t { typedef struct auth_t {
@ -148,6 +151,15 @@ typedef struct auth_t {
err_status_t err_status_t
auth_type_self_test(const auth_type_t *at); 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 * auth_type_get_ref_count(at) returns the reference count (the number
* of instantiations) of the auth_type_t at * of instantiations) of the auth_type_t at

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -49,6 +49,8 @@
#include "datatypes.h" #include "datatypes.h"
#include "rdbx.h" /* for xtd_seq_num_t */ #include "rdbx.h" /* for xtd_seq_num_t */
#include "err.h" /* for error codes */ #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) 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 */ /* 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); (void *state, uint8_t *buffer, unsigned int *octets_to_decrypt);
/* /*
* a cipher_set_nonce_seq_func_t function sets both the nonce * a cipher_set_iv_func_t function sets the current initialization vector
* and the extended sequence number
*/ */
typedef err_status_t (*cipher_set_iv_func_t) typedef err_status_t (*cipher_set_iv_func_t)
@ -147,6 +148,7 @@ typedef struct cipher_type_t {
int ref_count; int ref_count;
cipher_test_case_t *test_data; cipher_test_case_t *test_data;
debug_module_t *debug; debug_module_t *debug;
cipher_type_id_t id;
} cipher_type_t; } cipher_type_t;
/* /*
@ -169,7 +171,7 @@ typedef struct cipher_t {
#define cipher_dealloc(c) (((c)->type)->dealloc(c)) #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) \ #define cipher_encrypt(c, buf, len) \
(((c)->type)->encrypt(((c)->state), (buf), (len))) (((c)->type)->encrypt(((c)->state), (buf), (len)))
@ -178,7 +180,7 @@ typedef struct cipher_t {
(((c)->type)->decrypt(((c)->state), (buf), (len))) (((c)->type)->decrypt(((c)->state), (buf), (len)))
#define cipher_set_iv(c, n) \ #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_no_such_op)
err_status_t err_status_t
@ -201,6 +203,16 @@ err_status_t
cipher_type_self_test(const cipher_type_t *ct); 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 * cipher_bits_per_second(c, l, t) computes (and estimate of) the
* number of bits that a cipher implementation can encrypt in a second * number of bits that a cipher implementation can encrypt in a second

View File

@ -10,7 +10,33 @@
#ifndef CRYPTO_H #ifndef CRYPTO_H
#define 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 */ #endif /* CRYPTO_H */

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -55,7 +55,7 @@
#include "err.h" #include "err.h"
#include "crypto_types.h" #include "crypto_types.h"
#include "key.h" #include "key.h"
#include "crypto.h"
/* /*
* crypto_kernel_state_t defines the possible states: * crypto_kernel_state_t defines the possible states:
@ -69,36 +69,6 @@ typedef enum {
crypto_kernel_state_secure crypto_kernel_state_secure
} crypto_kernel_state_t; } 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 * 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 err_status_t
crypto_kernel_load_auth_type(auth_type_t *ct, auth_type_id_t id); 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 err_status_t
crypto_kernel_load_debug_module(debug_module_t *new_dm); crypto_kernel_load_debug_module(debug_module_t *new_dm);

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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); 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 */ #endif /* MATH_H */

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -97,12 +97,19 @@
#define NULL_CIPHER 0 #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. * AES 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. * 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 * @brief SEAL 3.0
@ -113,19 +120,26 @@
#define SEAL 2 #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. * AES CBC is the AES Cipher Block Chaining mode.
* This cipher uses a 16-octet key and a 30-octet offset (or salt) value. * 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. * @brief Strongest available cipher.
* *
* This identifier resolves to the strongest cipher type available. * This identifier resolves to the strongest cipher type available.
*/ */
#define STRONGHOLD_CIPHER AES_128_ICM #define STRONGHOLD_CIPHER AES_ICM
/** /**
* @} * @}

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -63,6 +63,7 @@
# endif # endif
#endif #endif
/* if DATATYPES_USE_MACROS is defined, then little functions are macros */ /* if DATATYPES_USE_MACROS is defined, then little functions are macros */
#define DATATYPES_USE_MACROS #define DATATYPES_USE_MACROS
@ -154,10 +155,10 @@ void
v128_copy_octet_string(v128_t *x, const uint8_t s[16]); v128_copy_octet_string(v128_t *x, const uint8_t s[16]);
void void
v128_left_shift(v128_t *x, int index); v128_left_shift(v128_t *x, int shift_index);
void 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 * 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 */ #ifdef DATATYPES_USE_MACROS /* little functions are really macros */
#define v128_set_to_zero(z) _v128_set_to_zero(z) #define v128_set_to_zero(z) _v128_set_to_zero(z)
#define v128_copy(z, x) _v128_copy(z, x) #define v128_copy(z, x) _v128_copy(z, x)
#define v128_xor(z, x, y) _v128_xor(z, x, y) #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)) # define be64_to_cpu(x) bswap_64((x))
#else #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 # ifdef HAVE_NETINET_IN_H
# include <netinet/in.h> # include <netinet/in.h>
# elif defined HAVE_WINSOCK2_H # elif defined HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
# endif # endif
# define be32_to_cpu(x) ntohl((x)) # define be32_to_cpu(x) ntohl((x))
# endif /* HAVE_X86 */
static inline uint64_t be64_to_cpu(uint64_t v) {
# ifdef NO_64BIT_MATH # ifdef NO_64BIT_MATH
/* use the make64 functions to do 64-bit 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 # 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 # endif
return v;
}
#endif /* ! SRTP_KERNEL_LINUX */ #endif /* ! SRTP_KERNEL_LINUX */
#endif /* WORDS_BIGENDIAN */ #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 */ #endif /* _DATATYPES_H */

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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_parse_err = 21, /**< error pasring data */
err_status_encode_err = 22, /**< error encoding data */ err_status_encode_err = 22, /**< error encoding data */
err_status_semaphore_err = 23,/**< error while using semaphores */ 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; } err_status_t;
/** /**

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -9,7 +9,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 addresses. This is required for processors that do not allow unaligned
loads. */ loads. */
#ifdef ALIGNMENT_32BIT_REQUIRED #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 #ifdef WORDS_BIGENDIAN
#define PUT_32(addr,value) \ #define PUT_32(addr,value) \
{ \ { \

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -8,7 +8,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -62,11 +62,11 @@ typedef struct {
*/ */
err_status_t 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 err_status_t
null_cipher_set_segment(null_cipher_ctx_t *c, null_cipher_set_segment(null_cipher_ctx_t *c,
unsigned long index); unsigned long segment_index);
err_status_t err_status_t
null_cipher_encrypt(null_cipher_ctx_t *c, null_cipher_encrypt(null_cipher_ctx_t *c,

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -49,7 +49,7 @@ rdb_init(rdb_t *rdb);
*/ */
err_status_t 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 * rdb_add_index
@ -61,7 +61,7 @@ rdb_check(const rdb_t *rdb, uint32_t index);
*/ */
err_status_t 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 * the functions rdb_increment() and rdb_get_value() are for use by

View File

@ -46,19 +46,29 @@ typedef uint64_t xtd_seq_num_t;
typedef struct { typedef struct {
xtd_seq_num_t index; xtd_seq_num_t index;
v128_t bitmask; bitvector_t bitmask;
} rdbx_t; } rdbx_t;
/* /*
* rdbx_init(rdbx_ptr) * rdbx_init(rdbx_ptr, ws)
* *
* initializes the rdbx pointed to by its argument, setting the * initializes the rdbx pointed to by its argument with the window size ws,
* rollover counter and sequence number to zero * setting the rollover counter and sequence number to zero
*/ */
err_status_t 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 err_status_t
rdbx_add_index(rdbx_t *rdbx, int delta); 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 * xtd_seq_num_t functions - these are *internal* functions of rdbx, and
* shouldn't be used to manipulate rdbx internal values. use the rdbx * shouldn't be used to manipulate rdbx internal values. use the rdbx
* api instead! * api instead!
*/ */
/*
* rdbx_get_ws(rdbx_ptr)
*
* gets the window size which was used to initialize the rdbx
*/
unsigned long
rdbx_get_window_size(const rdbx_t *rdbx);
/* index_init(&pi) initializes a packet index pi (sets it to zero) */ /* index_init(&pi) initializes a packet index pi (sets it to zero) */

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright(c) 2001-2005, Cisco Systems, Inc. * Copyright(c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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); status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER);
if (status) if (status)
return 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) if (status)
return 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) if (status)
return status; return status;
@ -297,15 +297,19 @@ crypto_kernel_shutdown() {
return err_status_ok; return err_status_ok;
} }
err_status_t static inline err_status_t
crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { crypto_kernel_do_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id,
kernel_cipher_type_t *ctype, *new; int replace) {
kernel_cipher_type_t *ctype, *new_ctype;
err_status_t status; err_status_t status;
/* defensive coding */ /* defensive coding */
if (new_ct == NULL) if (new_ct == NULL)
return err_status_bad_param; return err_status_bad_param;
if (new_ct->id != id)
return err_status_bad_param;
/* check cipher type by running self-test */ /* check cipher type by running self-test */
status = cipher_type_self_test(new_ct); status = cipher_type_self_test(new_ct);
if (status) { 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 */ /* walk down list, checking if this type is in the list already */
ctype = crypto_kernel.cipher_type_list; ctype = crypto_kernel.cipher_type_list;
while (ctype != NULL) { 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; return err_status_bad_param;
ctype = ctype->next; 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 */ /* allocate memory */
new = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t)); new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t));
if (new == NULL) if (new_ctype == NULL)
return err_status_alloc_fail; 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 */ /* set fields */
new->cipher_type = new_ct; new_ctype->cipher_type = new_ct;
new->id = id; new_ctype->id = id;
new->next = crypto_kernel.cipher_type_list;
/* set head of list to new cipher type */
crypto_kernel.cipher_type_list = new;
/* load debug module, if there is one present */ /* load debug module, if there is one present */
if (new_ct->debug != NULL) 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 err_status_t
crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) {
kernel_auth_type_t *atype, *new; 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; err_status_t status;
/* defensive coding */ /* defensive coding */
if (new_at == NULL) if (new_at == NULL)
return err_status_bad_param; return err_status_bad_param;
if (new_at->id != id)
return err_status_bad_param;
/* check auth type by running self-test */ /* check auth type by running self-test */
status = auth_type_self_test(new_at); status = auth_type_self_test(new_at);
if (status) { 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 */ /* walk down list, checking if this type is in the list already */
atype = crypto_kernel.auth_type_list; atype = crypto_kernel.auth_type_list;
while (atype != NULL) { 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; return err_status_bad_param;
atype = atype->next; atype = atype->next;
} }
/* put new_at at the head of the list */ /* if not found, put new_at at the head of the list */
/* allocate memory */ if (atype == NULL) {
new = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t)); /* allocate memory */
if (new == NULL) new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t));
return err_status_alloc_fail; 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 */ /* set fields */
new->auth_type = new_at; new_atype->auth_type = new_at;
new->id = id; new_atype->id = id;
new->next = crypto_kernel.auth_type_list;
/* set head of list to new auth type */
crypto_kernel.auth_type_list = new;
/* load debug module, if there is one present */ /* load debug module, if there is one present */
if (new_at->debug != NULL) 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 * cipher_type_t *
crypto_kernel_get_cipher_type(cipher_type_id_t id) { crypto_kernel_get_cipher_type(cipher_type_id_t id) {

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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" #include "err.h"
#ifdef ERR_REPORTING_SYSLOG #ifdef ERR_REPORTING_SYSLOG

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -9,7 +9,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 */ /* 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 uint8_t
nibble_to_hex_char(uint8_t nibble) { nibble_to_hex_char(uint8_t nibble) {
@ -106,7 +106,7 @@ nibble_to_hex_char(uint8_t nibble) {
char * char *
octet_string_hex_string(const void *s, int length) { octet_string_hex_string(const void *s, int length) {
const uint8_t *str = s; const uint8_t *str = (const uint8_t *)s;
int i; int i;
/* double length, since one octet takes two hex characters */ /* 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; return bit_string;
} }
inline int static inline int
hex_char_to_nibble(uint8_t c) { hex_char_to_nibble(uint8_t c) {
switch(c) { switch(c) {
case ('0'): return 0x0; case ('0'): return 0x0;
@ -149,9 +149,10 @@ hex_char_to_nibble(uint8_t c) {
case ('E'): return 0xe; case ('E'): return 0xe;
case ('f'): return 0xf; case ('f'): return 0xf;
case ('F'): return 0xf; case ('F'): return 0xf;
default: return -1; /* this flags an error */
} }
/* this flags an error */ /* NOTREACHED */
return -1; return -1; /* this keeps compilers from complaining */
} }
int int
@ -178,7 +179,7 @@ hex_string_to_octet_string(char *raw, char *hex, int len) {
tmp = hex_char_to_nibble(hex[0]); tmp = hex_char_to_nibble(hex[0]);
if (tmp == -1) if (tmp == -1)
return hex_len; return hex_len;
x = (uint8_t)(tmp << 4); x = (tmp << 4);
hex_len++; hex_len++;
tmp = hex_char_to_nibble(hex[1]); tmp = hex_char_to_nibble(hex[1]);
if (tmp == -1) if (tmp == -1)
@ -206,16 +207,16 @@ v128_hex_string(v128_t *x) {
char * char *
v128_bit_string(v128_t *x) { v128_bit_string(v128_t *x) {
int j, index; int j, i;
uint32_t mask; uint32_t mask;
for (j=index=0; j < 4; j++) { for (j=i=0; j < 4; j++) {
for (mask=0x80000000; mask > 0; mask >>= 1) { for (mask=0x80000000; mask > 0; mask >>= 1) {
if (x->v32[j] & mask) if (x->v32[j] & mask)
bit_string[index] = '1'; bit_string[i] = '1';
else else
bit_string[index] = '0'; bit_string[i] = '0';
++index; ++i;
} }
} }
bit_string[128] = 0; /* null terminate string */ 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 */ #endif /* DATATYPES_USE_MACROS */
void void
v128_right_shift(v128_t *x, int index) { v128_right_shift(v128_t *x, int shift) {
const int base_index = index >> 5; const int base_index = shift >> 5;
const int bit_index = index & 31; const int bit_index = shift & 31;
int i, from; int i, from;
uint32_t b; uint32_t b;
if (index > 127) { if (shift > 127) {
v128_set_to_zero(x); v128_set_to_zero(x);
return; return;
} }
@ -360,12 +361,12 @@ v128_right_shift(v128_t *x, int index) {
} }
void void
v128_left_shift(v128_t *x, int index) { v128_left_shift(v128_t *x, int shift) {
int i; int i;
const int base_index = index >> 5; const int base_index = shift >> 5;
const int bit_index = index & 31; const int bit_index = shift & 31;
if (index > 127) { if (shift > 127) {
v128_set_to_zero(x); v128_set_to_zero(x);
return; 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 int
octet_string_is_eq(uint8_t *a, uint8_t *b, int len) { 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; return 63;
case '=': case '=':
return 64; return 64;
default:
break;
} }
return -1; return -1;
} }
@ -583,7 +704,7 @@ base64_string_to_octet_string(char *raw, char *base64, int len) {
tmp = base64_char_to_sextet(base64[0]); tmp = base64_char_to_sextet(base64[0]);
if (tmp == -1) if (tmp == -1)
return base64_len; return base64_len;
x = (uint8_t)(tmp << 6); x = (tmp << 6);
base64_len++; base64_len++;
tmp = base64_char_to_sextet(base64[1]); tmp = base64_char_to_sextet(base64[1]);
if (tmp == -1) if (tmp == -1)

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 */ /* 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_multiply(gf2_8 x, gf2_8 y) {
gf2_8 z = 0; gf2_8 z = 0;

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,7 +43,6 @@
*/ */
#include "crypto_math.h" #include "crypto_math.h"
#include <stdlib.h> /* malloc() used in bitvector_alloc */
int int
octet_weight[256] = { octet_weight[256] = {
@ -173,7 +172,7 @@ v32_weight(v32_t a) {
return wt; return wt;
} }
inline unsigned char unsigned char
v32_distance(v32_t x, v32_t y) { v32_distance(v32_t x, v32_t y) {
x.value ^= y.value; x.value ^= y.value;
return v32_weight(x); return v32_weight(x);
@ -192,7 +191,7 @@ v32_dot_product(v32_t a, v32_t b) {
#define MAX_STRING_LENGTH 1024 #define MAX_STRING_LENGTH 1024
static char bit_string[MAX_STRING_LENGTH]; char bit_string[MAX_STRING_LENGTH];
char * char *
octet_bit_string(uint8_t x) { 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; return b;
} }
inline void void
v16_copy_octet_string(v16_t *x, const uint8_t s[2]) { v16_copy_octet_string(v16_t *x, const uint8_t s[2]) {
x->v8[0] = s[0]; x->v8[0] = s[0];
x->v8[1] = s[1]; x->v8[1] = s[1];
} }
inline void void
v32_copy_octet_string(v32_t *x, const uint8_t s[4]) { v32_copy_octet_string(v32_t *x, const uint8_t s[4]) {
x->v8[0] = s[0]; x->v8[0] = s[0];
x->v8[1] = s[1]; 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]; x->v8[3] = s[3];
} }
inline void void
v64_copy_octet_string(v64_t *x, const uint8_t s[8]) { v64_copy_octet_string(v64_t *x, const uint8_t s[8]) {
x->v8[0] = s[0]; x->v8[0] = s[0];
x->v8[1] = s[1]; x->v8[1] = s[1];
@ -632,7 +631,7 @@ v128_set_bit_to(v128_t *x, int i, int y){
#endif /* DATATYPES_USE_MACROS */ #endif /* DATATYPES_USE_MACROS */
inline void static inline void
v128_left_shift2(v128_t *x, int num_bits) { v128_left_shift2(v128_t *x, int num_bits) {
int i; int i;
int word_shift = num_bits >> 5; int word_shift = num_bits >> 5;
@ -773,165 +772,6 @@ octet_string_set_to_zero(uint8_t *s, int len) {
} }
/* functions manipulating bit_vector_t */
#define BITVECTOR_MAX_WORDS 5
int
bitvector_alloc(bitvector_t *v, unsigned long length) {
unsigned long l = (length + bytes_per_word - 1) / bytes_per_word;
int i;
/* allocate memory, then set parameters */
if (l > BITVECTOR_MAX_WORDS)
return -1;
else
l = BITVECTOR_MAX_WORDS;
v->word = malloc(l);
if (v->word == NULL)
return -1;
v->length = length;
/* initialize bitvector to zero */
for (i=0; i < (length >> 5); i++) {
v->word = 0;
}
return 0;
}
void
bitvector_set_bit(bitvector_t *v, int bit_index) {
v->word[(bit_index >> 5)] |= (1 << (bit_index & 31));
}
int
bitvector_get_bit(const bitvector_t *v, int bit_index) {
return ((v->word[(bit_index >> 5)]) >> (bit_index & 31)) & 1;
}
#include <stdio.h>
int
bitvector_print_hex(const bitvector_t *v, FILE *stream) {
int i;
int m = v->length >> 5;
int n = v->length & 31;
char string[9];
uint32_t tmp;
/* if length isn't a multiple of four, we can't hex_print */
if (n & 3)
return -1;
/* if the length is zero, do nothing */
if (v->length == 0)
return 0;
/*
* loop over words from most significant to least significant -
*/
for (i=m; i > 0; i++) {
char *str = string + 7;
tmp = v->word[i];
/* null terminate string */
string[8] = 0;
/* loop over nibbles */
*str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4;
*str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4;
*str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4;
*str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4;
*str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4;
*str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4;
*str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4;
*str-- = nibble_to_hex_char(tmp & 0xf);
/* now print stream */
fprintf(stream, string);
}
return 0;
}
int
hex_string_length(char *s) {
int count = 0;
/* ignore leading zeros */
while ((*s != 0) && *s == '0')
s++;
/* count remaining characters */
while (*s != 0) {
if (hex_char_to_nibble(*s++) == -1)
return -1;
count++;
}
return count;
}
int
bitvector_set_from_hex(bitvector_t *v, char *string) {
int num_hex_chars, m, n, i, j;
uint32_t tmp;
num_hex_chars = hex_string_length(string);
if (num_hex_chars == -1)
return -1;
/* set length */
v->length = num_hex_chars * 4;
/*
* at this point, we should subtract away a bit if the high
* bit of the first character is zero, but we ignore that
* for now and assume that we're four-bit aligned - DAM
*/
m = num_hex_chars / 8; /* number of words */
n = num_hex_chars % 8; /* number of nibbles in last word */
/* if the length is greater than the bitvector, return an error */
if (m > BITVECTOR_MAX_WORDS)
return -1;
/*
* loop over words from most significant - first word is a special
* case
*/
if (n) {
tmp = 0;
for (i=0; i < n; i++) {
tmp = hex_char_to_nibble(*string++);
tmp <<= 4;
}
v->word[m] = tmp;
}
/* now loop over the rest of the words */
for (i=m-1; i >= 0; i--) {
tmp = 0;
for (j=0; j < 8; j++) {
tmp = hex_char_to_nibble(*string++);
tmp <<= 4;
}
v->word[i] = tmp;
}
return 0;
}
/* functions below not yet tested! */ /* functions below not yet tested! */

View File

@ -28,7 +28,7 @@ stat_test_monobit(uint8_t *data) {
ones_count = 0; ones_count = 0;
while (data < data_end) { while (data < data_end) {
ones_count = (uint16_t)(ones_count + octet_get_weight(*data)); ones_count += octet_get_weight(*data);
data++; data++;
} }
@ -83,7 +83,7 @@ stat_test_runs(uint8_t *data) {
uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 }; uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 }; uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 }; uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
int16_t state = 0; int state = 0;
uint16_t mask; uint16_t mask;
int i; 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 gaps[6] = { 0, 0, 0, 0, 0, 0 };
uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 }; uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 }; uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
int16_t state = 0; int state = 0;
uint16_t mask; uint16_t mask;
/* counters for monobit, poker, and runs tests are initialized above */ /* counters for monobit, poker, and runs tests are initialized above */

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -70,19 +70,19 @@ rdb_init(rdb_t *rdb) {
*/ */
err_status_t 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 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; return err_status_ok;
/* if the index appears before the window, its bad */ /* if the index appears before the window, its bad */
if (index < rdb->window_start) if (p_index < rdb->window_start)
return err_status_fail; return err_status_replay_old;
/* otherwise, the index appears within the window, so check the bitmask */ /* otherwise, the index appears within the window, so check the bitmask */
if (v128_get_bit(&rdb->bitmask, (index - rdb->window_start)) == 1) if (v128_get_bit(&rdb->bitmask, (p_index - rdb->window_start)) == 1)
return err_status_fail; return err_status_replay_fail;
/* otherwise, the index is okay */ /* otherwise, the index is okay */
return err_status_ok; return err_status_ok;
@ -98,15 +98,15 @@ rdb_check(const rdb_t *rdb, uint32_t index) {
*/ */
err_status_t err_status_t
rdb_add_index(rdb_t *rdb, uint32_t index) { rdb_add_index(rdb_t *rdb, uint32_t p_index) {
int delta; 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 (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); v128_set_bit(&rdb->bitmask, delta);
} else { } else {
@ -115,7 +115,7 @@ rdb_add_index(rdb_t *rdb, uint32_t index) {
/* shift the window forward by delta bits*/ /* shift the window forward by delta bits*/
v128_left_shift(&rdb->bitmask, delta); 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; rdb->window_start += delta;
} }

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -45,18 +45,17 @@
#include "rdbx.h" #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 * 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 * where v is chosen from the set { ROC-1, ROC, ROC+1 } such that i is
* closest to the value 65,536 * r + s_l. If the value r+1 is used, * 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 * then the rollover counter r in the cryptographic context is
* incremented by one (if the packet containing s is authentic). * 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 (local_seq < seq_num_median) {
if (s - local_seq > seq_num_median) { if (s - local_seq > seq_num_median) {
guess_roc = local_roc - 1; guess_roc = local_roc - 1;
difference = seq_num_max - s + local_seq; difference = s - local_seq - seq_num_max;
} else { } else {
guess_roc = local_roc; guess_roc = local_roc;
difference = s - local_seq; difference = s - local_seq;
} }
} else { } else {
if (local_seq - seq_num_median > s) { if (local_seq - seq_num_median > s) {
guess_roc = local_roc+1; guess_roc = local_roc + 1;
difference = seq_num_max - local_seq + s; difference = s - local_seq + seq_num_max;
} else { } else {
difference = s - local_seq;
guess_roc = local_roc; guess_roc = local_roc;
difference = s - local_seq;
} }
} }
guess_seq = s; 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 err_status_t
rdbx_init(rdbx_t *rdbx) { rdbx_init(rdbx_t *rdbx, unsigned long ws) {
v128_set_to_zero(&rdbx->bitmask); if (ws == 0)
return err_status_bad_param;
if (bitvector_alloc(&rdbx->bitmask, ws) != 0)
return err_status_alloc_fail;
index_init(&rdbx->index); index_init(&rdbx->index);
return err_status_ok; 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 * 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 */ if (delta > 0) { /* if delta is positive, it's good */
return err_status_ok; 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 */ /* if delta is lower than the bitmask, it's bad */
return err_status_replay_old; return err_status_replay_old;
} else if (v128_get_bit(&rdbx->bitmask, } else if (bitvector_get_bit(&rdbx->bitmask,
rdbx_high_bit_in_bitmask + delta) == 1) { (int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta) == 1) {
/* delta is within the window, so check the bitmask */ /* delta is within the window, so check the bitmask */
return err_status_replay_fail; return err_status_replay_fail;
} }
@ -229,12 +292,12 @@ rdbx_add_index(rdbx_t *rdbx, int delta) {
if (delta > 0) { if (delta > 0) {
/* shift forward by delta */ /* shift forward by delta */
index_advance(&rdbx->index, (sequence_number_t)delta); index_advance(&rdbx->index, delta);
v128_left_shift(&rdbx->bitmask, delta); bitvector_left_shift(&rdbx->bitmask, delta);
v128_set_bit(&rdbx->bitmask, 127); bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) - 1);
} else { } else {
/* delta is in window, so flip bit in bitmask */ /* delta is in window */
v128_set_bit(&rdbx->bitmask, -delta); bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) -1 + delta);
} }
/* note that we need not consider the case that delta == 0 */ /* note that we need not consider the case that delta == 0 */

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -47,9 +47,6 @@
#include "ut_sim.h" #include "ut_sim.h"
#ifdef _MSC_VER
#pragma warning(disable:4100)
#endif
int int
ut_compar(const void *a, const void *b) { ut_compar(const void *a, const void *b) {

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -47,7 +47,7 @@
/* single, global prng structure */ /* single, global prng structure */
static ctr_prng_t ctr_prng; ctr_prng_t ctr_prng;
err_status_t err_status_t
ctr_prng_init(rand_source_func_t random_source) { ctr_prng_init(rand_source_func_t random_source) {
@ -66,7 +66,7 @@ ctr_prng_init(rand_source_func_t random_source) {
return status; return status;
/* initialize aes ctr context with random key */ /* 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) if (status)
return status; return status;
@ -92,7 +92,7 @@ ctr_prng_get_octet_string(void *dest, uint32_t len) {
/* /*
* write prng output * 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) if (status)
return status; return status;

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -47,11 +47,11 @@
/* single, global prng structure */ /* single, global prng structure */
static x917_prng_t x917_prng; x917_prng_t x917_prng;
err_status_t err_status_t
x917_prng_init(rand_source_func_t random_source) { x917_prng_init(rand_source_func_t random_source) {
v128_t tmp_key; uint8_t tmp_key[16];
err_status_t status; err_status_t status;
/* initialize output count to zero */ /* initialize output count to zero */
@ -61,12 +61,12 @@ x917_prng_init(rand_source_func_t random_source) {
x917_prng.rand = random_source; x917_prng.rand = random_source;
/* initialize secret key from random source */ /* initialize secret key from random source */
status = random_source((uint8_t *)&tmp_key, 16); status = random_source(tmp_key, 16);
if (status) if (status)
return status; return status;
/* expand aes key */ /* 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 */ /* initialize prng state from random source */
status = x917_prng.rand((uint8_t *)&x917_prng.state, 16); 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) { x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
uint32_t t; uint32_t t;
v128_t buffer; v128_t buffer;
int i, tail_len; uint32_t i, tail_len;
err_status_t status; err_status_t status;
/* /*
@ -99,7 +99,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
t = (uint32_t)time(NULL); t = (uint32_t)time(NULL);
/* loop until we have output enough data */ /* 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 */ /* exor time into state */
x917_prng.state.v32[0] ^= t; 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); v128_copy(&buffer, &x917_prng.state);
/* apply aes to buffer */ /* apply aes to buffer */
aes_encrypt(&buffer, x917_prng.key); aes_encrypt(&buffer, &x917_prng.key);
/* write data to output */ /* write data to output */
*dest++ = buffer.v8[0]; *dest++ = buffer.v8[0];
@ -132,7 +132,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) {
buffer.v32[0] ^= t; buffer.v32[0] ^= t;
/* encrypt buffer */ /* encrypt buffer */
aes_encrypt(&buffer, x917_prng.key); aes_encrypt(&buffer, &x917_prng.key);
/* copy buffer into state */ /* copy buffer into state */
v128_copy(&x917_prng.state, &buffer); 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); v128_copy(&buffer, &x917_prng.state);
/* apply aes to buffer */ /* apply aes to buffer */
aes_encrypt(&buffer, x917_prng.key); aes_encrypt(&buffer, &x917_prng.key);
/* write data to output */ /* write data to output */
for (i=0; i < tail_len; i++) { 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; buffer.v32[0] ^= t;
/* encrypt buffer */ /* encrypt buffer */
aes_encrypt(&buffer, x917_prng.key); aes_encrypt(&buffer, &x917_prng.key);
/* copy buffer into state */ /* copy buffer into state */
v128_copy(&x917_prng.state, &buffer); v128_copy(&x917_prng.state, &buffer);

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,18 +43,36 @@
*/ */
#include "config.h" #include "config.h"
#include "rand_source.h"
#ifdef DEV_URANDOM #ifdef DEV_URANDOM
# include <fcntl.h> /* for open() */ # include <fcntl.h> /* for open() */
# include <unistd.h> /* for close() */ # include <unistd.h> /* for close() */
#elif defined(HAVE_RAND_S)
# define _CRT_RAND_S
# include <stdlib.h>
#else #else
# include <stdio.h> # include <stdio.h>
#endif #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 err_status_t
@ -68,10 +86,12 @@ rand_source_init(void) {
dev_random_fdes = open(DEV_URANDOM, O_RDONLY); dev_random_fdes = open(DEV_URANDOM, O_RDONLY);
if (dev_random_fdes < 0) if (dev_random_fdes < 0)
return err_status_init_fail; return err_status_init_fail;
#elif defined(HAVE_RAND_S)
dev_random_fdes = RAND_SOURCE_READY;
#else #else
/* no random source available; let the user know */ /* no random source available; let the user know */
fprintf(stderr, "WARNING: no real random source present!\n"); fprintf(stderr, "WARNING: no real random source present!\n");
dev_random_fdes = 17; dev_random_fdes = RAND_SOURCE_READY;
#endif #endif
return err_status_ok; return err_status_ok;
} }
@ -85,25 +105,45 @@ rand_source_get_octet_string(void *dest, uint32_t len) {
* written * written
*/ */
#ifdef DEV_URANDOM #ifdef DEV_URANDOM
if (read(dev_random_fdes, dest, len) != len) uint8_t *dst = (uint8_t *)dest;
return err_status_fail; 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 #else
/* Generic C-library (rand()) version */ /* Generic C-library (rand()) version */
/* This is a random source of last resort */ /* This is a random source of last resort */
uint8_t *dst = dest; uint8_t *dst = (uint8_t *)dest;
while (len) while (len)
{ {
int val = rand(); int val = rand();
/* rand() returns 0-32767 (ugh) */ /* rand() returns 0-32767 (ugh) */
/* Is this a good enough way to get random bytes? /* Is this a good enough way to get random bytes?
It is if it passes FIPS-140... */ It is if it passes FIPS-140... */
*dst++ = (uint8_t)(val & 0xff); *dst++ = val & 0xff;
len--; len--;
} }
#endif #endif
return err_status_ok; return err_status_ok;
} }
err_status_t err_status_t
rand_source_deinit(void) { rand_source_deinit(void) {
if (dev_random_fdes < 0) if (dev_random_fdes < 0)
@ -112,7 +152,7 @@ rand_source_deinit(void) {
#ifdef DEV_URANDOM #ifdef DEV_URANDOM
close(dev_random_fdes); close(dev_random_fdes);
#endif #endif
dev_random_fdes = -1; dev_random_fdes = RAND_SOURCE_NOT_READY;
return err_status_ok; return err_status_ok;
} }

View File

@ -0,0 +1,8 @@
aes_calc
cipher_driver
datatypes_driver
env
kernel_driver
rand_gen
sha1_driver
stat_driver

BIN
libs/srtp/crypto/test/aes_calc Executable file

Binary file not shown.

View File

@ -28,14 +28,16 @@ usage(char *prog_name) {
exit(255); exit(255);
} }
#define AES_KEY_LEN 16 #define AES_MAX_KEY_LEN 32
int int
main (int argc, char *argv[]) { 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; aes_expanded_key_t exp_key;
int len; int key_len, len;
int verbose; int verbose;
err_status_t status;
if (argc == 3) { if (argc == 3) {
/* we're not in verbose mode */ /* we're not in verbose mode */
@ -54,22 +56,23 @@ main (int argc, char *argv[]) {
} }
/* read in key, checking length */ /* read in key, checking length */
if (strlen(argv[1]) > AES_KEY_LEN*2) { if (strlen(argv[1]) > AES_MAX_KEY_LEN*2) {
fprintf(stderr, fprintf(stderr,
"error: too many digits in key " "error: too many digits in key "
"(should be %d hexadecimal digits, found %u)\n", "(should be at most %d hexadecimal digits, found %u)\n",
AES_KEY_LEN*2, (unsigned)strlen(argv[1])); AES_MAX_KEY_LEN*2, (unsigned)strlen(argv[1]));
exit(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 */ /* check that hex string is the right length */
if (len < AES_KEY_LEN*2) { if (len != 32 && len != 48 && len != 64) {
fprintf(stderr, fprintf(stderr,
"error: too few digits in key " "error: bad number of digits in key "
"(should be %d hexadecimal digits, found %d)\n", "(should be 32/48/64 hexadecimal digits, found %d)\n",
AES_KEY_LEN*2, len); len);
exit(1); exit(1);
} }
key_len = len/2;
/* read in plaintext, checking length */ /* read in plaintext, checking length */
if (strlen(argv[2]) > 16*2) { if (strlen(argv[2]) > 16*2) {
@ -95,13 +98,18 @@ main (int argc, char *argv[]) {
} }
/* encrypt plaintext */ /* 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 */ /* write ciphertext to output */
if (verbose) { 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("ciphertext:\t");
} }
printf("%s\n", v128_hex_string(&data)); printf("%s\n", v128_hex_string(&data));

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -120,10 +120,13 @@ int
main(int argc, char *argv[]) { main(int argc, char *argv[]) {
cipher_t *c = NULL; cipher_t *c = NULL;
err_status_t status; err_status_t status;
unsigned char test_key[20] = { unsigned char test_key[48] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 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; int q;
unsigned do_timing_test = 0; 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) for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
cipher_driver_test_array_throughput(&aes_icm, 30, num_cipher); 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) for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
cipher_driver_test_array_throughput(&aes_cbc, 16, num_cipher); 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) { if (do_validation) {
@ -196,7 +204,7 @@ main(int argc, char *argv[]) {
check_status(status); 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); status = cipher_type_alloc(&aes_icm, &c, 30);
if (status) { if (status) {
fprintf(stderr, "error: can't allocate cipher\n"); fprintf(stderr, "error: can't allocate cipher\n");
@ -216,6 +224,27 @@ main(int argc, char *argv[]) {
status = cipher_dealloc(c); status = cipher_dealloc(c);
check_status(status); 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; return 0;
} }
@ -225,9 +254,9 @@ cipher_driver_test_throughput(cipher_t *c) {
int i; int i;
int min_enc_len = 32; int min_enc_len = 32;
int max_enc_len = 2048; /* should be a power of two */ 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); fflush(stdout);
for (i=min_enc_len; i <= max_enc_len; i = i * 2) for (i=min_enc_len; i <= max_enc_len; i = i * 2)
printf("msg len: %d\tgigabits per second: %f\n", 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; err_status_t status;
uint8_t *key; uint8_t *key;
cipher_t **cipher_array; 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 */ /* allocate array of pointers to ciphers */
cipher_array = (cipher_t **) malloc(sizeof(cipher_t *) * num_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; *ca = cipher_array;
/* allocate key */ /* allocate key */
key = crypto_alloc(klen); key = crypto_alloc(klen_pad);
if (key == NULL) { if (key == NULL) {
free(cipher_array); free(cipher_array);
return err_status_alloc_fail; 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 */ /* generate random key and initialize cipher */
for (j=0; j < klen; j++) for (j=0; j < klen; j++)
key[j] = (uint8_t) rand(); key[j] = (uint8_t) rand();
for (; j < klen_pad; j++)
key[j] = 0;
status = cipher_init(*cipher_array, key, direction_encrypt); status = cipher_init(*cipher_array, key, direction_encrypt);
if (status) if (status)
return status; return status;
@ -387,6 +421,8 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
cipher_array++; cipher_array++;
} }
crypto_free(key);
return err_status_ok; return err_status_ok;
} }
@ -423,24 +459,28 @@ cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher,
v128_t nonce; v128_t nonce;
clock_t timer; clock_t timer;
unsigned char *enc_buf; unsigned char *enc_buf;
int cipher_index = 0; int cipher_index = rand() % num_cipher;
/* Over-alloc, for NIST CBC padding */
enc_buf = crypto_alloc(octets_in_buffer); enc_buf = crypto_alloc(octets_in_buffer+17);
if (enc_buf == NULL) if (enc_buf == NULL)
return 0; /* indicate bad parameters by returning null */ return 0; /* indicate bad parameters by returning null */
memset(enc_buf, 0, octets_in_buffer);
/* time repeated trials */ /* time repeated trials */
v128_set_to_zero(&nonce); v128_set_to_zero(&nonce);
timer = clock(); timer = clock();
for(i=0; i < num_trials; i++, nonce.v32[3] = i) { for(i=0; i < num_trials; i++, nonce.v32[3] = i) {
/* length parameter to cipher_encrypt is in/out -- out is total, padded
/* choose a cipher at random from the array*/ * length -- so reset it each time. */
cipher_index = (*((uint32_t *)enc_buf)) % num_cipher; unsigned octets_to_encrypt = octets_in_buffer;
/* encrypt buffer with cipher */ /* encrypt buffer with cipher */
cipher_set_iv(cipher_array[cipher_index], &nonce); 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; timer = clock() - timer;
@ -451,7 +491,7 @@ cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher,
return 0; 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 void
@ -459,10 +499,10 @@ cipher_array_test_throughput(cipher_t *ca[], int num_cipher) {
int i; int i;
int min_enc_len = 16; int min_enc_len = 16;
int max_enc_len = 2048; /* should be a power of two */ 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", printf("timing %s throughput with key length %d, array size %d:\n",
(ca[0])->type->description, num_cipher); (ca[0])->type->description, (ca[0])->key_len, num_cipher);
fflush(stdout); fflush(stdout);
for (i=min_enc_len; i <= max_enc_len; i = i * 4) for (i=min_enc_len; i <= max_enc_len; i = i * 4)
printf("msg len: %d\tgigabits per second: %f\n", i, printf("msg len: %d\tgigabits per second: %f\n", i,

Binary file not shown.

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005 Cisco Systems, Inc. * Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

BIN
libs/srtp/crypto/test/sha1_driver Executable file

Binary file not shown.

View File

@ -113,17 +113,17 @@ sha1_test_case_validate(const hash_test_case_t *test_case) {
if (0 == memcmp(test_case->hash, hash_value, 20)) { if (0 == memcmp(test_case->hash, hash_value, 20)) {
#if VERBOSE #if VERBOSE
printf("PASSED: reference value: %s\n", 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", 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 #endif
return err_status_ok; return err_status_ok;
} }
printf("reference value: %s\n", 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", 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; return err_status_algo_fail;
@ -136,7 +136,7 @@ struct hex_sha1_test_case_t {
}; };
err_status_t err_status_t
sha1_add_test_cases() { sha1_add_test_cases(void) {
int i; int i;
err_status_t err; err_status_t err;
@ -485,6 +485,21 @@ sha1_add_test_cases() {
return err_status_ok; 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 err_status_t
sha1_validate(void) { sha1_validate(void) {
@ -510,6 +525,8 @@ sha1_validate(void) {
test_case = test_case->next_test_case; test_case = test_case->next_test_case;
} }
sha1_dealloc_test_cases();
return err_status_ok; return err_status_ok;
} }

BIN
libs/srtp/crypto/test/stat_driver Executable file

Binary file not shown.

View File

@ -37,7 +37,9 @@ main (int argc, char *argv[]) {
int i, j; int i, j;
extern cipher_type_t aes_icm; extern cipher_type_t aes_icm;
cipher_t *c; 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, 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" printf("(nota bene: a small fraction of stat_test failures does not \n"
"indicate that the random source is invalid)\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; return 0;
} }

View File

@ -346,7 +346,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories # directories like "/usr/src/myproject". Separate the files or directories
# with spaces. # 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 # 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 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp

View File

@ -86,14 +86,17 @@ libSRTP LIBSRTPVERSION Overview and Reference Manual\\
The original implementation and documentation of libSRTP was written The original implementation and documentation of libSRTP was written
by David McGrew of Cisco Systems, Inc. in order to promote the use, by David McGrew of Cisco Systems, Inc. in order to promote the use,
understanding, and interoperability of Secure RTP. Randell Jesup understanding, and interoperability of Secure RTP. Michael Jerris
contributed a working SRTCP implementation and other fixes. Alex contributed support for building under MSVC. Andris Pavenis
Vanzella and Will Clark contributed changes so that the AES ICM contributed many important fixes. Brian West contributed changes to
implementation can be used for ISMA media encryption. Steve Underwood enable dynamic linking. Yves Shumann reported documentation bugs.
contributed x86\_64 portability changes. We also give thanks to Brian Randell Jesup contributed a working SRTCP implementation and other
Weis, Mark Baugher, Jeff Chan, Bill Simon, Douglas Smith, Bill May, fixes. Alex Vanzella and Will Clark contributed changes so that the
Richard Preistley, Joe Tardo and others for contributions, comments, AES ICM implementation can be used for ISMA media encryption. Steve
and corrections. 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 This reference material in this documenation was generated using the
\texttt{doxygen} utility for automatic documentation of source code. \texttt{doxygen} utility for automatic documentation of source code.

View File

@ -5,10 +5,10 @@
This document describes libSRTP, the Open Source Secure RTP library This document describes libSRTP, the Open Source Secure RTP library
from Cisco Systems, Inc. RTP is the Real-time Transport Protocol, an from Cisco Systems, Inc. RTP is the Real-time Transport Protocol, an
IETF standard for the transport of real-time data such as telephony, 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 profile for providing confidentiality to RTP data and authentication
to the RTP header and payload. SRTP is an IETF Proposed Standard, and to the RTP header and payload. SRTP is an IETF Proposed Standard,
is defined in RFC 3711, and was developed in the IETF Audio/Video defined in RFC 3711, and was developed in the IETF Audio/Video
Transport (AVT) Working Group. This library supports all of the Transport (AVT) Working Group. This library supports all of the
mandatory features of SRTP, but not all of the optional features. See mandatory features of SRTP, but not all of the optional features. See
the @ref Features section for more detailed information. 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 extension\footnote{The extension \texttt{.tgz} is identical to
\texttt{tar.gz}, and indicates a compressed tar file.} You probably \texttt{tar.gz}, and indicates a compressed tar file.} You probably
want to get the most recent release. Unpack the distribution and 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}. will go is named \texttt{srtp}.
libSRTP uses the GNU \texttt{autoconf} and \texttt{make} libSRTP uses the GNU \texttt{autoconf} and \texttt{make}
@ -135,7 +135,7 @@ The configure script accepts the following options:
\end{description} \end{description}
\end{quote} \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 debugging. You can use the configure options to have the debugging
output sent to syslog or the system console. Alternatively, you can output sent to syslog or the system console. Alternatively, you can
define ERR\_REPORTING\_FILE in \texttt{include/conf.h} to be any other 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 The usage for rtpw is
\texttt{rtpw [[-d $<$debug$>$]* [-k $<$key$>$ [-a][-e]] [-s | -r] dest\_ip \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 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 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{center}
\begin{tabular}{ll} \begin{tabular}{ll}
-s & (S)RTP sender - causes app to send words \\ -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 -k $<$key$>$ & use SRTP master key $<$key$>$, where the
key is a hexadecimal value (without the key is a hexadecimal value (without the
leading "0x") \\ leading "0x") \\
@ -197,7 +197,7 @@ the dictionary will be sent, respectively. The options are:
(requires use of -k option as well)\\ (requires use of -k option as well)\\
-a & message authentication -a & message authentication
(requires use of -k option as well) \\ (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$>$ \\ -d $<$debug$>$ & turn on debugging for module $<$debug$>$ \\
\end{tabular} \end{tabular}
\end{center} \end{center}
@ -359,7 +359,7 @@ length as its second argument.
crypto_get_random(key, 30); crypto_get_random(key, 30);
// allocate and initialize the SRTP session // allocate and initialize the SRTP session
srtp_create(&session, policy); srtp_create(&session, &policy);
// main loop: get rtp packets, send srtp packets // main loop: get rtp packets, send srtp packets
while (1) { while (1) {

Binary file not shown.

201
libs/srtp/include/ekt.h Normal file
View File

@ -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 */

View File

@ -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 */

View File

@ -16,7 +16,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -54,72 +54,86 @@
#ifndef RTP_H #ifndef RTP_H
#define RTP_H #define RTP_H
#include "srtp.h"
#ifdef HAVE_NETINET_IN_H #ifdef HAVE_NETINET_IN_H
# include <netinet/in.h> # include <netinet/in.h>
#elif defined HAVE_WINSOCK2_H #elif defined HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #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 rtp_receiver_ctx_t *rtp_receiver_t;
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);
int int
rtp_receiver_init(rtp_receiver_t *rcvr, int socket, rtp_sendto(rtp_sender_t sender, const void* msg, int len);
struct sockaddr_in addr, uint32_t ssrc);
int int
rtp_sender_init(rtp_sender_t *sender, int socket, rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len);
struct sockaddr_in addr, uint32_t ssrc);
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 * srtp_sender_init(...) initializes an rtp_sender_t
*
*/ */
int 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 */ struct sockaddr_in name, /* socket name */
sec_serv_t security_services, /* sec. servs. to be used */ sec_serv_t security_services, /* sec. servs. to be used */
unsigned char *input_key /* master key/salt in hex */ unsigned char *input_key /* master key/salt in hex */
); );
int 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 */ struct sockaddr_in name, /* socket name */
sec_serv_t security_services, /* sec. servs. to be used */ sec_serv_t security_services, /* sec. servs. to be used */
unsigned char *input_key /* master key/salt in hex */ 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 */ #endif /* RTP_H */

View File

@ -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 */

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -50,14 +50,7 @@
extern "C" { extern "C" {
#endif #endif
#ifdef _MSC_VER #include "crypto_kernel.h"
#pragma warning(disable:4214)
#endif
#include "crypto_kernel.h"
#include "rdbx.h"
#include "rdb.h"
#include "integers.h"
/** /**
* @defgroup SRTP Secure RTP * @defgroup SRTP Secure RTP
@ -171,10 +164,22 @@ typedef enum {
typedef struct { typedef struct {
ssrc_type_t type; /**< The type of this particular SSRC */ 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; } 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. * @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 rtp; /**< SRTP crypto policy. */
crypto_policy_t rtcp; /**< SRTCP 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. */ * 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. */ struct srtp_policy_t *next; /**< Pointer to next stream policy. */
} srtp_policy_t; } srtp_policy_t;
@ -260,6 +275,15 @@ typedef struct srtp_stream_ctx_t *srtp_stream_t;
err_status_t err_status_t
srtp_init(void); 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 * @brief srtp_protect() is the Secure RTP sender-side packet processing
* function. * function.
@ -413,14 +437,13 @@ srtp_add_stream(srtp_t session,
*/ */
err_status_t 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 * @brief crypto_policy_set_rtp_default() sets a crypto policy
* structure to the SRTP default policy for RTP protection. * structure to the SRTP default policy for RTP protection.
* *
* @param p is a pointer to the policy strucutre to be set to the * @param p is a pointer to the policy structure to be set
* default policy.
* *
* The function call crypto_policy_set_rtp_default(&p) sets the * The function call crypto_policy_set_rtp_default(&p) sets the
* crypto_policy_t at location p to the SRTP default policy for RTP * 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 * @brief crypto_policy_set_rtcp_default() sets a crypto policy
* structure to the SRTP default policy for RTCP protection. * structure to the SRTP default policy for RTCP protection.
* *
* @param p is a pointer to the policy strucutre to be set to the * @param p is a pointer to the policy structure to be set
* default policy.
* *
* The function call crypto_policy_set_rtcp_default(&p) sets the * The function call crypto_policy_set_rtcp_default(&p) sets the
* crypto_policy_t at location p to the SRTP default policy for RTCP * 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 * @brief crypto_policy_set_aes_cm_128_hmac_sha1_80() sets a crypto
* policy structure to the SRTP default policy for RTP protection. * policy structure to the SRTP default policy for RTP protection.
* *
* @param p is a pointer to the policy strucutre to be set to the * @param p is a pointer to the policy structure to be set
* default policy.
* *
* The function crypto_policy_set_aes_cm_128_hmac_sha1_80() is a * The function crypto_policy_set_aes_cm_128_hmac_sha1_80() is a
* synonym for crypto_policy_set_rtp_default(). It conforms to the * synonym for crypto_policy_set_rtp_default(). It conforms to the
* naming convention used in * naming convention used in RFC 4568 (SDP Security Descriptions for
* http://www.ietf.org/internet-drafts/draft-ietf-mmusic-sdescriptions-12.txt * Media Streams).
* *
* @return void. * @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 * @brief crypto_policy_set_aes_cm_128_hmac_sha1_32() sets a crypto
* policy structure to a short-authentication tag policy * policy structure to a short-authentication tag policy
* *
* @param p is a pointer to the policy strucutre to be set to the * @param p is a pointer to the policy structure to be set
* default policy.
* *
* The function call crypto_policy_set_aes_cm_128_hmac_sha1_32(&p) * The function call crypto_policy_set_aes_cm_128_hmac_sha1_32(&p)
* sets the crypto_policy_t at location p to use policy * sets the crypto_policy_t at location p to use policy
* AES_CM_128_HMAC_SHA1_32 as defined in * AES_CM_128_HMAC_SHA1_32 as defined in RFC 4568.
* draft-ietf-mmusic-sdescriptions-12.txt. This policy uses AES-128 * This policy uses AES-128
* Counter Mode encryption and HMAC-SHA1 authentication, with an * Counter Mode encryption and HMAC-SHA1 authentication, with an
* authentication tag that is only 32 bits long. This length is * authentication tag that is only 32 bits long. This length is
* considered adequate only for protecting audio and video media that * 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 * @brief crypto_policy_set_aes_cm_128_null_auth() sets a crypto
* policy structure to an encryption-only policy * policy structure to an encryption-only policy
* *
* @param p is a pointer to the policy strucutre to be set to the * @param p is a pointer to the policy structure to be set
* default policy.
* *
* The function call crypto_policy_set_aes_cm_128_null_auth(&p) sets * 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 * 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 * @brief crypto_policy_set_null_cipher_hmac_sha1_80() sets a crypto
* policy structure to an authentication-only policy * policy structure to an authentication-only policy
* *
* @param p is a pointer to the policy strucutre to be set to the * @param p is a pointer to the policy structure to be set
* default policy.
* *
* The function call crypto_policy_set_null_cipher_hmac_sha1_80(&p) * 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 * 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 void
crypto_policy_set_null_cipher_hmac_sha1_80(crypto_policy_t *p); 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 * @brief srtp_dealloc() deallocates storage for an SRTP session
* context. * context.
@ -597,70 +679,114 @@ err_status_t
srtp_dealloc(srtp_t s); 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 * @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 */ /* in host order, so outside the #if */
#define SRTCP_E_BIT 0x80000000 #define SRTCP_E_BIT 0x80000000
/* for byte-access */ /* for byte-access */
#define SRTCP_E_BYTE_BIT 0x80 #define SRTCP_E_BYTE_BIT 0x80
#define SRTCP_INDEX_MASK 0x7fffffff #define SRTCP_INDEX_MASK 0x7fffffff
#ifdef _MSC_VER
#pragma pack(pop, r1)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -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 */

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -1,91 +1,91 @@
EXPORTS EXPORTS
srtp_init srtp_init
srtp_protect srtp_protect
srtp_unprotect srtp_unprotect
srtp_create srtp_create
srtp_add_stream srtp_add_stream
srtp_remove_stream srtp_remove_stream
crypto_policy_set_rtp_default crypto_policy_set_rtp_default
crypto_policy_set_rtcp_default crypto_policy_set_rtcp_default
crypto_policy_set_aes_cm_128_hmac_sha1_32 crypto_policy_set_aes_cm_128_hmac_sha1_32
crypto_policy_set_aes_cm_128_null_auth crypto_policy_set_aes_cm_128_null_auth
crypto_policy_set_null_cipher_hmac_sha1_80 crypto_policy_set_null_cipher_hmac_sha1_80
srtp_dealloc srtp_dealloc
srtp_get_stream srtp_get_stream
srtp_protect_rtcp srtp_protect_rtcp
srtp_unprotect_rtcp srtp_unprotect_rtcp
srtp_install_event_handler srtp_install_event_handler
crypto_kernel_init crypto_kernel_init
crypto_kernel_shutdown crypto_kernel_shutdown
crypto_kernel_status crypto_kernel_status
crypto_kernel_list_debug_modules crypto_kernel_list_debug_modules
crypto_kernel_load_cipher_type crypto_kernel_load_cipher_type
crypto_kernel_load_auth_type crypto_kernel_load_auth_type
crypto_kernel_load_debug_module crypto_kernel_load_debug_module
crypto_kernel_alloc_cipher crypto_kernel_alloc_cipher
crypto_kernel_alloc_auth crypto_kernel_alloc_auth
crypto_kernel_set_debug_module crypto_kernel_set_debug_module
crypto_get_random crypto_get_random
rand_source_init rand_source_init
rand_source_get_octet_string rand_source_get_octet_string
rand_source_deinit rand_source_deinit
x917_prng_init x917_prng_init
x917_prng_get_octet_string x917_prng_get_octet_string
ctr_prng_init ctr_prng_init
ctr_prng_get_octet_string ctr_prng_get_octet_string
cipher_output cipher_output
cipher_get_key_length cipher_get_key_length
cipher_type_self_test cipher_type_self_test
cipher_bits_per_second cipher_bits_per_second
auth_get_key_length auth_get_key_length
auth_get_tag_length auth_get_tag_length
auth_get_prefix_length auth_get_prefix_length
auth_type_self_test auth_type_self_test
auth_type_get_ref_count auth_type_get_ref_count
stat_test_monobit stat_test_monobit
stat_test_poker stat_test_poker
stat_test_runs stat_test_runs
stat_test_rand_source stat_test_rand_source
stat_test_rand_source_with_repetition stat_test_rand_source_with_repetition
err_reporting_init err_reporting_init
err_report err_report
key_limit_set key_limit_set
key_limit_clone key_limit_clone
key_limit_check key_limit_check
key_limit_update key_limit_update
rdbx_init rdbx_init
rdbx_estimate_index rdbx_estimate_index
rdbx_check rdbx_check
rdbx_add_index rdbx_add_index
index_init index_init
index_advance index_advance
index_guess index_guess
octet_get_weight octet_get_weight
octet_string_hex_string octet_string_hex_string
v128_bit_string v128_bit_string
v128_hex_string v128_hex_string
nibble_to_hex_char nibble_to_hex_char
hex_string_to_octet_string hex_string_to_octet_string
v128_copy_octet_string v128_copy_octet_string
v128_left_shift v128_left_shift
v128_right_shift v128_right_shift
octet_string_is_eq octet_string_is_eq
octet_string_set_to_zero octet_string_set_to_zero
rdb_init rdb_init
rdb_check rdb_check
rdb_add_index rdb_add_index
rdb_increment rdb_increment
rdb_get_value rdb_get_value
aes_expand_encryption_key aes_expand_encryption_key
aes_expand_decryption_key aes_expand_decryption_key
aes_encrypt aes_encrypt
aes_decrypt aes_decrypt
aes_icm_context_init aes_icm_context_init
aes_icm_set_iv aes_icm_set_iv
aes_icm_encrypt aes_icm_encrypt
aes_icm_output aes_icm_output
aes_icm_dealloc aes_icm_dealloc
aes_icm_encrypt_ismacryp aes_icm_encrypt_ismacryp
aes_icm_alloc_ismacryp aes_icm_alloc_ismacryp
crypto_alloc crypto_alloc
crypto_free crypto_free

278
libs/srtp/srtp/ekt.c Normal file
View File

@ -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 */
}

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2005 Cisco Systems, Inc. * Copyright(c) 2001-2006 Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -0,0 +1,261 @@
/*
* dtls_srtp_driver.c
*
* test driver for DTLS-SRTP functions
*
* David McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h> /* for printf() */
#include "getopt_s.h" /* for local getopt() */
#include "srtp_priv.h"
err_status_t
test_dtls_srtp(void);
srtp_hdr_t *
srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc);
void
usage(char *prog_name) {
printf("usage: %s [ -t ][ -c ][ -v ][-d <debug_module> ]* [ -l ]\n"
" -d <mod> turn on debugging module <mod>\n"
" -l list debugging modules\n", prog_name);
exit(1);
}
int
main(int argc, char *argv[]) {
unsigned do_list_mods = 0;
int q;
err_status_t err;
printf("dtls_srtp_driver\n");
/* initialize srtp library */
err = srtp_init();
if (err) {
printf("error: srtp init failed with error code %d\n", err);
exit(1);
}
/* process input arguments */
while (1) {
q = getopt_s(argc, argv, "ld:");
if (q == -1)
break;
switch (q) {
case 'l':
do_list_mods = 1;
break;
case 'd':
err = crypto_kernel_set_debug_module(optarg_s, 1);
if (err) {
printf("error: set debug module (%s) failed\n", optarg_s);
exit(1);
}
break;
default:
usage(argv[0]);
}
}
if (do_list_mods) {
err = crypto_kernel_list_debug_modules();
if (err) {
printf("error: list of debug modules failed\n");
exit(1);
}
}
printf("testing dtls_srtp...");
err = test_dtls_srtp();
if (err) {
printf("\nerror (code %d)\n", err);
exit(1);
}
printf("passed\n");
/* shut down srtp library */
err = srtp_shutdown();
if (err) {
printf("error: srtp shutdown failed with error code %d\n", err);
exit(1);
}
return 0;
}
err_status_t
test_dtls_srtp(void) {
srtp_hdr_t *test_packet;
int test_packet_len = 80;
srtp_t s;
srtp_policy_t policy;
uint8_t key[SRTP_MAX_KEY_LEN];
uint8_t salt[SRTP_MAX_KEY_LEN];
unsigned int key_len, salt_len;
srtp_profile_t profile;
err_status_t err;
/* create a 'null' SRTP session */
err = srtp_create(&s, NULL);
if (err)
return err;
/*
* verify that packet-processing functions behave properly - we
* expect that these functions will return err_status_no_ctx
*/
test_packet = srtp_create_test_packet(80, 0xa5a5a5a5);
if (test_packet == NULL)
return err_status_alloc_fail;
err = srtp_protect(s, test_packet, &test_packet_len);
if (err != err_status_no_ctx) {
printf("wrong return value from srtp_protect() (got code %d)\n",
err);
return err_status_fail;
}
err = srtp_unprotect(s, test_packet, &test_packet_len);
if (err != err_status_no_ctx) {
printf("wrong return value from srtp_unprotect() (got code %d)\n",
err);
return err_status_fail;
}
err = srtp_protect_rtcp(s, test_packet, &test_packet_len);
if (err != err_status_no_ctx) {
printf("wrong return value from srtp_protect_rtcp() (got code %d)\n",
err);
return err_status_fail;
}
err = srtp_unprotect_rtcp(s, test_packet, &test_packet_len);
if (err != err_status_no_ctx) {
printf("wrong return value from srtp_unprotect_rtcp() (got code %d)\n",
err);
return err_status_fail;
}
/*
* set keys to known values for testing
*/
profile = srtp_profile_aes128_cm_sha1_80;
key_len = srtp_profile_get_master_key_length(profile);
salt_len = srtp_profile_get_master_salt_length(profile);
memset(key, 0xff, key_len);
memset(salt, 0xee, salt_len);
append_salt_to_key(key, key_len, salt, salt_len);
policy.key = key;
/* initialize SRTP policy from profile */
err = crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile);
if (err) return err;
err = crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile);
if (err) return err;
policy.ssrc.type = ssrc_any_inbound;
policy.ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
err = srtp_add_stream(s, &policy);
if (err)
return err;
err = srtp_dealloc(s);
if (err)
return err;
free(test_packet);
return err_status_ok;
}
/*
* srtp_create_test_packet(len, ssrc) returns a pointer to a
* (malloced) example RTP packet whose data field has the length given
* by pkt_octet_len and the SSRC value ssrc. The total length of the
* packet is twelve octets longer, since the header is at the
* beginning. There is room at the end of the packet for a trailer,
* and the four octets following the packet are filled with 0xff
* values to enable testing for overwrites.
*
* note that the location of the test packet can (and should) be
* deallocated with the free() call once it is no longer needed.
*/
srtp_hdr_t *
srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc) {
int i;
uint8_t *buffer;
srtp_hdr_t *hdr;
int bytes_in_hdr = 12;
/* allocate memory for test packet */
hdr = malloc(pkt_octet_len + bytes_in_hdr
+ SRTP_MAX_TRAILER_LEN + 4);
if (!hdr)
return NULL;
hdr->version = 2; /* RTP version two */
hdr->p = 0; /* no padding needed */
hdr->x = 0; /* no header extension */
hdr->cc = 0; /* no CSRCs */
hdr->m = 0; /* marker bit */
hdr->pt = 0xf; /* payload type */
hdr->seq = htons(0x1234); /* sequence number */
hdr->ts = htonl(0xdecafbad); /* timestamp */
hdr->ssrc = htonl(ssrc); /* synch. source */
buffer = (uint8_t *)hdr;
buffer += bytes_in_hdr;
/* set RTP data to 0xab */
for (i=0; i < pkt_octet_len; i++)
*buffer++ = 0xab;
/* set post-data value to 0xffff to enable overrun checking */
for (i=0; i < SRTP_MAX_TRAILER_LEN+4; i++)
*buffer++ = 0xff;
return hdr;
}

112
libs/srtp/test/getopt_s.c Normal file
View File

@ -0,0 +1,112 @@
/*
* getopt.c
*
* a minimal implementation of the getopt() function, written so that
* test applications that use that function can run on non-POSIX
* platforms
*
*/
/*
*
* Copyright (c) 2001-2006 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdlib.h> /* for NULL */
int optind_s = 0;
char *optarg_s;
#define GETOPT_FOUND_WITHOUT_ARGUMENT 2
#define GETOPT_FOUND_WITH_ARGUMENT 1
#define GETOPT_NOT_FOUND 0
static int
getopt_check_character(char c, const char *string) {
unsigned int max_string_len = 128;
while (*string != 0) {
if (max_string_len == 0) {
return '?';
}
if (*string++ == c) {
if (*string == ':') {
return GETOPT_FOUND_WITH_ARGUMENT;
} else {
return GETOPT_FOUND_WITHOUT_ARGUMENT;
}
}
}
return GETOPT_NOT_FOUND;
}
int
getopt_s(int argc,
char * const argv[],
const char *optstring) {
while (optind_s + 1 < argc) {
char *string;
/* move 'string' on to next argument */
optind_s++;
string = argv[optind_s];
if (string == NULL)
return '?'; /* NULL argument string */
if (string[0] != '-')
return -1; /* found an unexpected character */
switch(getopt_check_character(string[1], optstring)) {
case GETOPT_FOUND_WITH_ARGUMENT:
if (optind_s + 1 < argc) {
optind_s++;
optarg_s = argv[optind_s];
return string[1];
} else {
return '?'; /* argument missing */
}
case GETOPT_FOUND_WITHOUT_ARGUMENT:
return string[1];
case GETOPT_NOT_FOUND:
default:
return '?'; /* didn't find expected character */
break;
}
}
return -1;
}

BIN
libs/srtp/test/rdbx_driver Executable file

Binary file not shown.

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,8 +43,8 @@
* *
*/ */
#include <stdio.h> /* for printf() */ #include <stdio.h> /* for printf() */
#include <unistd.h> /* for getopt() */ #include "getopt_s.h" /* for local getopt() */
#include "rdbx.h" #include "rdbx.h"
@ -55,10 +55,10 @@
#include "ut_sim.h" #include "ut_sim.h"
err_status_t err_status_t
test_replay_dbx(int num_trials); test_replay_dbx(int num_trials, unsigned long ws);
double double
rdbx_check_adds_per_second(int num_trials); rdbx_check_adds_per_second(int num_trials, unsigned long ws);
void void
usage(char *prog_name) { usage(char *prog_name) {
@ -70,13 +70,13 @@ int
main (int argc, char *argv[]) { main (int argc, char *argv[]) {
double rate; double rate;
err_status_t status; err_status_t status;
char q; int q;
unsigned do_timing_test = 0; unsigned do_timing_test = 0;
unsigned do_validation = 0; unsigned do_validation = 0;
/* process input arguments */ /* process input arguments */
while (1) { while (1) {
q = getopt(argc, argv, "tv"); q = getopt_s(argc, argv, "tv");
if (q == -1) if (q == -1)
break; break;
switch (q) { switch (q) {
@ -99,9 +99,18 @@ main (int argc, char *argv[]) {
usage(argv[0]); usage(argv[0]);
if (do_validation) { if (do_validation) {
printf("testing rdbx_t...\n"); printf("testing rdbx_t (ws=128)...\n");
status = test_replay_dbx(1 << 12); status = test_replay_dbx(1 << 12, 128);
if (status) {
printf("failed\n");
exit(1);
}
printf("passed\n");
printf("testing rdbx_t (ws=1024)...\n");
status = test_replay_dbx(1 << 12, 1024);
if (status) { if (status) {
printf("failed\n"); printf("failed\n");
exit(1); exit(1);
@ -110,8 +119,10 @@ main (int argc, char *argv[]) {
} }
if (do_timing_test) { if (do_timing_test) {
rate = rdbx_check_adds_per_second(1 << 18); rate = rdbx_check_adds_per_second(1 << 18, 128);
printf("rdbx_check/replay_adds per second: %e\n", rate); printf("rdbx_check/replay_adds per second (ws=128): %e\n", rate);
rate = rdbx_check_adds_per_second(1 << 18, 1024);
printf("rdbx_check/replay_adds per second (ws=1024): %e\n", rate);
} }
return 0; return 0;
@ -119,8 +130,11 @@ main (int argc, char *argv[]) {
void void
print_rdbx(rdbx_t *rdbx) { print_rdbx(rdbx_t *rdbx) {
char buf[2048];
printf("rdbx: {%llu, %s}\n", printf("rdbx: {%llu, %s}\n",
(unsigned long long)(rdbx->index), v128_bit_string(&rdbx->bitmask)); (unsigned long long)(rdbx->index),
bitvector_bit_string(&rdbx->bitmask, buf, sizeof(buf))
);
} }
@ -183,28 +197,38 @@ rdbx_check_expect_failure(rdbx_t *rdbx, uint32_t idx) {
} }
err_status_t err_status_t
rdbx_check_unordered(rdbx_t *rdbx, uint32_t idx) { rdbx_check_add_unordered(rdbx_t *rdbx, uint32_t idx) {
int delta;
xtd_seq_num_t est;
err_status_t rstat; err_status_t rstat;
rstat = rdbx_check(rdbx, idx); delta = index_guess(&rdbx->index, &est, idx);
rstat = rdbx_check(rdbx, delta);
if ((rstat != err_status_ok) && (rstat != err_status_replay_old)) { if ((rstat != err_status_ok) && (rstat != err_status_replay_old)) {
printf("replay_check_unordered failed at index %u\n", idx); printf("replay_check_add_unordered failed at index %u\n", idx);
return err_status_algo_fail; return err_status_algo_fail;
} }
if (rstat == err_status_replay_old) {
return err_status_ok;
}
if (rdbx_add_index(rdbx, delta) != err_status_ok) {
printf("rdbx_add_index failed at index %u\n", idx);
return err_status_algo_fail;
}
return err_status_ok; return err_status_ok;
} }
#define MAX_IDX 160
err_status_t err_status_t
test_replay_dbx(int num_trials) { test_replay_dbx(int num_trials, unsigned long ws) {
rdbx_t rdbx; rdbx_t rdbx;
uint32_t idx, ircvd; uint32_t idx, ircvd;
ut_connection utc; ut_connection utc;
err_status_t status; err_status_t status;
int num_fp_trials; int num_fp_trials;
status = rdbx_init(&rdbx); status = rdbx_init(&rdbx, ws);
if (status) { if (status) {
printf("replay_init failed with error code %d\n", status); printf("replay_init failed with error code %d\n", status);
exit(1); exit(1);
@ -241,7 +265,9 @@ test_replay_dbx(int num_trials) {
printf("passed\n"); printf("passed\n");
/* re-initialize */ /* re-initialize */
if (rdbx_init(&rdbx) != err_status_ok) { rdbx_dealloc(&rdbx);
if (rdbx_init(&rdbx, ws) != err_status_ok) {
printf("replay_init failed\n"); printf("replay_init failed\n");
return err_status_init_fail; return err_status_init_fail;
} }
@ -257,12 +283,40 @@ test_replay_dbx(int num_trials) {
printf("\ttesting non-sequential insertion..."); printf("\ttesting non-sequential insertion...");
for (idx=0; idx < num_trials; idx++) { for (idx=0; idx < num_trials; idx++) {
ircvd = ut_next_index(&utc); ircvd = ut_next_index(&utc);
status = rdbx_check_unordered(&rdbx, ircvd); status = rdbx_check_add_unordered(&rdbx, ircvd);
if (status)
return status;
status = rdbx_check_expect_failure(&rdbx, ircvd);
if (status)
return status;
}
printf("passed\n");
/* re-initialize */
rdbx_dealloc(&rdbx);
if (rdbx_init(&rdbx, ws) != err_status_ok) {
printf("replay_init failed\n");
return err_status_init_fail;
}
/*
* test insertion with large gaps.
* check for false positives for each insertion.
*/
printf("\ttesting insertion with large gaps...");
for (idx=0, ircvd=0; idx < num_trials; idx++, ircvd += (1 << (rand() % 12))) {
status = rdbx_check_add(&rdbx, ircvd);
if (status)
return status;
status = rdbx_check_expect_failure(&rdbx, ircvd);
if (status) if (status)
return status; return status;
} }
printf("passed\n"); printf("passed\n");
rdbx_dealloc(&rdbx);
return err_status_ok; return err_status_ok;
} }
@ -272,7 +326,7 @@ test_replay_dbx(int num_trials) {
#include <stdlib.h> /* for random() */ #include <stdlib.h> /* for random() */
double double
rdbx_check_adds_per_second(int num_trials) { rdbx_check_adds_per_second(int num_trials, unsigned long ws) {
uint32_t i; uint32_t i;
int delta; int delta;
rdbx_t rdbx; rdbx_t rdbx;
@ -280,7 +334,7 @@ rdbx_check_adds_per_second(int num_trials) {
clock_t timer; clock_t timer;
int failures; /* count number of failures */ int failures; /* count number of failures */
if (rdbx_init(&rdbx) != err_status_ok) { if (rdbx_init(&rdbx, ws) != err_status_ok) {
printf("replay_init failed\n"); printf("replay_init failed\n");
exit(1); exit(1);
} }
@ -301,6 +355,8 @@ rdbx_check_adds_per_second(int num_trials) {
printf("number of failures: %d \n", failures); printf("number of failures: %d \n", failures);
rdbx_dealloc(&rdbx);
return (double) CLOCKS_PER_SEC * num_trials / timer; return (double) CLOCKS_PER_SEC * num_trials / timer;
} }

BIN
libs/srtp/test/replay_driver Executable file

Binary file not shown.

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -48,7 +48,14 @@
#include "rdb.h" #include "rdb.h"
#include "ut_sim.h" #include "ut_sim.h"
void /*
* num_trials defines the number of trials that are used in the
* validation functions below
*/
unsigned num_trials = 1 << 16;
err_status_t
test_rdb_db(void); test_rdb_db(void);
double double
@ -56,9 +63,14 @@ rdb_check_adds_per_second(void);
int int
main (void) { main (void) {
err_status_t err;
printf("testing anti-replay database (rdb_t)...\n"); printf("testing anti-replay database (rdb_t)...\n");
test_rdb_db(); err = test_rdb_db();
if (err) {
printf("failed\n");
exit(1);
}
printf("done\n"); printf("done\n");
printf("rdb_check/rdb_adds per second: %e\n", printf("rdb_check/rdb_adds per second: %e\n",
@ -73,73 +85,138 @@ print_rdb(rdb_t *rdb) {
printf("rdb: {%u, %s}\n", rdb->window_start, v128_bit_string(&rdb->bitmask)); printf("rdb: {%u, %s}\n", rdb->window_start, v128_bit_string(&rdb->bitmask));
} }
void err_status_t
rdb_check_add(rdb_t *rdb, uint32_t idx) { rdb_check_add(rdb_t *rdb, uint32_t idx) {
if (rdb_check(rdb, idx) != err_status_ok) { if (rdb_check(rdb, idx) != err_status_ok) {
printf("rdb_check failed at index %u\n", idx); printf("rdb_check failed at index %u\n", idx);
return; return err_status_fail;
} }
if (rdb_add_index(rdb, idx) != err_status_ok) if (rdb_add_index(rdb, idx) != err_status_ok) {
printf("rdb_add_index failed at index %u\n", idx); printf("rdb_add_index failed at index %u\n", idx);
return err_status_fail;
}
return err_status_ok;
} }
void err_status_t
rdb_check_expect_failure(rdb_t *rdb, uint32_t idx) { rdb_check_expect_failure(rdb_t *rdb, uint32_t idx) {
err_status_t err;
if (rdb_check(rdb, idx) != err_status_fail)
err = rdb_check(rdb, idx);
if ((err != err_status_replay_old) && (err != err_status_replay_fail)) {
printf("rdb_check failed at index %u (false positive)\n", idx); printf("rdb_check failed at index %u (false positive)\n", idx);
return err_status_fail;
}
return err_status_ok;
} }
void err_status_t
rdb_check_unordered(rdb_t *rdb, uint32_t idx) { rdb_check_add_unordered(rdb_t *rdb, uint32_t idx) {
err_status_t rstat; err_status_t rstat;
/* printf("index: %u\n", idx); */
rstat = rdb_check(rdb, idx); rstat = rdb_check(rdb, idx);
if ((rstat != err_status_ok) && (rstat != err_status_replay_old)) if ((rstat != err_status_ok) && (rstat != err_status_replay_old)) {
printf("rdb_check_unordered failed at index %u\n", idx); printf("rdb_check_add_unordered failed at index %u\n", idx);
return rstat;
}
if (rstat == err_status_replay_old) {
return err_status_ok;
}
if (rdb_add_index(rdb, idx) != err_status_ok) {
printf("rdb_add_index failed at index %u\n", idx);
return err_status_fail;
}
return err_status_ok;
} }
err_status_t
#define MAX_IDX 160
void
test_rdb_db() { test_rdb_db() {
rdb_t rdb; rdb_t rdb;
uint32_t idx, ircvd; uint32_t idx, ircvd;
ut_connection utc; ut_connection utc;
err_status_t err;
if (rdb_init(&rdb) != err_status_ok) { if (rdb_init(&rdb) != err_status_ok) {
printf("rdb_init failed\n"); printf("rdb_init failed\n");
exit(1); return err_status_init_fail;
} }
/* test sequential insertion */ /* test sequential insertion */
for (idx=0; idx < MAX_IDX; idx++) { for (idx=0; idx < num_trials; idx++) {
rdb_check_add(&rdb, idx); err = rdb_check_add(&rdb, idx);
if (err)
return err;
} }
/* test for false positives */ /* test for false positives */
for (idx=0; idx < MAX_IDX; idx++) { for (idx=0; idx < num_trials; idx++) {
rdb_check_expect_failure(&rdb, idx); err = rdb_check_expect_failure(&rdb, idx);
if (err)
return err;
} }
/* re-initialize */ /* re-initialize */
if (rdb_init(&rdb) != err_status_ok) { if (rdb_init(&rdb) != err_status_ok) {
printf("rdb_init failed\n"); printf("rdb_init failed\n");
exit(1); return err_status_fail;
} }
/* test non-sequential insertion */ /* test non-sequential insertion */
ut_init(&utc); ut_init(&utc);
for (idx=0; idx < MAX_IDX; idx++) { for (idx=0; idx < num_trials; idx++) {
ircvd = ut_next_index(&utc); ircvd = ut_next_index(&utc);
rdb_check_unordered(&rdb, ircvd); err = rdb_check_add_unordered(&rdb, ircvd);
if (err)
return err;
err = rdb_check_expect_failure(&rdb, ircvd);
if (err)
return err;
} }
/* re-initialize */
if (rdb_init(&rdb) != err_status_ok) {
printf("rdb_init failed\n");
return err_status_fail;
}
/* test insertion with large gaps */
for (idx=0, ircvd=0; idx < num_trials; idx++, ircvd += (1 << (rand() % 10))) {
err = rdb_check_add(&rdb, ircvd);
if (err)
return err;
err = rdb_check_expect_failure(&rdb, ircvd);
if (err)
return err;
}
/* re-initialize */
if (rdb_init(&rdb) != err_status_ok) {
printf("rdb_init failed\n");
return err_status_fail;
}
/* test loss of first 513 packets */
for (idx=0; idx < num_trials; idx++) {
err = rdb_check_add(&rdb, idx + 513);
if (err)
return err;
}
/* test for false positives */
for (idx=0; idx < num_trials + 513; idx++) {
err = rdb_check_expect_failure(&rdb, idx);
if (err)
return err;
}
return err_status_ok;
} }
#include <time.h> /* for clock() */ #include <time.h> /* for clock() */

BIN
libs/srtp/test/roc_driver Executable file

Binary file not shown.

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -138,6 +138,12 @@ roc_test(int num_trials) {
ref, local, est, ircvd, delta); ref, local, est, ircvd, delta);
#endif #endif
if (local + delta != est) {
printf(" *bad delta*: local %llu + delta %d != est %llu\n",
(unsigned long long)local, delta, (unsigned long long)est);
return err_status_algo_fail;
}
/* now update local xtd_seq_num_t as necessary */ /* now update local xtd_seq_num_t as necessary */
if (delta > 0) if (delta > 0)
index_advance(&local, delta); index_advance(&local, delta);

View File

@ -8,7 +8,7 @@
*/ */
#include "rtp.h" #include "rtp_priv.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -21,11 +21,11 @@
#define PRINT_DEBUG 0 /* set to 1 to print out debugging data */ #define PRINT_DEBUG 0 /* set to 1 to print out debugging data */
#define VERBOSE_DEBUG 0 /* set to 1 to print out more data */ #define VERBOSE_DEBUG 0 /* set to 1 to print out more data */
ssize_t int
rtp_sendto(rtp_sender_t *sender, const void* msg, int len) { rtp_sendto(rtp_sender_t sender, const void* msg, int len) {
int octets_sent; int octets_sent;
err_status_t stat; err_status_t stat;
int pkt_len = len + rtp_header_len; int pkt_len = len + RTP_HEADER_LEN;
/* marshal data */ /* marshal data */
strncpy(sender->message.body, msg, len); strncpy(sender->message.body, msg, len);
@ -61,14 +61,19 @@ rtp_sendto(rtp_sender_t *sender, const void* msg, int len) {
return octets_sent; return octets_sent;
} }
ssize_t int
rtp_recvfrom(rtp_receiver_t *receiver, void *msg, int *len) { rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len) {
int octets_recvd; int octets_recvd;
err_status_t stat; err_status_t stat;
octets_recvd = recvfrom(receiver->socket, (void *)&receiver->message, octets_recvd = recvfrom(receiver->socket, (void *)&receiver->message,
*len, 0, (struct sockaddr *) NULL, 0); *len, 0, (struct sockaddr *) NULL, 0);
if (octets_recvd == -1) {
*len = 0;
return -1;
}
/* verify rtp header */ /* verify rtp header */
if (receiver->message.header.version != 2) { if (receiver->message.header.version != 2) {
*len = 0; *len = 0;
@ -99,10 +104,10 @@ rtp_recvfrom(rtp_receiver_t *receiver, void *msg, int *len) {
} }
int int
rtp_sender_init(rtp_sender_t *sender, rtp_sender_init(rtp_sender_t sender,
int socket, int sock,
struct sockaddr_in addr, struct sockaddr_in addr,
uint32_t ssrc) { unsigned int ssrc) {
/* set header values */ /* set header values */
sender->message.header.ssrc = htonl(ssrc); sender->message.header.ssrc = htonl(ssrc);
@ -116,17 +121,17 @@ rtp_sender_init(rtp_sender_t *sender,
sender->message.header.cc = 0; sender->message.header.cc = 0;
/* set other stuff */ /* set other stuff */
sender->socket = socket; sender->socket = sock;
sender->addr = addr; sender->addr = addr;
return 0; return 0;
} }
int int
rtp_receiver_init(rtp_receiver_t *rcvr, rtp_receiver_init(rtp_receiver_t rcvr,
int socket, int sock,
struct sockaddr_in addr, struct sockaddr_in addr,
uint32_t ssrc) { unsigned int ssrc) {
/* set header values */ /* set header values */
rcvr->message.header.ssrc = htonl(ssrc); rcvr->message.header.ssrc = htonl(ssrc);
@ -140,11 +145,48 @@ rtp_receiver_init(rtp_receiver_t *rcvr,
rcvr->message.header.cc = 0; rcvr->message.header.cc = 0;
/* set other stuff */ /* set other stuff */
rcvr->socket = socket; rcvr->socket = sock;
rcvr->addr = addr; rcvr->addr = addr;
return 0; return 0;
} }
int
rtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy) {
return srtp_create(&sender->srtp_ctx, policy);
}
int
rtp_sender_deinit_srtp(rtp_sender_t sender) {
return srtp_dealloc(sender->srtp_ctx);
}
int
rtp_receiver_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy) {
return srtp_create(&sender->srtp_ctx, policy);
}
int
rtp_receiver_deinit_srtp(rtp_receiver_t sender) {
return srtp_dealloc(sender->srtp_ctx);
}
rtp_sender_t
rtp_sender_alloc(void) {
return (rtp_sender_t)malloc(sizeof(rtp_sender_ctx_t));
}
void
rtp_sender_dealloc(rtp_sender_t rtp_ctx) {
free(rtp_ctx);
}
rtp_receiver_t
rtp_receiver_alloc(void) {
return (rtp_receiver_t)malloc(sizeof(rtp_receiver_ctx_t));
}
void
rtp_receiver_dealloc(rtp_receiver_t rtp_ctx) {
return free(rtp_ctx);
}

View File

@ -16,7 +16,7 @@
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -52,13 +52,19 @@
#include "datatypes.h" #include "datatypes.h"
#include "getopt_s.h" /* for local getopt() */
#include <stdio.h> /* for printf, fprintf */ #include <stdio.h> /* for printf, fprintf */
#include <stdlib.h> /* for atoi() */ #include <stdlib.h> /* for atoi() */
#include <errno.h> #include <errno.h>
#include <unistd.h> /* for close() */ #include <signal.h> /* for signal() */
#include <string.h> /* for strncpy() */ #include <string.h> /* for strncpy() */
#include <time.h> /* for usleep() */ #include <time.h> /* for usleep() */
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for close() */
#endif
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
@ -113,6 +119,18 @@ void
leave_group(int sock, struct ip_mreq mreq, char *name); leave_group(int sock, struct ip_mreq mreq, char *name);
/*
* setup_signal_handler() sets up a signal handler to trigger
* cleanups after an interrupt
*/
int setup_signal_handler(char* name);
/*
* handle_signal(...) handles interrupt signal to trigger cleanups
*/
volatile int interrupted = 0;
/* /*
* program_type distinguishes the [s]rtp sender and receiver cases * program_type distinguishes the [s]rtp sender and receiver cases
*/ */
@ -156,6 +174,10 @@ main (int argc, char *argv[]) {
} }
#endif #endif
if (setup_signal_handler(argv[0]) != 0) {
exit(1);
}
/* initialize srtp library */ /* initialize srtp library */
status = srtp_init(); status = srtp_init();
if (status) { if (status) {
@ -165,13 +187,13 @@ main (int argc, char *argv[]) {
/* check args */ /* check args */
while (1) { while (1) {
c = getopt(argc, argv, "k:rsaeld:"); c = getopt_s(argc, argv, "k:rsaeld:");
if (c == -1) { if (c == -1) {
break; break;
} }
switch (c) { switch (c) {
case 'k': case 'k':
input_key = optarg; input_key = optarg_s;
break; break;
case 'e': case 'e':
sec_servs |= sec_serv_conf; sec_servs |= sec_serv_conf;
@ -186,9 +208,9 @@ main (int argc, char *argv[]) {
prog_type = sender; prog_type = sender;
break; break;
case 'd': case 'd':
status = crypto_kernel_set_debug_module(optarg, 1); status = crypto_kernel_set_debug_module(optarg_s, 1);
if (status) { if (status) {
printf("error: set debug module (%s) failed\n", optarg); printf("error: set debug module (%s) failed\n", optarg_s);
exit(1); exit(1);
} }
break; break;
@ -222,16 +244,16 @@ main (int argc, char *argv[]) {
usage(argv[0]); usage(argv[0]);
} }
if (argc != optind + 2) { if (argc != optind_s + 2) {
/* wrong number of arguments */ /* wrong number of arguments */
usage(argv[0]); usage(argv[0]);
} }
/* get address from arg */ /* get address from arg */
address = argv[optind++]; address = argv[optind_s++];
/* get port from arg */ /* get port from arg */
port = atoi(argv[optind++]); port = atoi(argv[optind_s++]);
/* set address */ /* set address */
#ifdef HAVE_INET_ATON #ifdef HAVE_INET_ATON
@ -261,7 +283,7 @@ main (int argc, char *argv[]) {
err = errno; err = errno;
#endif #endif
fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err); fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err);
exit(1); exit(1);
} }
name.sin_addr = rcvr_addr; name.sin_addr = rcvr_addr;
@ -327,7 +349,10 @@ main (int argc, char *argv[]) {
policy.ssrc.type = ssrc_specific; policy.ssrc.type = ssrc_specific;
policy.ssrc.value = ssrc; policy.ssrc.value = ssrc;
policy.key = (uint8_t *) key; policy.key = (uint8_t *) key;
policy.ekt = NULL;
policy.next = NULL; policy.next = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.rtp.sec_serv = sec_servs; policy.rtp.sec_serv = sec_servs;
policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */ policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */
@ -380,6 +405,9 @@ main (int argc, char *argv[]) {
policy.rtcp.auth_key_len = 0; policy.rtcp.auth_key_len = 0;
policy.rtcp.auth_tag_len = 0; policy.rtcp.auth_tag_len = 0;
policy.rtcp.sec_serv = sec_serv_none; policy.rtcp.sec_serv = sec_serv_none;
policy.window_size = 0;
policy.allow_repeat_tx = 0;
policy.ekt = NULL;
policy.next = NULL; policy.next = NULL;
} }
@ -399,8 +427,13 @@ main (int argc, char *argv[]) {
#endif /* BEW */ #endif /* BEW */
/* initialize sender's rtp and srtp contexts */ /* initialize sender's rtp and srtp contexts */
rtp_sender_init(&snd, sock, name, ssrc); snd = rtp_sender_alloc();
status = srtp_create(&snd.srtp_ctx, &policy); if (snd == NULL) {
fprintf(stderr, "error: malloc() failed\n");
exit(1);
}
rtp_sender_init(snd, sock, name, ssrc);
status = rtp_sender_init_srtp(snd, &policy);
if (status) { if (status) {
fprintf(stderr, fprintf(stderr,
"error: srtp_create() failed with code %d\n", "error: srtp_create() failed with code %d\n",
@ -419,18 +452,22 @@ main (int argc, char *argv[]) {
} }
/* read words from dictionary, then send them off */ /* read words from dictionary, then send them off */
while (fgets(word, MAX_WORD_LEN, dict) != NULL) { while (!interrupted && fgets(word, MAX_WORD_LEN, dict) != NULL) {
len = strlen(word) + 1; /* plus one for null */ len = strlen(word) + 1; /* plus one for null */
if (len > MAX_WORD_LEN) if (len > MAX_WORD_LEN)
printf("error: word %s too large to send\n", word); printf("error: word %s too large to send\n", word);
else { else {
rtp_sendto(&snd, word, len); rtp_sendto(snd, word, len);
printf("sending word: %s", word); printf("sending word: %s", word);
} }
usleep(USEC_RATE); usleep(USEC_RATE);
} }
rtp_sender_deinit_srtp(snd);
rtp_sender_dealloc(snd);
fclose(dict);
} else { /* prog_type == receiver */ } else { /* prog_type == receiver */
rtp_receiver_t rcvr; rtp_receiver_t rcvr;
@ -444,8 +481,13 @@ main (int argc, char *argv[]) {
exit(1); exit(1);
} }
rtp_receiver_init(&rcvr, sock, name, ssrc); rcvr = rtp_receiver_alloc();
status = srtp_create(&rcvr.srtp_ctx, &policy); if (rcvr == NULL) {
fprintf(stderr, "error: malloc() failed\n");
exit(1);
}
rtp_receiver_init(rcvr, sock, name, ssrc);
status = rtp_receiver_init_srtp(rcvr, &policy);
if (status) { if (status) {
fprintf(stderr, fprintf(stderr,
"error: srtp_create() failed with code %d\n", "error: srtp_create() failed with code %d\n",
@ -454,18 +496,36 @@ main (int argc, char *argv[]) {
} }
/* get next word and loop */ /* get next word and loop */
while (1) { while (!interrupted) {
len = MAX_WORD_LEN; len = MAX_WORD_LEN;
if (rtp_recvfrom(&rcvr, word, &len) > -1) if (rtp_recvfrom(rcvr, word, &len) > -1)
printf("\tword: %s", word); printf("\tword: %s\n", word);
} }
rtp_receiver_deinit_srtp(rcvr);
rtp_receiver_dealloc(rcvr);
} }
if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) { if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
leave_group(sock, mreq, argv[0]); leave_group(sock, mreq, argv[0]);
} }
#ifdef RTPW_USE_WINSOCK2
ret = closesocket(sock);
#else
ret = close(sock);
#endif
if (ret < 0) {
fprintf(stderr, "%s: Failed to close socket", argv[0]);
perror("");
}
status = srtp_shutdown();
if (status) {
printf("error: srtp shutdown failed with error code %d\n", status);
exit(1);
}
#ifdef RTPW_USE_WINSOCK2 #ifdef RTPW_USE_WINSOCK2
WSACleanup(); WSACleanup();
#endif #endif
@ -505,3 +565,41 @@ leave_group(int sock, struct ip_mreq mreq, char *name) {
} }
} }
void handle_signal(int signum)
{
interrupted = 1;
/* Reset handler explicitly, in case we don't have sigaction() (and signal()
has BSD semantics), or we don't have SA_RESETHAND */
signal(signum, SIG_DFL);
}
int setup_signal_handler(char* name)
{
#if HAVE_SIGACTION
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = handle_signal;
sigemptyset(&act.sa_mask);
#if defined(SA_RESETHAND)
act.sa_flags = SA_RESETHAND;
#else
act.sa_flags = 0;
#endif
/* Note that we're not setting SA_RESTART; we want recvfrom to return
* EINTR when we signal the receiver. */
if (sigaction(SIGTERM, &act, NULL) != 0) {
fprintf(stderr, "%s: error setting up signal handler", name);
perror("");
return -1;
}
#else
if (signal(SIGTERM, handle_signal) == SIG_ERR) {
fprintf(stderr, "%s: error setting up signal handler", name);
perror("");
return -1;
}
#endif
return 0;
}

80
libs/srtp/test/rtpw_test.sh Executable file
View File

@ -0,0 +1,80 @@
#!/bin/sh
#
# usage: rtpw_test <rtpw_commands>
#
# tests the rtpw sender and receiver functions
RTPW=./rtpw
DEST_PORT=9999
DURATION=3
key=2b2edc5034f61a72345ca5986d7bfd0189aa6dc2ecab32fd9af74df6dfc6
ARGS="-k $key -ae"
# First, we run "killall" to get rid of all existing rtpw processes.
# This step also enables this script to clean up after itself; if this
# script is interrupted after the rtpw processes are started but before
# they are killed, those processes will linger. Re-running the script
# will get rid of them.
killall rtpw 2>/dev/null
if test -x $RTPW; then
echo $0 ": starting rtpw receiver process... "
$RTPW $* $ARGS -r 0.0.0.0 $DEST_PORT &
receiver_pid=$!
echo $0 ": receiver PID = $receiver_pid"
sleep 1
# verify that the background job is running
ps | grep -q $receiver_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 254
fi
echo $0 ": starting rtpw sender process..."
$RTPW $* $ARGS -s 127.0.0.1 $DEST_PORT &
sender_pid=$!
echo $0 ": sender PID = $sender_pid"
# verify that the background job is running
ps | grep -q $sender_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 255
fi
sleep $DURATION
kill $receiver_pid
kill $sender_pid
wait $receiver_pid
wait $sender_pid
echo $0 ": done (test passed)"
else
echo "error: can't find executable" $RTPW
exit 1
fi
# EOF

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2005, Cisco Systems, Inc. * Copyright (c) 2001-2006, Cisco Systems, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -47,9 +47,9 @@
#include <time.h> /* for clock() */ #include <time.h> /* for clock() */
#include <stdlib.h> /* for malloc(), free() */ #include <stdlib.h> /* for malloc(), free() */
#include <stdio.h> /* for print(), fflush() */ #include <stdio.h> /* for print(), fflush() */
#include <unistd.h> /* for getopt() */ #include "getopt_s.h" /* for local getopt() */
#include "srtp.h" #include "srtp_priv.h"
#ifdef HAVE_NETINET_IN_H #ifdef HAVE_NETINET_IN_H
# include <netinet/in.h> # include <netinet/in.h>
@ -62,9 +62,15 @@
err_status_t err_status_t
srtp_validate(void); srtp_validate(void);
err_status_t
srtp_validate_aes_256(void);
err_status_t err_status_t
srtp_create_big_policy(srtp_policy_t **list); srtp_create_big_policy(srtp_policy_t **list);
err_status_t
srtp_dealloc_big_policy(srtp_policy_t *list);
err_status_t err_status_t
srtp_test_remove_stream(void); srtp_test_remove_stream(void);
@ -83,6 +89,9 @@ srtp_do_rejection_timing(const srtp_policy_t *policy);
err_status_t err_status_t
srtp_test(const srtp_policy_t *policy); srtp_test(const srtp_policy_t *policy);
err_status_t
srtcp_test(const srtp_policy_t *policy);
err_status_t err_status_t
srtp_session_print_policy(srtp_t srtp); srtp_session_print_policy(srtp_t srtp);
@ -135,7 +144,7 @@ debug_module_t mod_driver = {
int int
main (int argc, char *argv[]) { main (int argc, char *argv[]) {
char q; int q;
unsigned do_timing_test = 0; unsigned do_timing_test = 0;
unsigned do_rejection_test = 0; unsigned do_rejection_test = 0;
unsigned do_codec_timing = 0; unsigned do_codec_timing = 0;
@ -148,7 +157,9 @@ main (int argc, char *argv[]) {
* structure srtp_hdr_t correctly * structure srtp_hdr_t correctly
*/ */
if (sizeof(srtp_hdr_t) != 12) { if (sizeof(srtp_hdr_t) != 12) {
printf("error: srtp_hdr_t has incorrect size\n"); printf("error: srtp_hdr_t has incorrect size"
"(size is %ld bytes, expected 12)\n",
(long)sizeof(srtp_hdr_t));
exit(1); exit(1);
} }
@ -169,7 +180,7 @@ main (int argc, char *argv[]) {
/* process input arguments */ /* process input arguments */
while (1) { while (1) {
q = getopt(argc, argv, "trcvld:"); q = getopt_s(argc, argv, "trcvld:");
if (q == -1) if (q == -1)
break; break;
switch (q) { switch (q) {
@ -189,9 +200,9 @@ main (int argc, char *argv[]) {
do_list_mods = 1; do_list_mods = 1;
break; break;
case 'd': case 'd':
status = crypto_kernel_set_debug_module(optarg, 1); status = crypto_kernel_set_debug_module(optarg_s, 1);
if (status) { if (status) {
printf("error: set debug module (%s) failed\n", optarg); printf("error: set debug module (%s) failed\n", optarg_s);
exit(1); exit(1);
} }
break; break;
@ -216,7 +227,7 @@ main (int argc, char *argv[]) {
const srtp_policy_t **policy = policy_array; const srtp_policy_t **policy = policy_array;
srtp_policy_t *big_policy; srtp_policy_t *big_policy;
/* loop over policy array, testing srtp for each policy */ /* loop over policy array, testing srtp and srtcp for each policy */
while (*policy != NULL) { while (*policy != NULL) {
printf("testing srtp_protect and srtp_unprotect\n"); printf("testing srtp_protect and srtp_unprotect\n");
if (srtp_test(*policy) == err_status_ok) if (srtp_test(*policy) == err_status_ok)
@ -225,6 +236,13 @@ main (int argc, char *argv[]) {
printf("failed\n"); printf("failed\n");
exit(1); exit(1);
} }
printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n");
if (srtcp_test(*policy) == err_status_ok)
printf("passed\n\n");
else {
printf("failed\n");
exit(1);
}
policy++; policy++;
} }
@ -241,6 +259,11 @@ main (int argc, char *argv[]) {
printf("failed\n"); printf("failed\n");
exit(1); exit(1);
} }
status = srtp_dealloc_big_policy(big_policy);
if (status) {
printf("unexpected failure with error code %d\n", status);
exit(1);
}
/* run test on wildcard policy */ /* run test on wildcard policy */
printf("testing srtp_protect and srtp_unprotect on " printf("testing srtp_protect and srtp_unprotect on "
@ -265,6 +288,19 @@ main (int argc, char *argv[]) {
exit(1); exit(1);
} }
/*
* run validation test against the reference packets for
* AES-256
*/
printf("testing srtp_protect and srtp_unprotect against "
"reference packets (AES-256)\n");
if (srtp_validate_aes_256() == err_status_ok)
printf("passed\n\n");
else {
printf("failed\n");
exit(1);
}
/* /*
* test the function srtp_remove_stream() * test the function srtp_remove_stream()
*/ */
@ -309,6 +345,9 @@ main (int argc, char *argv[]) {
policy.ssrc.type = ssrc_specific; policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xdecafbad; policy.ssrc.value = 0xdecafbad;
policy.key = test_key; policy.key = test_key;
policy.ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL; policy.next = NULL;
printf("mips estimate: %e\n", mips); printf("mips estimate: %e\n", mips);
@ -333,6 +372,18 @@ main (int argc, char *argv[]) {
printf("G.729\t\t%d\t\t\t%e\n", 20, printf("G.729\t\t%d\t\t\t%e\n", 20,
(double) mips * (20 * 8) / (double) mips * (20 * 8) /
srtp_bits_per_second(20, &policy) / .02 ); srtp_bits_per_second(20, &policy) / .02 );
printf("Wideband\t%d\t\t\t%e\n", 320,
(double) mips * (320 * 8) /
srtp_bits_per_second(320, &policy) / .01 );
printf("Wideband\t%d\t\t\t%e\n", 640,
(double) mips * (640 * 8) /
srtp_bits_per_second(640, &policy) / .02 );
}
status = srtp_shutdown();
if (status) {
printf("error: srtp shutdown failed with error code %d\n", status);
exit(1);
} }
return 0; return 0;
@ -361,7 +412,7 @@ srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc) {
int bytes_in_hdr = 12; int bytes_in_hdr = 12;
/* allocate memory for test packet */ /* allocate memory for test packet */
hdr = malloc(pkt_octet_len + bytes_in_hdr hdr = (srtp_hdr_t*) malloc(pkt_octet_len + bytes_in_hdr
+ SRTP_MAX_TRAILER_LEN + 4); + SRTP_MAX_TRAILER_LEN + 4);
if (!hdr) if (!hdr)
return NULL; return NULL;
@ -474,7 +525,6 @@ srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) {
timer = clock(); timer = clock();
for (i=0; i < num_trials; i++) { for (i=0; i < num_trials; i++) {
err_status_t status;
len = msg_len_octets + 12; /* add in rtp header length */ len = msg_len_octets + 12; /* add in rtp header length */
/* srtp protect message */ /* srtp protect message */
@ -485,12 +535,21 @@ srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) {
} }
/* increment message number */ /* increment message number */
mesg->seq = htons(ntohs(mesg->seq) + 1); {
/* hack sequence to avoid problems with macros for htons/ntohs on some systems */
short new_seq = ntohs(mesg->seq) + 1;
mesg->seq = htons(new_seq);
}
} }
timer = clock() - timer; timer = clock() - timer;
free(mesg); free(mesg);
status = srtp_dealloc(srtp);
if (status) {
printf("error: srtp_dealloc() failed with error code %d\n", status);
exit(1);
}
return (double) (msg_len_octets) * 8 * return (double) (msg_len_octets) * 8 *
num_trials * CLOCKS_PER_SEC / timer; num_trials * CLOCKS_PER_SEC / timer;
@ -531,7 +590,13 @@ srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy) {
timer = clock() - timer; timer = clock() - timer;
free(mesg); free(mesg);
status = srtp_dealloc(srtp);
if (status) {
printf("error: srtp_dealloc() failed with error code %d\n", status);
exit(1);
}
return (double) num_trials * CLOCKS_PER_SEC / timer; return (double) num_trials * CLOCKS_PER_SEC / timer;
} }
@ -659,9 +724,12 @@ srtp_test(const srtp_policy_t *policy) {
* we always copy the policy into the rcvr_policy, since otherwise * we always copy the policy into the rcvr_policy, since otherwise
* the compiler would fret about the constness of the policy * the compiler would fret about the constness of the policy
*/ */
rcvr_policy = malloc(sizeof(srtp_policy_t)); rcvr_policy = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
if (rcvr_policy == NULL) if (rcvr_policy == NULL) {
free(hdr);
free(hdr2);
return err_status_alloc_fail; return err_status_alloc_fail;
}
memcpy(rcvr_policy, policy, sizeof(srtp_policy_t)); memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
if (policy->ssrc.type == ssrc_any_outbound) { if (policy->ssrc.type == ssrc_any_outbound) {
rcvr_policy->ssrc.type = ssrc_any_inbound; rcvr_policy->ssrc.type = ssrc_any_inbound;
@ -683,6 +751,7 @@ srtp_test(const srtp_policy_t *policy) {
if (status) { if (status) {
free(hdr); free(hdr);
free(hdr2); free(hdr2);
free(rcvr_policy);
return status; return status;
} }
@ -703,6 +772,7 @@ srtp_test(const srtp_policy_t *policy) {
printf("failed with error code %d\n", status); printf("failed with error code %d\n", status);
free(hdr); free(hdr);
free(hdr2); free(hdr2);
free(rcvr_policy);
return status; return status;
} else { } else {
printf("passed\n"); printf("passed\n");
@ -728,6 +798,7 @@ srtp_test(const srtp_policy_t *policy) {
printf("failed\n"); printf("failed\n");
free(hdr); free(hdr);
free(hdr2); free(hdr2);
free(rcvr_policy);
return status; return status;
} else { } else {
printf("passed\n"); printf("passed\n");
@ -740,6 +811,210 @@ srtp_test(const srtp_policy_t *policy) {
free(hdr); free(hdr);
free(hdr2); free(hdr2);
free(rcvr_policy);
return err_status_ok;
}
err_status_t
srtcp_test(const srtp_policy_t *policy) {
int i;
srtp_t srtcp_sender;
srtp_t srtcp_rcvr;
err_status_t status = err_status_ok;
srtp_hdr_t *hdr, *hdr2;
uint8_t hdr_enc[64];
uint8_t *pkt_end;
int msg_len_octets, msg_len_enc;
int len;
int tag_length = policy->rtp.auth_tag_len;
uint32_t ssrc;
srtp_policy_t *rcvr_policy;
err_check(srtp_create(&srtcp_sender, policy));
/* print out policy */
err_check(srtp_session_print_policy(srtcp_sender));
/*
* initialize data buffer, using the ssrc in the policy unless that
* value is a wildcard, in which case we'll just use an arbitrary
* one
*/
if (policy->ssrc.type != ssrc_specific)
ssrc = 0xdecafbad;
else
ssrc = policy->ssrc.value;
msg_len_octets = 28;
hdr = srtp_create_test_packet(msg_len_octets, ssrc);
if (hdr == NULL)
return err_status_alloc_fail;
hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
if (hdr2 == NULL) {
free(hdr);
return err_status_alloc_fail;
}
/* set message length */
len = msg_len_octets;
debug_print(mod_driver, "before protection:\n%s",
srtp_packet_to_string(hdr, len));
#if PRINT_REFERENCE_PACKET
debug_print(mod_driver, "reference packet before protection:\n%s",
octet_string_hex_string((uint8_t *)hdr, len));
#endif
err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
debug_print(mod_driver, "after protection:\n%s",
srtp_packet_to_string(hdr, len));
#if PRINT_REFERENCE_PACKET
debug_print(mod_driver, "after protection:\n%s",
octet_string_hex_string((uint8_t *)hdr, len));
#endif
/* save protected message and length */
memcpy(hdr_enc, hdr, len);
msg_len_enc = len;
/*
* check for overrun of the srtp_protect() function
*
* The packet is followed by a value of 0xfffff; if the value of the
* data following the packet is different, then we know that the
* protect function is overwriting the end of the packet.
*/
pkt_end = (uint8_t *)hdr + sizeof(srtp_hdr_t)
+ msg_len_octets + tag_length;
for (i = 0; i < 4; i++)
if (pkt_end[i] != 0xff) {
fprintf(stdout, "overwrite in srtp_protect_rtcp() function "
"(expected %x, found %x in trailing octet %d)\n",
0xff, ((uint8_t *)hdr)[i], i);
free(hdr);
free(hdr2);
return err_status_algo_fail;
}
/*
* if the policy includes confidentiality, check that ciphertext is
* different than plaintext
*
* Note that this check will give false negatives, with some small
* probability, especially if the packets are short. For that
* reason, we skip this check if the plaintext is less than four
* octets long.
*/
if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
printf("testing that ciphertext is distinct from plaintext...");
status = err_status_algo_fail;
for (i=12; i < msg_len_octets+12; i++)
if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
status = err_status_ok;
}
if (status) {
printf("failed\n");
free(hdr);
free(hdr2);
return status;
}
printf("passed\n");
}
/*
* if the policy uses a 'wildcard' ssrc, then we need to make a copy
* of the policy that changes the direction to inbound
*
* we always copy the policy into the rcvr_policy, since otherwise
* the compiler would fret about the constness of the policy
*/
rcvr_policy = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
if (rcvr_policy == NULL)
return err_status_alloc_fail;
memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
if (policy->ssrc.type == ssrc_any_outbound) {
rcvr_policy->ssrc.type = ssrc_any_inbound;
}
err_check(srtp_create(&srtcp_rcvr, rcvr_policy));
err_check(srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len));
debug_print(mod_driver, "after unprotection:\n%s",
srtp_packet_to_string(hdr, len));
/* verify that the unprotected packet matches the origial one */
for (i=0; i < msg_len_octets; i++)
if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
fprintf(stdout, "mismatch at octet %d\n", i);
status = err_status_algo_fail;
}
if (status) {
free(hdr);
free(hdr2);
free(rcvr_policy);
return status;
}
/*
* if the policy includes authentication, then test for false positives
*/
if (policy->rtp.sec_serv & sec_serv_auth) {
char *data = ((char *)hdr) + 12;
printf("testing for false positives in replay check...");
/* set message length */
len = msg_len_enc;
/* unprotect a second time - should fail with a replay error */
status = srtp_unprotect_rtcp(srtcp_rcvr, hdr_enc, &len);
if (status != err_status_replay_fail) {
printf("failed with error code %d\n", status);
free(hdr);
free(hdr2);
free(rcvr_policy);
return status;
} else {
printf("passed\n");
}
printf("testing for false positives in auth check...");
/* increment sequence number in header */
hdr->seq++;
/* set message length */
len = msg_len_octets;
/* apply protection */
err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len));
/* flip bits in packet */
data[0] ^= 0xff;
/* unprotect, and check for authentication failure */
status = srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len);
if (status != err_status_auth_fail) {
printf("failed\n");
free(hdr);
free(hdr2);
free(rcvr_policy);
return status;
} else {
printf("passed\n");
}
}
err_check(srtp_dealloc(srtcp_sender));
err_check(srtp_dealloc(srtcp_rcvr));
free(hdr);
free(hdr2);
free(rcvr_policy);
return err_status_ok; return err_status_ok;
} }
@ -772,14 +1047,18 @@ srtp_session_print_policy(srtp_t srtp) {
"# rtp services: %s\r\n" "# rtp services: %s\r\n"
"# rtcp cipher: %s\r\n" "# rtcp cipher: %s\r\n"
"# rtcp auth: %s\r\n" "# rtcp auth: %s\r\n"
"# rtcp services: %s\r\n", "# rtcp services: %s\r\n"
"# window size: %lu\r\n"
"# tx rtx allowed:%s\r\n",
direction[stream->direction], direction[stream->direction],
stream->rtp_cipher->type->description, stream->rtp_cipher->type->description,
stream->rtp_auth->type->description, stream->rtp_auth->type->description,
serv_descr[stream->rtp_services], serv_descr[stream->rtp_services],
stream->rtcp_cipher->type->description, stream->rtcp_cipher->type->description,
stream->rtcp_auth->type->description, stream->rtcp_auth->type->description,
serv_descr[stream->rtcp_services]); serv_descr[stream->rtcp_services],
rdbx_get_window_size(&stream->rtp_rdbx),
stream->allow_repeat_tx ? "true" : "false");
} }
/* loop over streams in session, printing the policy of each */ /* loop over streams in session, printing the policy of each */
@ -794,14 +1073,18 @@ srtp_session_print_policy(srtp_t srtp) {
"# rtp services: %s\r\n" "# rtp services: %s\r\n"
"# rtcp cipher: %s\r\n" "# rtcp cipher: %s\r\n"
"# rtcp auth: %s\r\n" "# rtcp auth: %s\r\n"
"# rtcp services: %s\r\n", "# rtcp services: %s\r\n"
"# window size: %lu\r\n"
"# tx rtx allowed:%s\r\n",
stream->ssrc, stream->ssrc,
stream->rtp_cipher->type->description, stream->rtp_cipher->type->description,
stream->rtp_auth->type->description, stream->rtp_auth->type->description,
serv_descr[stream->rtp_services], serv_descr[stream->rtp_services],
stream->rtcp_cipher->type->description, stream->rtcp_cipher->type->description,
stream->rtcp_auth->type->description, stream->rtcp_auth->type->description,
serv_descr[stream->rtcp_services]); serv_descr[stream->rtcp_services],
rdbx_get_window_size(&stream->rtp_rdbx),
stream->allow_repeat_tx ? "true" : "false");
/* advance to next stream in the list */ /* advance to next stream in the list */
stream = stream->next; stream = stream->next;
@ -891,7 +1174,7 @@ srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) {
double double
mips_estimate(int num_trials, int *ignore) { mips_estimate(int num_trials, int *ignore) {
clock_t t; clock_t t;
int i, sum; volatile int i, sum;
sum = 0; sum = 0;
t = clock(); t = clock();
@ -915,12 +1198,6 @@ mips_estimate(int num_trials, int *ignore) {
err_status_t err_status_t
srtp_validate() { srtp_validate() {
unsigned char test_key[30] = {
0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
};
uint8_t srtp_plaintext_ref[28] = { uint8_t srtp_plaintext_ref[28] = {
0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab, 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
@ -955,6 +1232,9 @@ srtp_validate() {
policy.ssrc.type = ssrc_specific; policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe; policy.ssrc.value = 0xcafebabe;
policy.key = test_key; policy.key = test_key;
policy.ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL; policy.next = NULL;
status = srtp_create(&srtp_snd, &policy); status = srtp_create(&srtp_snd, &policy);
@ -996,6 +1276,122 @@ srtp_validate() {
if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
return err_status_fail; return err_status_fail;
status = srtp_dealloc(srtp_snd);
if (status)
return status;
status = srtp_dealloc(srtp_recv);
if (status)
return status;
return err_status_ok;
}
/*
* srtp_validate_aes_256() verifies the correctness of libsrtp by comparing
* some computed packets against some pre-computed reference values.
* These packets were made with the AES-CM-256/HMAC-SHA-1-80 policy.
*/
err_status_t
srtp_validate_aes_256() {
unsigned char aes_256_test_key[46] = {
0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76,
0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29,
0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1,
0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6,
0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9,
0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2
};
uint8_t srtp_plaintext_ref[28] = {
0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab
};
uint8_t srtp_plaintext[38] = {
0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t srtp_ciphertext[38] = {
0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
0xca, 0xfe, 0xba, 0xbe, 0xf1, 0xd9, 0xde, 0x17,
0xff, 0x25, 0x1f, 0xf1, 0xaa, 0x00, 0x77, 0x74,
0xb0, 0xb4, 0xb4, 0x0d, 0xa0, 0x8d, 0x9d, 0x9a,
0x5b, 0x3a, 0x55, 0xd8, 0x87, 0x3b
};
srtp_t srtp_snd, srtp_recv;
err_status_t status;
int len;
srtp_policy_t policy;
/*
* create a session with a single stream using the default srtp
* policy and with the SSRC value 0xcafebabe
*/
crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtcp);
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = aes_256_test_key;
policy.ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
status = srtp_create(&srtp_snd, &policy);
if (status)
return status;
/*
* protect plaintext, then compare with ciphertext
*/
len = 28;
status = srtp_protect(srtp_snd, srtp_plaintext, &len);
if (status || (len != 38))
return err_status_fail;
debug_print(mod_driver, "ciphertext:\n %s",
octet_string_hex_string(srtp_plaintext, len));
debug_print(mod_driver, "ciphertext reference:\n %s",
octet_string_hex_string(srtp_ciphertext, len));
if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
return err_status_fail;
/*
* create a receiver session context comparable to the one created
* above - we need to do this so that the replay checking doesn't
* complain
*/
status = srtp_create(&srtp_recv, &policy);
if (status)
return status;
/*
* unprotect ciphertext, then compare with plaintext
*/
status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
if (status || (len != 28))
return status;
if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
return err_status_fail;
status = srtp_dealloc(srtp_snd);
if (status)
return status;
status = srtp_dealloc(srtp_recv);
if (status)
return status;
return err_status_ok; return err_status_ok;
} }
@ -1017,7 +1413,7 @@ srtp_create_big_policy(srtp_policy_t **list) {
*/ */
tmp = NULL; tmp = NULL;
while (policy_array[i] != NULL) { while (policy_array[i] != NULL) {
p = malloc(sizeof(srtp_policy_t)); p = (srtp_policy_t*) malloc(sizeof(srtp_policy_t));
if (p == NULL) if (p == NULL)
return err_status_bad_param; return err_status_bad_param;
memcpy(p, policy_array[i], sizeof(srtp_policy_t)); memcpy(p, policy_array[i], sizeof(srtp_policy_t));
@ -1032,10 +1428,23 @@ srtp_create_big_policy(srtp_policy_t **list) {
return err_status_ok; return err_status_ok;
} }
err_status_t
srtp_dealloc_big_policy(srtp_policy_t *list) {
srtp_policy_t *p, *next;
for (p = list; p != NULL; p = next) {
next = p->next;
free(p);
}
return err_status_ok;
}
err_status_t err_status_t
srtp_test_remove_stream() { srtp_test_remove_stream() {
err_status_t status; err_status_t status;
srtp_policy_t *policy_list; srtp_policy_t *policy_list, policy;
srtp_t session; srtp_t session;
srtp_stream_t stream; srtp_stream_t stream;
/* /*
@ -1076,6 +1485,41 @@ srtp_test_remove_stream() {
if (stream == NULL) if (stream == NULL)
return err_status_fail; return err_status_fail;
status = srtp_dealloc(session);
if (status != err_status_ok)
return status;
status = srtp_dealloc_big_policy(policy_list);
if (status != err_status_ok)
return status;
/* Now test adding and removing a single stream */
crypto_policy_set_rtp_default(&policy.rtp);
crypto_policy_set_rtcp_default(&policy.rtcp);
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = 0xcafebabe;
policy.key = test_key;
policy.ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
status = srtp_create(&session, NULL);
if (status != err_status_ok)
return status;
status = srtp_add_stream(session, &policy);
if (status != err_status_ok)
return status;
status = srtp_remove_stream(session, htonl(0xcafebabe));
if (status != err_status_ok)
return status;
status = srtp_dealloc(session);
if (status != err_status_ok)
return status;
return err_status_ok; return err_status_ok;
} }
@ -1110,6 +1554,9 @@ const srtp_policy_t default_policy = {
sec_serv_conf_and_auth /* security services flag */ sec_serv_conf_and_auth /* security services flag */
}, },
test_key, test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL NULL
}; };
@ -1132,6 +1579,9 @@ const srtp_policy_t aes_tmmh_policy = {
sec_serv_conf_and_auth /* security services flag */ sec_serv_conf_and_auth /* security services flag */
}, },
test_key, test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL NULL
}; };
@ -1154,6 +1604,9 @@ const srtp_policy_t tmmh_only_policy = {
sec_serv_auth /* security services flag */ sec_serv_auth /* security services flag */
}, },
test_key, test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL NULL
}; };
@ -1176,6 +1629,9 @@ const srtp_policy_t aes_only_policy = {
sec_serv_conf /* security services flag */ sec_serv_conf /* security services flag */
}, },
test_key, test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL NULL
}; };
@ -1198,6 +1654,9 @@ const srtp_policy_t hmac_only_policy = {
sec_serv_auth /* security services flag */ sec_serv_auth /* security services flag */
}, },
test_key, test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL NULL
}; };
@ -1220,6 +1679,83 @@ const srtp_policy_t null_policy = {
sec_serv_none /* security services flag */ sec_serv_none /* security services flag */
}, },
test_key, test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL
};
unsigned char test_256_key[46] = {
0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76,
0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29,
0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1,
0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6,
0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9,
0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2
};
const srtp_policy_t aes_256_hmac_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{ /* SRTP policy */
AES_ICM, /* cipher type */
46, /* cipher key length in octets */
HMAC_SHA1, /* authentication func type */
20, /* auth key length in octets */
10, /* auth tag length in octets */
sec_serv_conf_and_auth /* security services flag */
},
{ /* SRTCP policy */
AES_ICM, /* cipher type */
46, /* cipher key length in octets */
HMAC_SHA1, /* authentication func type */
20, /* auth key length in octets */
10, /* auth tag length in octets */
sec_serv_conf_and_auth /* security services flag */
},
test_256_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL
};
uint8_t ekt_test_key[16] = {
0x77, 0x26, 0x9d, 0xac, 0x16, 0xa3, 0x28, 0xca,
0x8e, 0xc9, 0x68, 0x4b, 0xcc, 0xc4, 0xd2, 0x1b
};
#include "ekt.h"
ekt_policy_ctx_t ekt_test_policy = {
0xa5a5, /* SPI */
EKT_CIPHER_AES_128_ECB,
ekt_test_key,
NULL
};
const srtp_policy_t hmac_only_with_ekt_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{
NULL_CIPHER, /* cipher type */
0, /* cipher key length in octets */
HMAC_SHA1, /* authentication func type */
20, /* auth key length in octets */
4, /* auth tag length in octets */
sec_serv_auth /* security services flag */
},
{
NULL_CIPHER, /* cipher type */
0, /* cipher key length in octets */
HMAC_SHA1, /* authentication func type */
20, /* auth key length in octets */
4, /* auth tag length in octets */
sec_serv_auth /* security services flag */
},
test_key,
&ekt_test_policy, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL NULL
}; };
@ -1248,6 +1784,8 @@ policy_array[] = {
#endif #endif
&default_policy, &default_policy,
&null_policy, &null_policy,
&aes_256_hmac_policy,
&hmac_only_with_ekt_policy,
NULL NULL
}; };
@ -1270,5 +1808,8 @@ const srtp_policy_t wildcard_policy = {
sec_serv_conf_and_auth /* security services flag */ sec_serv_conf_and_auth /* security services flag */
}, },
test_key, test_key,
NULL,
128, /* replay window size */
0, /* retransmission not allowed */
NULL NULL
}; };

View File

@ -6,7 +6,7 @@
a=`find . -name "*.[ch]"` a=`find . -name "*.[ch]"`
for x in $a; do for x in $a; do
sed 's/(c) 2001-2004/(c) 2001-2005/' $x > $x.tmp; sed 's/(c) 2001-2005/(c) 2001-2006/' $x > $x.tmp;
mv $x.tmp $x; mv $x.tmp $x;
done done

View File

@ -47,6 +47,7 @@
#undef inline #undef inline
#include <datatypes.h> #include <datatypes.h>
#include <srtp.h> #include <srtp.h>
#include <srtp_priv.h>
#include <switch_version.h> #include <switch_version.h>
#define READ_INC(rtp_session) switch_mutex_lock(rtp_session->read_mutex); rtp_session->reading++ #define READ_INC(rtp_session) switch_mutex_lock(rtp_session->read_mutex); rtp_session->reading++