update libsrtp to use openssl

This commit is contained in:
Michael Jerris 2014-02-24 09:20:03 -05:00
parent 365f81b412
commit 80c7eb85e6
36 changed files with 3541 additions and 197 deletions

View File

@ -5,28 +5,37 @@ AM_CFLAGS = $(new_AM_CFLAGS) -I./src -Icrypto/include -I$(srcdir)/include -I$
AM_CPPFLAGS = $(AM_CFLAGS) AM_CPPFLAGS = $(AM_CFLAGS)
AM_LDFLAGS = $(new_AM_LDFLAGS) -L. AM_LDFLAGS = $(new_AM_LDFLAGS) -L.
HMAC_OBJS = @HMAC_OBJS@
RNG_EXTRA_OBJS = @RNG_EXTRA_OBJS@
AES_ICM_OBJS = @AES_ICM_OBJS@
lib_LTLIBRARIES = libsrtp.la libcryptomath.la lib_LTLIBRARIES = libsrtp.la libcryptomath.la
libsrtp_la_SOURCES = srtp/srtp.c srtp/ekt.c crypto/cipher/cipher.c crypto/cipher/null_cipher.c \ libsrtp_la_SOURCES = srtp/srtp.c srtp/ekt.c crypto/cipher/cipher.c crypto/cipher/null_cipher.c \
crypto/cipher/aes.c crypto/cipher/aes_icm.c \ crypto/hash/null_auth.c crypto/hash/auth.c \
crypto/cipher/aes_cbc.c \
crypto/hash/null_auth.c crypto/hash/sha1.c \
crypto/hash/hmac.c crypto/hash/auth.c \
crypto/math/datatypes.c crypto/math/stat.c \ crypto/math/datatypes.c crypto/math/stat.c \
crypto/kernel/crypto_kernel.c crypto/kernel/alloc.c \ crypto/kernel/crypto_kernel.c crypto/kernel/alloc.c \
crypto/kernel/key.c \ crypto/kernel/key.c \
crypto/rng/prng.c crypto/rng/ctr_prng.c \ crypto/rng/prng.c crypto/rng/ctr_prng.c \
crypto/kernel/err.c \ crypto/kernel/err.c \
crypto/replay/rdb.c crypto/replay/rdbx.c crypto/replay/ut_sim.c crypto/replay/rdb.c crypto/replay/rdbx.c crypto/replay/ut_sim.c
libsrtp_la_LDFLAGS = -version-info 1:42:1 libsrtp_la_LDFLAGS = -version-info 1:42:1
EXTRA_DIST= EXTRA_DIST=
if ENABLE_OPENSSL
libsrtp_la_SOURCES += crypto/cipher/aes_icm_ossl.c crypto/cipher/aes_gcm_ossl.c
libsrtp_la_SOURCES += crypto/rng/rand_source_ossl.c
else
libsrtp_la_SOURCES += crypto/hash/sha1.c crypto/hash/hmac.c
libsrtp_la_SOURCES += crypto/cipher/aes_icm.c crypto/cipher/aes.c crypto/cipher/aes_cbc.c
if RNG_OBJS_LINUX if RNG_OBJS_LINUX
libsrtp_la_SOURCES += crypto/rng/rand_linux_kernel.c libsrtp_la_SOURCES += crypto/rng/rand_linux_kernel.c
EXTRA_DIST += crypto/rng/rand_source.c EXTRA_DIST += crypto/rng/rand_source.c
else else
libsrtp_la_SOURCES += crypto/rng/rand_source.c libsrtp_la_SOURCES += crypto/rng/rand_source.c
endif endif
endif
if GDOI if GDOI
libsrtp_la_SOURCES += gdoi/srtp+gdoi.c libsrtp_la_SOURCES += gdoi/srtp+gdoi.c

View File

@ -26,9 +26,10 @@ The configure script accepts the following options:
--enable-syslog use syslog for error reporting --enable-syslog use syslog for error reporting
--disable-stdout use stdout for error reporting --disable-stdout use stdout for error reporting
--enable-console use /dev/console for error reporting --enable-console use /dev/console for error reporting
--enable-openssl use OpenSSL crypto primitives
--gdoi use GDOI key management (disabled at present) --gdoi use GDOI key management (disabled at present)
By default, debugging is enabled and stdout is used for debugging. By default, debbuging is enabled and stdout is used for debugging.
You can use the above configure options to have the debugging output You can use the above configure options to have the debugging output
sent to syslog or the system console. Alternatively, you can define sent to syslog or the system console. Alternatively, you can define
ERR_REPORTING_FILE in include/conf.h to be any other file that can be ERR_REPORTING_FILE in include/conf.h to be any other file that can be
@ -77,7 +78,7 @@ Applications
Manual srtp keying uses the -k option; automated key management Manual srtp keying uses the -k option; automated key management
using gdoi will be added later. using gdoi will be added later.
usage: rtpw [-d <debug>]* [-k <key> [-a][-e]] [-s | -r] dest_ip dest_port usage: rtpw [-d <debug>]* [-k <key> [-a][-e <key size>][-g]] [-s | -r] dest_ip dest_port
or rtpw -l or rtpw -l
Either the -s (sender) or -r (receiver) option must be chosen. Either the -s (sender) or -r (receiver) option must be chosen.
@ -86,25 +87,15 @@ or rtpw -l
which the dictionary will be sent, respectively. which the dictionary will be sent, respectively.
options: options:
-a use message authentication
-s (s)rtp sender - causes app to send words -e <key size> use encryption (use 128, 192, or 256 for key size)
-g Use AES-GCM mode (must be used with -e)
-r (s)rtp receive - causes app to receive words -k <key> sets the srtp master key
-s act as rtp sender
-k <key> use srtp master key <key>, where the -r act as rtp receiver
key is a hexadecimal value (without the -l list debug modules
leading "0x") -d <debug> turn on debugging for module <debug>
-i specify input/output file
-e encrypt/decrypt (for data confidentiality)
(requires use of -k option as well)
-a message authentication
(requires use of -k option as well)
-l list debug modules
-d <debug> turn on debugging for module <debug>
In order to get random 30-byte values for use as key/salt pairs , you In order to get random 30-byte values for use as key/salt pairs , you
can use the following bash function to format the output of can use the following bash function to format the output of
@ -119,7 +110,7 @@ An example of an SRTP session using two rtpw programs follows:
set k=c1eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451 set k=c1eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451
[sh1]$ test/rtpw -s -k $k -ea 0.0.0.0 9999 [sh1]$ test/rtpw -s -k $k -e 128 -a 0.0.0.0 9999
Security services: confidentiality message authentication Security services: confidentiality message authentication
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451 set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
setting SSRC to 2078917053 setting SSRC to 2078917053
@ -129,7 +120,7 @@ sending word: aa
sending word: aal sending word: aal
... ...
[sh2]$ test/rtpw -r -k $k -ea 0.0.0.0 9999 [sh2]$ test/rtpw -r -k $k -e 128 -a 0.0.0.0 9999
security services: confidentiality message authentication security services: confidentiality message authentication
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451 set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
19 octets received from SSRC 2078917053 word: A 19 octets received from SSRC 2078917053 word: A

View File

@ -1,4 +1,4 @@
#! /bin/sh #! /bin/sh
srcpath=$(dirname $0 2>/dev/null ) || srcpath="." srcpath=$(dirname $0 2>/dev/null ) || srcpath="."
$srcpath/configure "$@" --disable-shared --with-pic $srcpath/configure "$@" --disable-shared --with-pic --enable-openssl

View File

@ -143,22 +143,6 @@ if test "$cross_compiling" != yes; then
[AC_CHECK_FILE(/dev/random, DEV_URANDOM=/dev/random)]) [AC_CHECK_FILE(/dev/random, DEV_URANDOM=/dev/random)])
fi fi
AC_MSG_CHECKING(which random device to use)
if test "$enable_kernel_linux" = "yes"; then
RNG_OBJS=rand_linux_kernel.o
AC_MSG_RESULT([Linux kernel builtin])
else
RNG_OBJS=rand_source.o
if test -n "$DEV_URANDOM"; then
AC_DEFINE_UNQUOTED(DEV_URANDOM, "$DEV_URANDOM",[Path to random device])
AC_MSG_RESULT([$DEV_URANDOM])
else
AC_MSG_RESULT([standard rand() function...])
fi
fi
AC_SUBST(RNG_OBJS)
AM_CONDITIONAL(RNG_OBJS_LINUX, test x$enable_kernel_linux = xyes)
dnl Checks for header files. dnl Checks for header files.
AC_HEADER_STDC AC_HEADER_STDC
AC_CHECK_HEADERS(stdlib.h) AC_CHECK_HEADERS(stdlib.h)
@ -273,6 +257,56 @@ if test "$enable_generic_aesicm" = "yes"; then
fi fi
AC_MSG_RESULT($enable_generic_aesicm) AC_MSG_RESULT($enable_generic_aesicm)
AC_MSG_CHECKING(whether to leverage OpenSSL crypto)
AC_ARG_ENABLE(openssl,
[AS_HELP_STRING([--enable-openssl],
[compile in OpenSSL crypto engine])],
[], enable_openssl=no)
if test "$enable_openssl" = "yes"; then
echo $enable_openssl
LDFLAGS="$LDFLAGS $(pkg-config --libs openssl)";
CFLAGS="$CFLAGS $(pkg-config --cflags openssl)";
AC_CHECK_LIB([crypto], [EVP_EncryptInit], [],
[AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])])
AC_CHECK_LIB([crypto], [EVP_aes_128_ctr], [],
[AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])])
AC_CHECK_LIB([crypto], [EVP_aes_128_gcm], [],
[AC_MSG_FAILURE([can't find openssl >1.0.1 crypto lib])])
AC_DEFINE(OPENSSL, 1, [Define this to use OpenSSL crypto.])
AES_ICM_OBJS="crypto/cipher/aes_icm_ossl.o crypto/cipher/aes_gcm_ossl.o"
RNG_OBJS=rand_source_ossl.o
HMAC_OBJS=crypto/hash/hmac_ossl.o
USE_OPENSSL=1
AC_SUBST(USE_OPENSSL)
else
echo $enable_openssl
AES_ICM_OBJS="crypto/cipher/aes_icm.o crypto/cipher/aes.o crypto/cipher/aes_cbc.o"
AC_MSG_CHECKING(which random device to use)
if test "$enable_kernel_linux" = "yes"; then
RNG_OBJS=rand_linux_kernel.o
AC_MSG_RESULT([Linux kernel builtin])
else
RNG_OBJS=rand_source.o
if test -n "$DEV_URANDOM"; then
AC_DEFINE_UNQUOTED(DEV_URANDOM, "$DEV_URANDOM",[Path to random device])
AC_MSG_RESULT([$DEV_URANDOM])
else
AC_MSG_RESULT([standard rand() function...])
fi
fi
RNG_EXTRA_OBJS="crypto/rng/prng.o crypto/rng/ctr_prng.o"
HMAC_OBJS="crypto/hash/hmac.o crypto/hash/sha1.o"
fi
AM_CONDITIONAL([ENABLE_OPENSSL],[test "${enable_openssl}" = "yes"])
AM_CONDITIONAL([RNG_OBJS_LINUX], test x$enable_kernel_linux = xyes)
AC_SUBST(AES_ICM_OBJS)
AC_SUBST(RNG_OBJS)
AC_SUBST(RNG_EXTRA_OBJS)
AC_SUBST(HMAC_OBJS)
AC_MSG_RESULT($enable_openssl)
AC_MSG_CHECKING(whether to use syslog for error reporting) AC_MSG_CHECKING(whether to use syslog for error reporting)
AC_ARG_ENABLE(syslog, AC_ARG_ENABLE(syslog,
[AS_HELP_STRING([--enable-syslog], [use syslog for error reporting])], [AS_HELP_STRING([--enable-syslog], [use syslog for error reporting])],

View File

@ -9,14 +9,14 @@ top_builddir = @top_builddir@
VPATH = @srcdir@ VPATH = @srcdir@
CC = @CC@ CC = @CC@
INCDIR = -Iinclude -I$(srcdir)/include INCDIR = -Iinclude -I$(srcdir)/include
DEFS = @DEFS@ DEFS = @DEFS@
CPPFLAGS= @CPPFLAGS@ CPPFLAGS= @CPPFLAGS@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
LDFLAGS = @LDFLAGS@ -L. LDFLAGS = @LDFLAGS@ -L. -L..
COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS) COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS)
CRYPTOLIB = -lcryptomodule CRYPTOLIB = -lsrtp
RANLIB = @RANLIB@ RANLIB = @RANLIB@
@ -25,7 +25,7 @@ RANLIB = @RANLIB@
# `make clean` will work on the cygwin platform # `make clean` will work on the cygwin platform
EXE = @EXE@ EXE = @EXE@
# Random source. # Random source.
RNG_OBJS = @RNG_OBJS@ USE_OPENSSL = @USE_OPENSSL@
ifdef ARCH ifdef ARCH
DEFS += -D$(ARCH)=1 DEFS += -D$(ARCH)=1
@ -41,9 +41,13 @@ dummy : all runtest
# test applications # test applications
ifneq (1, $(USE_OPENSSL))
AES_CALC = test/aes_calc$(EXE)
endif
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) $(AES_CALC) test/rand_gen$(EXE) \
#test/env$(EXE) #test/env$(EXE)
# data values used to test the aes_calc application for AES-128 # data values used to test the aes_calc application for AES-128
@ -58,60 +62,31 @@ p256=00112233445566778899aabbccddeeff
c256=8ea2b7ca516745bfeafc49904b496089 c256=8ea2b7ca516745bfeafc49904b496089
runtest: libcryptomodule.a $(testapp) runtest: $(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 crypto test applications..."
ifneq (1, $(USE_OPENSSL))
test `test/aes_calc $(k128) $(p128)` = $(c128) test `test/aes_calc $(k128) $(p128)` = $(c128)
test `test/aes_calc $(k256) $(p256)` = $(c256) test `test/aes_calc $(k256) $(p256)` = $(c256)
endif
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
test/sha1_driver$(EXE) -v >/dev/null test/sha1_driver$(EXE) -v >/dev/null
test/kernel_driver$(EXE) -v >/dev/null test/kernel_driver$(EXE) -v >/dev/null
test/rand_gen$(EXE) -n 256 >/dev/null test/rand_gen$(EXE) -n 256 >/dev/null
@echo "libcryptomodule test applications passed." @echo "crypto test applications passed."
# libcryptomodule.a (the crypto engine)
ciphers = cipher/cipher.o cipher/null_cipher.o \
cipher/aes.o cipher/aes_icm.o \
cipher/aes_cbc.o
hashes = hash/null_auth.o hash/sha1.o \
hash/hmac.o hash/auth.o
math = math/datatypes.o math/stat.o
rng = rng/$(RNG_OBJS) rng/rand_source.o rng/prng.o rng/ctr_prng.o
err = kernel/err.o
kernel = kernel/crypto_kernel.o kernel/alloc.o \
kernel/key.o $(rng) $(err)
xfm = ae_xfm/xfm.o
cryptobj = $(ciphers) $(hashes) $(math) $(stat) $(kernel) $(xfm)
# the rule for making object files and test apps # the rule for making object files and test apps
%.o: %.c %.o: %.c
$(COMPILE) -c $< -o $@ $(COMPILE) -c $< -o $@
%$(EXE): %.c libcryptomodule.a %$(EXE): %.c
$(COMPILE) $(LDFLAGS) $< -o $@ $(CRYPTOLIB) $(LIBS) $(COMPILE) $(LDFLAGS) $< -o $@ $(CRYPTOLIB) $(LIBS)
ifndef AR all: $(testapp)
AR=ar
endif
# and the crypto module library itself
libcryptomodule.a: $(cryptobj)
$(AR) cr libcryptomodule.a $(cryptobj)
$(RANLIB) libcryptomodule.a
all: libcryptomodule.a $(testapp)
# housekeeping functions # housekeeping functions

View File

@ -104,36 +104,25 @@ 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, int key_len, aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, int key_len) {
cipher_direction_t dir) {
err_status_t status;
debug_print(mod_aes_cbc, debug_print(mod_aes_cbc,
"key: %s", octet_string_hex_string(key, key_len)); "key: %s", octet_string_hex_string(key, key_len));
/* expand key for the appropriate direction */ /*
switch (dir) { * Save the key until we have the IV later. We don't
case (direction_encrypt): * know the direction until the IV is set.
status = aes_expand_encryption_key(key, key_len, &c->expanded_key); */
if (status) c->key_len = (key_len <= 32 ? key_len : 32);
return status; memcpy(c->key, key, c->key_len);
break;
case (direction_decrypt):
status = aes_expand_decryption_key(key, key_len, &c->expanded_key);
if (status)
return status;
break;
default:
return err_status_bad_param;
}
return err_status_ok; return err_status_ok;
} }
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, int direction) {
err_status_t status;
int i; int i;
/* v128_t *input = iv; */ /* v128_t *input = iv; */
uint8_t *input = (uint8_t*) iv; uint8_t *input = (uint8_t*) iv;
@ -144,6 +133,24 @@ aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) {
debug_print(mod_aes_cbc, "setting iv: %s", v128_hex_string(&c->state)); debug_print(mod_aes_cbc, "setting iv: %s", v128_hex_string(&c->state));
/* expand key for the appropriate direction */
switch (direction) {
case (direction_encrypt):
status = aes_expand_encryption_key(c->key, c->key_len, &c->expanded_key);
memset(c->key, 0, 32);
if (status)
return status;
break;
case (direction_decrypt):
status = aes_expand_decryption_key(c->key, c->key_len, &c->expanded_key);
memset(c->key, 0, 32);
if (status)
return status;
break;
default:
return err_status_bad_param;
}
return err_status_ok; return err_status_ok;
} }
@ -375,6 +382,8 @@ cipher_test_case_t aes_cbc_test_case_0 = {
aes_cbc_test_case_0_plaintext, /* plaintext */ aes_cbc_test_case_0_plaintext, /* plaintext */
32, /* octets in ciphertext */ 32, /* octets in ciphertext */
aes_cbc_test_case_0_ciphertext, /* ciphertext */ aes_cbc_test_case_0_ciphertext, /* ciphertext */
0,
NULL,
NULL /* pointer to next testcase */ NULL /* pointer to next testcase */
}; };
@ -426,6 +435,8 @@ cipher_test_case_t aes_cbc_test_case_1 = {
aes_cbc_test_case_1_plaintext, /* plaintext */ aes_cbc_test_case_1_plaintext, /* plaintext */
80, /* octets in ciphertext */ 80, /* octets in ciphertext */
aes_cbc_test_case_1_ciphertext, /* ciphertext */ aes_cbc_test_case_1_ciphertext, /* ciphertext */
0,
NULL,
&aes_cbc_test_case_0 /* pointer to next testcase */ &aes_cbc_test_case_0 /* pointer to next testcase */
}; };
@ -467,6 +478,8 @@ cipher_test_case_t aes_cbc_test_case_2 = {
aes_cbc_test_case_2_plaintext, /* plaintext */ aes_cbc_test_case_2_plaintext, /* plaintext */
32, /* octets in ciphertext */ 32, /* octets in ciphertext */
aes_cbc_test_case_2_ciphertext, /* ciphertext */ aes_cbc_test_case_2_ciphertext, /* ciphertext */
0,
NULL,
&aes_cbc_test_case_1 /* pointer to next testcase */ &aes_cbc_test_case_1 /* pointer to next testcase */
}; };
@ -520,6 +533,8 @@ cipher_test_case_t aes_cbc_test_case_3 = {
aes_cbc_test_case_3_plaintext, /* plaintext */ aes_cbc_test_case_3_plaintext, /* plaintext */
80, /* octets in ciphertext */ 80, /* octets in ciphertext */
aes_cbc_test_case_3_ciphertext, /* ciphertext */ aes_cbc_test_case_3_ciphertext, /* ciphertext */
0,
NULL,
&aes_cbc_test_case_2 /* pointer to next testcase */ &aes_cbc_test_case_2 /* pointer to next testcase */
}; };
@ -527,9 +542,11 @@ 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,
(cipher_init_func_t) aes_cbc_context_init, (cipher_init_func_t) aes_cbc_context_init,
(cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_cbc_nist_encrypt, (cipher_encrypt_func_t) aes_cbc_nist_encrypt,
(cipher_decrypt_func_t) aes_cbc_nist_decrypt, (cipher_decrypt_func_t) aes_cbc_nist_decrypt,
(cipher_set_iv_func_t) aes_cbc_set_iv, (cipher_set_iv_func_t) aes_cbc_set_iv,
(cipher_get_tag_func_t) 0,
(char *) aes_cbc_description, (char *) aes_cbc_description,
(int) 0, /* instance count */ (int) 0, /* instance count */
(cipher_test_case_t *) &aes_cbc_test_case_3, (cipher_test_case_t *) &aes_cbc_test_case_3,

View File

@ -0,0 +1,529 @@
/*
* aes_gcm_ossl.c
*
* AES Galois Counter Mode
*
* John A. Foley
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013, 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 <openssl/evp.h>
#include "aes_icm_ossl.h"
#include "aes_gcm_ossl.h"
#include "alloc.h"
#include "crypto_types.h"
debug_module_t mod_aes_gcm = {
0, /* debugging is off by default */
"aes gcm" /* printable module name */
};
/*
* The following are the global singleton instances for the
* 128-bit and 256-bit GCM ciphers.
*/
extern cipher_type_t aes_gcm_128_openssl;
extern cipher_type_t aes_gcm_256_openssl;
/*
* For now we only support 8 octet tags. The spec allows for
* optional 12 and 16 byte tags. These longer tag lengths may
* be implemented in the future.
*/
#define GCM_AUTH_TAG_LEN 8
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30 or 46 for
* AES-128-GCM or AES-256-GCM respectively. Note that the
* key length includes the 14 byte salt value that is used when
* initializing the KDF.
*/
err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len)
{
aes_gcm_ctx_t *gcm;
int tmp;
uint8_t *allptr;
debug_print(mod_aes_gcm, "allocating cipher with key length %d", key_len);
/*
* Verify the key_len is valid for one of: AES-128/256
*/
if (key_len != AES_128_KEYSIZE_WSALT &&
key_len != AES_256_KEYSIZE_WSALT) {
return (err_status_bad_param);
}
/* allocate memory a cipher of type aes_gcm */
tmp = sizeof(cipher_t) + sizeof(aes_gcm_ctx_t);
allptr = crypto_alloc(tmp);
if (allptr == NULL) {
return (err_status_alloc_fail);
}
/* set pointers */
*c = (cipher_t*)allptr;
(*c)->state = allptr + sizeof(cipher_t);
gcm = (aes_gcm_ctx_t *)(*c)->state;
/* increment ref_count */
switch (key_len) {
case AES_128_KEYSIZE_WSALT:
(*c)->type = &aes_gcm_128_openssl;
(*c)->algorithm = AES_128_GCM;
aes_gcm_128_openssl.ref_count++;
((aes_gcm_ctx_t*)(*c)->state)->key_size = AES_128_KEYSIZE;
((aes_gcm_ctx_t*)(*c)->state)->tag_len = GCM_AUTH_TAG_LEN;
break;
case AES_256_KEYSIZE_WSALT:
(*c)->type = &aes_gcm_256_openssl;
(*c)->algorithm = AES_256_GCM;
aes_gcm_256_openssl.ref_count++;
((aes_gcm_ctx_t*)(*c)->state)->key_size = AES_256_KEYSIZE;
((aes_gcm_ctx_t*)(*c)->state)->tag_len = GCM_AUTH_TAG_LEN;
break;
}
/* set key size */
(*c)->key_len = key_len;
EVP_CIPHER_CTX_init(&gcm->ctx);
return (err_status_ok);
}
/*
* This function deallocates a GCM session
*/
err_status_t aes_gcm_openssl_dealloc (cipher_t *c)
{
aes_gcm_ctx_t *ctx;
ctx = (aes_gcm_ctx_t*)c->state;
if (ctx) {
EVP_CIPHER_CTX_cleanup(&ctx->ctx);
/* decrement ref_count for the appropriate engine */
switch (ctx->key_size) {
case AES_256_KEYSIZE:
aes_gcm_256_openssl.ref_count--;
break;
case AES_128_KEYSIZE:
aes_gcm_128_openssl.ref_count--;
break;
default:
return (err_status_dealloc_fail);
break;
}
}
/* zeroize entire state*/
octet_string_set_to_zero((uint8_t*)c, sizeof(cipher_t) + sizeof(aes_gcm_ctx_t));
/* free memory */
crypto_free(c);
return (err_status_ok);
}
/*
* aes_gcm_openssl_context_init(...) initializes the aes_gcm_context
* using the value in key[].
*
* the key is the secret key
*/
err_status_t aes_gcm_openssl_context_init (aes_gcm_ctx_t *c, const uint8_t *key)
{
c->dir = direction_any;
/* copy key to be used later when CiscoSSL crypto context is created */
v128_copy_octet_string((v128_t*)&c->key, key);
if (c->key_size == AES_256_KEYSIZE) {
debug_print(mod_aes_gcm, "Copying last 16 bytes of key: %s",
v128_hex_string((v128_t*)(key + AES_128_KEYSIZE)));
v128_copy_octet_string(((v128_t*)(&c->key.v8)) + 1,
key + AES_128_KEYSIZE);
}
debug_print(mod_aes_gcm, "key: %s", v128_hex_string((v128_t*)&c->key));
EVP_CIPHER_CTX_cleanup(&c->ctx);
return (err_status_ok);
}
/*
* aes_gcm_openssl_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
err_status_t aes_gcm_openssl_set_iv (aes_gcm_ctx_t *c, void *iv,
int direction)
{
const EVP_CIPHER *evp;
v128_t *nonce = iv;
if (direction != direction_encrypt && direction != direction_decrypt) {
return (err_status_bad_param);
}
c->dir = direction;
debug_print(mod_aes_gcm, "setting iv: %s", v128_hex_string(nonce));
switch (c->key_size) {
case AES_256_KEYSIZE:
evp = EVP_aes_256_gcm();
break;
case AES_128_KEYSIZE:
evp = EVP_aes_128_gcm();
break;
default:
return (err_status_bad_param);
break;
}
if (!EVP_CipherInit_ex(&c->ctx, evp, NULL, (const unsigned char*)&c->key.v8,
NULL, (c->dir == direction_encrypt ? 1 : 0))) {
return (err_status_init_fail);
}
/* set IV len and the IV value, the followiong 3 calls are required */
if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) {
return (err_status_init_fail);
}
if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, iv)) {
return (err_status_init_fail);
}
if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_IV_GEN, 0, iv)) {
return (err_status_init_fail);
}
return (err_status_ok);
}
/*
* This function processes the AAD
*
* Parameters:
* c Crypto context
* aad Additional data to process for AEAD cipher suites
* aad_len length of aad buffer
*/
err_status_t aes_gcm_openssl_set_aad (aes_gcm_ctx_t *c, unsigned char *aad,
unsigned int aad_len)
{
int rv;
/*
* Set dummy tag, OpenSSL requires the Tag to be set before
* processing AAD
*/
EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len, aad);
rv = EVP_Cipher(&c->ctx, NULL, aad, aad_len);
if (rv != aad_len) {
return (err_status_algo_fail);
} else {
return (err_status_ok);
}
}
/*
* This function encrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
err_status_t aes_gcm_openssl_encrypt (aes_gcm_ctx_t *c, unsigned char *buf,
unsigned int *enc_len)
{
if (c->dir != direction_encrypt && c->dir != direction_decrypt) {
return (err_status_bad_param);
}
/*
* Encrypt the data
*/
EVP_Cipher(&c->ctx, buf, buf, *enc_len);
return (err_status_ok);
}
/*
* This function calculates and returns the GCM tag for a given context.
* This should be called after encrypting the data. The *len value
* is increased by the tag size. The caller must ensure that *buf has
* enough room to accept the appended tag.
*
* Parameters:
* c Crypto context
* buf data to encrypt
* len length of encrypt buffer
*/
err_status_t aes_gcm_openssl_get_tag (aes_gcm_ctx_t *c, unsigned char *buf,
int *len)
{
/*
* Calculate the tag
*/
EVP_Cipher(&c->ctx, NULL, NULL, 0);
/*
* Retreive the tag
*/
EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_GET_TAG, c->tag_len, buf);
/*
* Increase encryption length by desired tag size
*/
*len = c->tag_len;
return (err_status_ok);
}
/*
* This function decrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
err_status_t aes_gcm_openssl_decrypt (aes_gcm_ctx_t *c, unsigned char *buf,
unsigned int *enc_len)
{
if (c->dir != direction_encrypt && c->dir != direction_decrypt) {
return (err_status_bad_param);
}
/*
* Set the tag before decrypting
*/
EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len,
buf + (*enc_len - c->tag_len));
EVP_Cipher(&c->ctx, buf, buf, *enc_len - c->tag_len);
/*
* Check the tag
*/
if (EVP_Cipher(&c->ctx, NULL, NULL, 0)) {
return (err_status_auth_fail);
}
/*
* Reduce the buffer size by the tag length since the tag
* is not part of the original payload
*/
*enc_len -= c->tag_len;
return (err_status_ok);
}
/*
* Name of this crypto engine
*/
char aes_gcm_128_openssl_description[] = "AES-128 GCM using openssl";
char aes_gcm_256_openssl_description[] = "AES-256 GCM using openssl";
/*
* KAT values for AES self-test. These
* values we're derived from independent test code
* using OpenSSL.
*/
uint8_t aes_gcm_test_case_0_key[AES_128_KEYSIZE_WSALT] = {
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
};
uint8_t aes_gcm_test_case_0_iv[12] = {
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88
};
uint8_t aes_gcm_test_case_0_plaintext[60] = {
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
};
uint8_t aes_gcm_test_case_0_aad[20] = {
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xab, 0xad, 0xda, 0xd2
};
uint8_t aes_gcm_test_case_0_ciphertext[68] = {
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91,
/* the last 8 bytes are the tag */
0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
};
cipher_test_case_t aes_gcm_test_case_0 = {
AES_128_KEYSIZE_WSALT, /* octets in key */
aes_gcm_test_case_0_key, /* key */
aes_gcm_test_case_0_iv, /* packet index */
60, /* octets in plaintext */
aes_gcm_test_case_0_plaintext, /* plaintext */
68, /* octets in ciphertext */
aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */
20, /* octets in AAD */
aes_gcm_test_case_0_aad, /* AAD */
NULL /* pointer to next testcase */
};
uint8_t aes_gcm_test_case_1_key[AES_256_KEYSIZE_WSALT] = {
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c,
0xaf, 0xf5, 0x26, 0x9a, 0x21, 0xd5, 0x14, 0xb2,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
};
uint8_t aes_gcm_test_case_1_iv[12] = {
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88
};
uint8_t aes_gcm_test_case_1_plaintext[60] = {
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
};
uint8_t aes_gcm_test_case_1_aad[20] = {
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xab, 0xad, 0xda, 0xd2
};
uint8_t aes_gcm_test_case_1_ciphertext[68] = {
0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46,
0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a,
0x94, 0x82, 0xca, 0xab, 0x3e, 0x39, 0xd7, 0x86,
0x1b, 0xc7, 0x93, 0xed, 0x75, 0x7f, 0x23, 0x5a,
0xda, 0xfd, 0xd3, 0xe2, 0x0e, 0x80, 0x87, 0xa9,
0x6d, 0xd7, 0xe2, 0x6a, 0x7d, 0x5f, 0xb4, 0x80,
0xef, 0xef, 0xc5, 0x29, 0x12, 0xd1, 0xaa, 0x10,
0x09, 0xc9, 0x86, 0xc1,
/* the last 8 bytes are the tag */
0x45, 0xbc, 0x03, 0xe6, 0xe1, 0xac, 0x0a, 0x9f,
};
cipher_test_case_t aes_gcm_test_case_1 = {
AES_256_KEYSIZE_WSALT, /* octets in key */
aes_gcm_test_case_1_key, /* key */
aes_gcm_test_case_1_iv, /* packet index */
60, /* octets in plaintext */
aes_gcm_test_case_1_plaintext, /* plaintext */
68, /* octets in ciphertext */
aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */
20, /* octets in AAD */
aes_gcm_test_case_1_aad, /* AAD */
NULL /* pointer to next testcase */
};
/*
* This is the vector function table for this crypto engine.
*/
cipher_type_t aes_gcm_128_openssl = {
(cipher_alloc_func_t) aes_gcm_openssl_alloc,
(cipher_dealloc_func_t) aes_gcm_openssl_dealloc,
(cipher_init_func_t) aes_gcm_openssl_context_init,
(cipher_set_aad_func_t) aes_gcm_openssl_set_aad,
(cipher_encrypt_func_t) aes_gcm_openssl_encrypt,
(cipher_decrypt_func_t) aes_gcm_openssl_decrypt,
(cipher_set_iv_func_t) aes_gcm_openssl_set_iv,
(cipher_get_tag_func_t) aes_gcm_openssl_get_tag,
(char*) aes_gcm_128_openssl_description,
(int) 0, /* instance count */
(cipher_test_case_t*) &aes_gcm_test_case_0,
(debug_module_t*) &mod_aes_gcm,
(cipher_type_id_t) AES_128_GCM
};
/*
* This is the vector function table for this crypto engine.
*/
cipher_type_t aes_gcm_256_openssl = {
(cipher_alloc_func_t) aes_gcm_openssl_alloc,
(cipher_dealloc_func_t) aes_gcm_openssl_dealloc,
(cipher_init_func_t) aes_gcm_openssl_context_init,
(cipher_set_aad_func_t) aes_gcm_openssl_set_aad,
(cipher_encrypt_func_t) aes_gcm_openssl_encrypt,
(cipher_decrypt_func_t) aes_gcm_openssl_decrypt,
(cipher_set_iv_func_t) aes_gcm_openssl_set_iv,
(cipher_get_tag_func_t) aes_gcm_openssl_get_tag,
(char*) aes_gcm_256_openssl_description,
(int) 0, /* instance count */
(cipher_test_case_t*) &aes_gcm_test_case_1,
(debug_module_t*) &mod_aes_gcm,
(cipher_type_id_t) AES_256_GCM
};

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2006, Cisco Systems, Inc. * Copyright (c) 2001-2006,2013 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
@ -272,7 +272,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, int direction) {
v128_t *nonce = (v128_t *) iv; v128_t *nonce = (v128_t *) iv;
debug_print(mod_aes_icm, debug_print(mod_aes_icm,
@ -503,6 +503,8 @@ cipher_test_case_t aes_icm_test_case_0 = {
aes_icm_test_case_0_plaintext, /* plaintext */ aes_icm_test_case_0_plaintext, /* plaintext */
32, /* octets in ciphertext */ 32, /* octets in ciphertext */
aes_icm_test_case_0_ciphertext, /* ciphertext */ aes_icm_test_case_0_ciphertext, /* ciphertext */
0,
NULL,
NULL /* pointer to next testcase */ NULL /* pointer to next testcase */
}; };
@ -542,6 +544,8 @@ cipher_test_case_t aes_icm_test_case_1 = {
aes_icm_test_case_1_plaintext, /* plaintext */ aes_icm_test_case_1_plaintext, /* plaintext */
32, /* octets in ciphertext */ 32, /* octets in ciphertext */
aes_icm_test_case_1_ciphertext, /* ciphertext */ aes_icm_test_case_1_ciphertext, /* ciphertext */
0,
NULL,
&aes_icm_test_case_0 /* pointer to next testcase */ &aes_icm_test_case_0 /* pointer to next testcase */
}; };
@ -555,9 +559,11 @@ cipher_type_t aes_icm = {
(cipher_alloc_func_t) aes_icm_alloc, (cipher_alloc_func_t) aes_icm_alloc,
(cipher_dealloc_func_t) aes_icm_dealloc, (cipher_dealloc_func_t) aes_icm_dealloc,
(cipher_init_func_t) aes_icm_context_init, (cipher_init_func_t) aes_icm_context_init,
(cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_icm_encrypt, (cipher_encrypt_func_t) aes_icm_encrypt,
(cipher_decrypt_func_t) aes_icm_encrypt, (cipher_decrypt_func_t) aes_icm_encrypt,
(cipher_set_iv_func_t) aes_icm_set_iv, (cipher_set_iv_func_t) aes_icm_set_iv,
(cipher_get_tag_func_t) 0,
(char *) aes_icm_description, (char *) aes_icm_description,
(int) 0, /* instance count */ (int) 0, /* instance count */
(cipher_test_case_t *) &aes_icm_test_case_1, (cipher_test_case_t *) &aes_icm_test_case_1,

View File

@ -0,0 +1,537 @@
/*
* aes_icm_ossl.c
*
* AES Integer Counter Mode
*
* John A. Foley
* Cisco Systems, Inc.
*
* 2/24/2012: This module was modified to use CiscoSSL for AES counter
* mode. Eddy Lem contributed the code to allow this.
*
* 12/20/2012: Added support for AES-192 and AES-256.
*/
/*
*
* Copyright (c) 2013, 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 <openssl/evp.h>
#include "aes_icm_ossl.h"
#include "crypto_types.h"
#include "alloc.h"
#include "crypto_types.h"
debug_module_t mod_aes_icm = {
0, /* debugging is off by default */
"aes icm ossl" /* printable module name */
};
extern cipher_test_case_t aes_icm_test_case_0;
extern cipher_type_t aes_icm;
extern cipher_type_t aes_icm_192;
extern cipher_type_t aes_icm_256;
/*
* integer counter mode works as follows:
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | pakcet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30, 38, or 46 for
* AES-128, AES-192, and AES-256 respectively. Note, this key_len
* value is inflated, as it also accounts for the 112 bit salt
* value.
*/
err_status_t aes_icm_openssl_alloc (cipher_t **c, int key_len, int x)
{
aes_icm_ctx_t *icm;
int tmp;
uint8_t *allptr;
debug_print(mod_aes_icm, "allocating cipher with key length %d", key_len);
/*
* Verify the key_len is valid for one of: AES-128/192/256
*/
if (key_len != AES_128_KEYSIZE_WSALT && key_len != AES_192_KEYSIZE_WSALT &&
key_len != AES_256_KEYSIZE_WSALT) {
return err_status_bad_param;
}
/* allocate memory a cipher of type aes_icm */
tmp = sizeof(cipher_t) + sizeof(aes_icm_ctx_t);
allptr = (uint8_t*)crypto_alloc(tmp);
if (allptr == NULL) {
return err_status_alloc_fail;
}
/* set pointers */
*c = (cipher_t*)allptr;
(*c)->state = allptr + sizeof(cipher_t);
icm = (aes_icm_ctx_t*)(*c)->state;
/* increment ref_count */
switch (key_len) {
case AES_128_KEYSIZE_WSALT:
(*c)->algorithm = AES_128_ICM;
(*c)->type = &aes_icm;
aes_icm.ref_count++;
((aes_icm_ctx_t*)(*c)->state)->key_size = AES_128_KEYSIZE;
break;
case AES_192_KEYSIZE_WSALT:
(*c)->algorithm = AES_192_ICM;
(*c)->type = &aes_icm_192;
aes_icm_192.ref_count++;
((aes_icm_ctx_t*)(*c)->state)->key_size = AES_192_KEYSIZE;
break;
case AES_256_KEYSIZE_WSALT:
(*c)->algorithm = AES_256_ICM;
(*c)->type = &aes_icm_256;
aes_icm_256.ref_count++;
((aes_icm_ctx_t*)(*c)->state)->key_size = AES_256_KEYSIZE;
break;
}
/* set key size */
(*c)->key_len = key_len;
EVP_CIPHER_CTX_init(&icm->ctx);
return err_status_ok;
}
/*
* This function deallocates an instance of this engine
*/
err_status_t aes_icm_openssl_dealloc (cipher_t *c)
{
aes_icm_ctx_t *ctx;
if (c == NULL) {
return err_status_bad_param;
}
/*
* Free the EVP context
*/
ctx = (aes_icm_ctx_t*)c->state;
if (ctx != NULL) {
EVP_CIPHER_CTX_cleanup(&ctx->ctx);
/* decrement ref_count for the appropriate engine */
switch (ctx->key_size) {
case AES_256_KEYSIZE:
aes_icm_256.ref_count--;
break;
case AES_192_KEYSIZE:
aes_icm_192.ref_count--;
break;
case AES_128_KEYSIZE:
aes_icm.ref_count--;
break;
default:
return err_status_dealloc_fail;
break;
}
}
/* zeroize entire state*/
octet_string_set_to_zero((uint8_t*)c,
sizeof(cipher_t) + sizeof(aes_icm_ctx_t));
/* free memory */
crypto_free(c);
return err_status_ok;
}
/*
* aes_icm_openssl_context_init(...) initializes the aes_icm_context
* using the value in key[].
*
* the key is the secret key
*
* the salt is unpredictable (but not necessarily secret) data which
* randomizes the starting point in the keystream
*/
err_status_t aes_icm_openssl_context_init (aes_icm_ctx_t *c, const uint8_t *key)
{
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
memcpy(&c->counter, key + c->key_size, SALT_SIZE);
memcpy(&c->offset, key + c->key_size, SALT_SIZE);
/* force last two octets of the offset to zero (for srtp compatibility) */
c->offset.v8[SALT_SIZE] = c->offset.v8[SALT_SIZE + 1] = 0;
c->counter.v8[SALT_SIZE] = c->counter.v8[SALT_SIZE + 1] = 0;
/* copy key to be used later when CiscoSSL crypto context is created */
v128_copy_octet_string((v128_t*)&c->key, key);
/* if the key is greater than 16 bytes, copy the second
* half. Note, we treat AES-192 and AES-256 the same here
* for simplicity. The storage location receiving the
* key is statically allocated to handle a full 32 byte key
* regardless of the cipher in use.
*/
if (c->key_size == AES_256_KEYSIZE || c->key_size == AES_192_KEYSIZE) {
debug_print(mod_aes_icm, "Copying last 16 bytes of key: %s",
v128_hex_string((v128_t*)(key + AES_128_KEYSIZE)));
v128_copy_octet_string(((v128_t*)(&c->key.v8)) + 1, key + AES_128_KEYSIZE);
}
debug_print(mod_aes_icm, "key: %s", v128_hex_string((v128_t*)&c->key));
debug_print(mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
EVP_CIPHER_CTX_cleanup(&c->ctx);
return err_status_ok;
}
/*
* aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
err_status_t aes_icm_openssl_set_iv (aes_icm_ctx_t *c, void *iv, int dir)
{
const EVP_CIPHER *evp;
v128_t *nonce = (v128_t*)iv;
debug_print(mod_aes_icm, "setting iv: %s", v128_hex_string(nonce));
v128_xor(&c->counter, &c->offset, nonce);
debug_print(mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter));
switch (c->key_size) {
case AES_256_KEYSIZE:
evp = EVP_aes_256_ctr();
break;
case AES_192_KEYSIZE:
evp = EVP_aes_192_ctr();
break;
case AES_128_KEYSIZE:
evp = EVP_aes_128_ctr();
break;
default:
return err_status_bad_param;
break;
}
if (!EVP_EncryptInit_ex(&c->ctx, evp,
NULL, c->key.v8, c->counter.v8)) {
return err_status_fail;
} else {
return err_status_ok;
}
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
err_status_t aes_icm_openssl_encrypt (aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len)
{
int len = 0;
debug_print(mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter));
if (!EVP_EncryptUpdate(&c->ctx, buf, &len, buf, *enc_len)) {
return err_status_cipher_fail;
}
*enc_len = len;
if (!EVP_EncryptFinal_ex(&c->ctx, buf, (int*)&len)) {
return err_status_cipher_fail;
}
*enc_len += len;
return err_status_ok;
}
/*
* Abstraction layer for encrypt.
*/
err_status_t aes_icm_output (aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output)
{
unsigned int len = num_octets_to_output;
/* zeroize the buffer */
octet_string_set_to_zero(buffer, num_octets_to_output);
/* exor keystream into buffer */
return aes_icm_openssl_encrypt(c, buffer, &len);
}
/*
* Name of this crypto engine
*/
char aes_icm_openssl_description[] = "AES-128 counter mode using openssl";
char aes_icm_192_openssl_description[] = "AES-192 counter mode using openssl";
char aes_icm_256_openssl_description[] = "AES-256 counter mode using openssl";
/*
* KAT values for AES self-test. These
* values came from the legacy libsrtp code.
*/
uint8_t aes_icm_test_case_0_key[AES_128_KEYSIZE_WSALT] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
};
uint8_t aes_icm_test_case_0_nonce[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t aes_icm_test_case_0_plaintext[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
uint8_t aes_icm_test_case_0_ciphertext[32] = {
0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
};
cipher_test_case_t aes_icm_test_case_0 = {
AES_128_KEYSIZE_WSALT, /* octets in key */
aes_icm_test_case_0_key, /* key */
aes_icm_test_case_0_nonce, /* packet index */
32, /* octets in plaintext */
aes_icm_test_case_0_plaintext, /* plaintext */
32, /* octets in ciphertext */
aes_icm_test_case_0_ciphertext, /* ciphertext */
0,
NULL,
NULL /* pointer to next testcase */
};
/*
* KAT values for AES-192-CTR self-test. These
* values came from section 7 of RFC 6188.
*/
uint8_t aes_icm_192_test_case_1_key[AES_192_KEYSIZE_WSALT] = {
0xea, 0xb2, 0x34, 0x76, 0x4e, 0x51, 0x7b, 0x2d,
0x3d, 0x16, 0x0d, 0x58, 0x7d, 0x8c, 0x86, 0x21,
0x97, 0x40, 0xf6, 0x5f, 0x99, 0xb6, 0xbc, 0xf7,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
};
uint8_t aes_icm_192_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_192_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_192_test_case_1_ciphertext[32] = {
0x35, 0x09, 0x6c, 0xba, 0x46, 0x10, 0x02, 0x8d,
0xc1, 0xb5, 0x75, 0x03, 0x80, 0x4c, 0xe3, 0x7c,
0x5d, 0xe9, 0x86, 0x29, 0x1d, 0xcc, 0xe1, 0x61,
0xd5, 0x16, 0x5e, 0xc4, 0x56, 0x8f, 0x5c, 0x9a
};
cipher_test_case_t aes_icm_192_test_case_1 = {
AES_192_KEYSIZE_WSALT, /* octets in key */
aes_icm_192_test_case_1_key, /* key */
aes_icm_192_test_case_1_nonce, /* packet index */
32, /* octets in plaintext */
aes_icm_192_test_case_1_plaintext, /* plaintext */
32, /* octets in ciphertext */
aes_icm_192_test_case_1_ciphertext, /* ciphertext */
0,
NULL,
NULL /* pointer to next testcase */
};
/*
* KAT values for AES-256-CTR self-test. These
* values came from section 7 of RFC 6188.
*/
uint8_t aes_icm_256_test_case_2_key[AES_256_KEYSIZE_WSALT] = {
0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
};
uint8_t aes_icm_256_test_case_2_nonce[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t aes_icm_256_test_case_2_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_256_test_case_2_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_256_test_case_2 = {
AES_256_KEYSIZE_WSALT, /* octets in key */
aes_icm_256_test_case_2_key, /* key */
aes_icm_256_test_case_2_nonce, /* packet index */
32, /* octets in plaintext */
aes_icm_256_test_case_2_plaintext, /* plaintext */
32, /* octets in ciphertext */
aes_icm_256_test_case_2_ciphertext, /* ciphertext */
0,
NULL,
NULL /* pointer to next testcase */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
cipher_type_t aes_icm = {
(cipher_alloc_func_t) aes_icm_openssl_alloc,
(cipher_dealloc_func_t) aes_icm_openssl_dealloc,
(cipher_init_func_t) aes_icm_openssl_context_init,
(cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_icm_openssl_encrypt,
(cipher_decrypt_func_t) aes_icm_openssl_encrypt,
(cipher_set_iv_func_t) aes_icm_openssl_set_iv,
(cipher_get_tag_func_t) 0,
(char*) aes_icm_openssl_description,
(int) 0, /* instance count */
(cipher_test_case_t*) &aes_icm_test_case_0,
(debug_module_t*) &mod_aes_icm,
(cipher_type_id_t) AES_ICM
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
cipher_type_t aes_icm_192 = {
(cipher_alloc_func_t) aes_icm_openssl_alloc,
(cipher_dealloc_func_t) aes_icm_openssl_dealloc,
(cipher_init_func_t) aes_icm_openssl_context_init,
(cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_icm_openssl_encrypt,
(cipher_decrypt_func_t) aes_icm_openssl_encrypt,
(cipher_set_iv_func_t) aes_icm_openssl_set_iv,
(cipher_get_tag_func_t) 0,
(char*) aes_icm_192_openssl_description,
(int) 0, /* instance count */
(cipher_test_case_t*) &aes_icm_192_test_case_1,
(debug_module_t*) &mod_aes_icm,
(cipher_type_id_t) AES_192_ICM
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
cipher_type_t aes_icm_256 = {
(cipher_alloc_func_t) aes_icm_openssl_alloc,
(cipher_dealloc_func_t) aes_icm_openssl_dealloc,
(cipher_init_func_t) aes_icm_openssl_context_init,
(cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_icm_openssl_encrypt,
(cipher_decrypt_func_t) aes_icm_openssl_encrypt,
(cipher_set_iv_func_t) aes_icm_openssl_set_iv,
(cipher_get_tag_func_t) 0,
(char*) aes_icm_256_openssl_description,
(int) 0, /* instance count */
(cipher_test_case_t*) &aes_icm_256_test_case_2,
(debug_module_t*) &mod_aes_icm,
(cipher_type_id_t) AES_256_ICM
};

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2006, Cisco Systems, Inc. * Copyright (c) 2001-2006,2013 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,6 +45,7 @@
*/ */
#include "cipher.h" #include "cipher.h"
#include "crypto_types.h"
#include "rand_source.h" /* used in invertibiltiy tests */ #include "rand_source.h" /* used in invertibiltiy tests */
#include "alloc.h" /* for crypto_alloc(), crypto_free() */ #include "alloc.h" /* for crypto_alloc(), crypto_free() */
@ -87,6 +88,7 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
err_status_t status; err_status_t status;
uint8_t buffer[SELF_TEST_BUF_OCTETS]; uint8_t buffer[SELF_TEST_BUF_OCTETS];
uint8_t buffer2[SELF_TEST_BUF_OCTETS]; uint8_t buffer2[SELF_TEST_BUF_OCTETS];
int tag_len;
unsigned int len; unsigned int len;
int i, j, case_num = 0; int i, j, case_num = 0;
@ -105,7 +107,6 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
* encryption and decryption functions * encryption and decryption functions
*/ */
while (test_case != NULL) { while (test_case != NULL) {
/* allocate cipher */ /* allocate cipher */
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)
@ -117,7 +118,7 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
debug_print(mod_cipher, "testing encryption", NULL); debug_print(mod_cipher, "testing encryption", NULL);
/* initialize cipher */ /* initialize cipher */
status = cipher_init(c, test_case->key, direction_encrypt); status = cipher_init(c, test_case->key);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
@ -136,12 +137,30 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
test_case->plaintext_length_octets)); test_case->plaintext_length_octets));
/* set the initialization vector */ /* set the initialization vector */
status = cipher_set_iv(c, test_case->idx); status = cipher_set_iv(c, test_case->idx, direction_encrypt);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
} }
if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
debug_print(mod_cipher, "IV: %s",
octet_string_hex_string(test_case->idx, 12));
/*
* Set the AAD
*/
status = cipher_set_aad(c, test_case->aad,
test_case->aad_length_octets);
if (status) {
cipher_dealloc(c);
return status;
}
debug_print(mod_cipher, "AAD: %s",
octet_string_hex_string(test_case->aad,
test_case->aad_length_octets));
}
/* encrypt */ /* encrypt */
len = test_case->plaintext_length_octets; len = test_case->plaintext_length_octets;
status = cipher_encrypt(c, buffer, &len); status = cipher_encrypt(c, buffer, &len);
@ -150,6 +169,18 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
return status; return status;
} }
if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
/*
* Get the GCM tag
*/
status = cipher_get_tag(c, buffer + len, &tag_len);
if (status) {
cipher_dealloc(c);
return status;
}
len += tag_len;
}
debug_print(mod_cipher, "ciphertext: %s", debug_print(mod_cipher, "ciphertext: %s",
octet_string_hex_string(buffer, octet_string_hex_string(buffer,
test_case->ciphertext_length_octets)); test_case->ciphertext_length_octets));
@ -184,7 +215,7 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
debug_print(mod_cipher, "testing decryption", NULL); debug_print(mod_cipher, "testing decryption", NULL);
/* re-initialize cipher for decryption */ /* re-initialize cipher for decryption */
status = cipher_init(c, test_case->key, direction_decrypt); status = cipher_init(c, test_case->key);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
@ -203,12 +234,27 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
test_case->plaintext_length_octets)); test_case->plaintext_length_octets));
/* set the initialization vector */ /* set the initialization vector */
status = cipher_set_iv(c, test_case->idx); status = cipher_set_iv(c, test_case->idx, direction_decrypt);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
} }
if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
/*
* Set the AAD
*/
status = cipher_set_aad(c, test_case->aad,
test_case->aad_length_octets);
if (status) {
cipher_dealloc(c);
return status;
}
debug_print(mod_cipher, "AAD: %s",
octet_string_hex_string(test_case->aad,
test_case->aad_length_octets));
}
/* decrypt */ /* decrypt */
len = test_case->ciphertext_length_octets; len = test_case->ciphertext_length_octets;
status = cipher_decrypt(c, buffer, &len); status = cipher_decrypt(c, buffer, &len);
@ -297,19 +343,34 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
if (status) return status; if (status) return status;
/* initialize cipher */ /* initialize cipher */
status = cipher_init(c, key, direction_encrypt); status = cipher_init(c, key);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
} }
/* set initialization vector */ /* set initialization vector */
status = cipher_set_iv(c, test_case->idx); status = cipher_set_iv(c, test_case->idx, direction_encrypt);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
} }
if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
/*
* Set the AAD
*/
status = cipher_set_aad(c, test_case->aad,
test_case->aad_length_octets);
if (status) {
cipher_dealloc(c);
return status;
}
debug_print(mod_cipher, "AAD: %s",
octet_string_hex_string(test_case->aad,
test_case->aad_length_octets));
}
/* encrypt buffer with cipher */ /* encrypt buffer with cipher */
plaintext_len = length; plaintext_len = length;
status = cipher_encrypt(c, buffer, &length); status = cipher_encrypt(c, buffer, &length);
@ -317,6 +378,17 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
} }
if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
/*
* Get the GCM tag
*/
status = cipher_get_tag(c, buffer + length, &tag_len);
if (status) {
cipher_dealloc(c);
return status;
}
length += tag_len;
}
debug_print(mod_cipher, "ciphertext: %s", debug_print(mod_cipher, "ciphertext: %s",
octet_string_hex_string(buffer, length)); octet_string_hex_string(buffer, length));
@ -324,16 +396,30 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
* re-initialize cipher for decryption, re-set the iv, then * re-initialize cipher for decryption, re-set the iv, then
* decrypt the ciphertext * decrypt the ciphertext
*/ */
status = cipher_init(c, key, direction_decrypt); status = cipher_init(c, key);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
} }
status = cipher_set_iv(c, test_case->idx); status = cipher_set_iv(c, test_case->idx, direction_decrypt);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
return status; return status;
} }
if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
/*
* Set the AAD
*/
status = cipher_set_aad(c, test_case->aad,
test_case->aad_length_octets);
if (status) {
cipher_dealloc(c);
return status;
}
debug_print(mod_cipher, "AAD: %s",
octet_string_hex_string(test_case->aad,
test_case->aad_length_octets));
}
status = cipher_decrypt(c, buffer, &length); status = cipher_decrypt(c, buffer, &length);
if (status) { if (status) {
cipher_dealloc(c); cipher_dealloc(c);
@ -344,8 +430,9 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
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 (length != (unsigned int)plaintext_len) if (length != (unsigned int)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++)
if (buffer[i] != buffer2[i]) { if (buffer[i] != buffer2[i]) {
@ -405,7 +492,7 @@ cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_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) {
cipher_set_iv(c, &nonce); cipher_set_iv(c, &nonce, direction_encrypt);
cipher_encrypt(c, enc_buf, &len); cipher_encrypt(c, enc_buf, &len);
} }
timer = clock() - timer; timer = clock() - timer;

View File

@ -10,7 +10,7 @@
/* /*
* *
* Copyright (c) 2001-2006, Cisco Systems, Inc. * Copyright (c) 2001-2006,2013 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
@ -130,6 +130,8 @@ null_cipher_test_0 = {
NULL, /* plaintext */ NULL, /* plaintext */
0, /* octets in plaintext */ 0, /* octets in plaintext */
NULL, /* ciphertext */ NULL, /* ciphertext */
0,
NULL,
NULL /* pointer to next testcase */ NULL /* pointer to next testcase */
}; };
@ -142,9 +144,11 @@ cipher_type_t null_cipher = {
(cipher_alloc_func_t) null_cipher_alloc, (cipher_alloc_func_t) null_cipher_alloc,
(cipher_dealloc_func_t) null_cipher_dealloc, (cipher_dealloc_func_t) null_cipher_dealloc,
(cipher_init_func_t) null_cipher_init, (cipher_init_func_t) null_cipher_init,
(cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) null_cipher_encrypt, (cipher_encrypt_func_t) null_cipher_encrypt,
(cipher_decrypt_func_t) null_cipher_encrypt, (cipher_decrypt_func_t) null_cipher_encrypt,
(cipher_set_iv_func_t) null_cipher_set_iv, (cipher_set_iv_func_t) null_cipher_set_iv,
(cipher_get_tag_func_t) 0,
(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,

View File

@ -0,0 +1,297 @@
/*
* hmac_ossl.c
*
* Implementation of hmac auth_type_t that leverages OpenSSL
*
* John A. Foley
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2013, 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 "hmac.h"
#include "alloc.h"
#include <openssl/evp.h>
/* the debug module for authentiation */
debug_module_t mod_hmac = {
0, /* debugging is off by default */
"hmac sha-1 openssl" /* printable name for module */
};
err_status_t
hmac_alloc (auth_t **a, int key_len, int out_len)
{
extern auth_type_t hmac;
uint8_t *pointer;
hmac_ctx_t *new_hmac_ctx;
debug_print(mod_hmac, "allocating auth func with key length %d", key_len);
debug_print(mod_hmac, " tag length %d", out_len);
/*
* check key length - note that we don't support keys larger
* than 20 bytes yet
*/
if (key_len > 20) {
return err_status_bad_param;
}
/* check output length - should be less than 20 bytes */
if (out_len > 20) {
return err_status_bad_param;
}
/* allocate memory for auth and hmac_ctx_t structures */
pointer = (uint8_t*)crypto_alloc(sizeof(hmac_ctx_t) + sizeof(auth_t));
if (pointer == NULL) {
return err_status_alloc_fail;
}
/* set pointers */
*a = (auth_t*)pointer;
(*a)->type = &hmac;
(*a)->state = pointer + sizeof(auth_t);
(*a)->out_len = out_len;
(*a)->key_len = key_len;
(*a)->prefix_len = 0;
new_hmac_ctx = (hmac_ctx_t*)((*a)->state);
memset(new_hmac_ctx, 0, sizeof(hmac_ctx_t));
/* increment global count of all hmac uses */
hmac.ref_count++;
return err_status_ok;
}
err_status_t
hmac_dealloc (auth_t *a)
{
extern auth_type_t hmac;
hmac_ctx_t *hmac_ctx;
hmac_ctx = (hmac_ctx_t*)a->state;
if (hmac_ctx->ctx_initialized) {
EVP_MD_CTX_cleanup(&hmac_ctx->ctx);
}
if (hmac_ctx->init_ctx_initialized) {
EVP_MD_CTX_cleanup(&hmac_ctx->init_ctx);
}
/* zeroize entire state*/
octet_string_set_to_zero((uint8_t*)a,
sizeof(hmac_ctx_t) + sizeof(auth_t));
/* free memory */
crypto_free(a);
/* decrement global count of all hmac uses */
hmac.ref_count--;
return err_status_ok;
}
err_status_t
hmac_init (hmac_ctx_t *state, const uint8_t *key, int key_len)
{
int i;
uint8_t ipad[64];
/*
* check key length - note that we don't support keys larger
* than 20 bytes yet
*/
if (key_len > 20) {
return err_status_bad_param;
}
/*
* set values of ipad and opad by exoring the key into the
* appropriate constant values
*/
for (i = 0; i < key_len; i++) {
ipad[i] = key[i] ^ 0x36;
state->opad[i] = key[i] ^ 0x5c;
}
/* set the rest of ipad, opad to constant values */
for (; i < 64; i++) {
ipad[i] = 0x36;
((uint8_t*)state->opad)[i] = 0x5c;
}
debug_print(mod_hmac, "ipad: %s", octet_string_hex_string(ipad, 64));
/* initialize sha1 context */
sha1_init(&state->init_ctx);
state->init_ctx_initialized = 1;
/* hash ipad ^ key */
sha1_update(&state->init_ctx, ipad, 64);
return (hmac_start(state));
}
err_status_t
hmac_start (hmac_ctx_t *state)
{
if (state->ctx_initialized) {
EVP_MD_CTX_cleanup(&state->ctx);
}
if (!EVP_MD_CTX_copy(&state->ctx, &state->init_ctx)) {
return err_status_auth_fail;
} else {
state->ctx_initialized = 1;
return err_status_ok;
}
}
err_status_t
hmac_update (hmac_ctx_t *state, const uint8_t *message, int msg_octets)
{
debug_print(mod_hmac, "input: %s",
octet_string_hex_string(message, msg_octets));
/* hash message into sha1 context */
sha1_update(&state->ctx, message, msg_octets);
return err_status_ok;
}
err_status_t
hmac_compute (hmac_ctx_t *state, const void *message,
int msg_octets, int tag_len, uint8_t *result)
{
uint32_t hash_value[5];
uint32_t H[5];
int i;
/* check tag length, return error if we can't provide the value expected */
if (tag_len > 20) {
return err_status_bad_param;
}
/* hash message, copy output into H */
sha1_update(&state->ctx, message, msg_octets);
sha1_final(&state->ctx, H);
/*
* note that we don't need to debug_print() the input, since the
* function hmac_update() already did that for us
*/
debug_print(mod_hmac, "intermediate state: %s",
octet_string_hex_string((uint8_t*)H, 20));
/* re-initialize hash context */
sha1_init(&state->ctx);
/* hash opad ^ key */
sha1_update(&state->ctx, (uint8_t*)state->opad, 64);
/* hash the result of the inner hash */
sha1_update(&state->ctx, (uint8_t*)H, 20);
/* the result is returned in the array hash_value[] */
sha1_final(&state->ctx, hash_value);
/* copy hash_value to *result */
for (i = 0; i < tag_len; i++) {
result[i] = ((uint8_t*)hash_value)[i];
}
debug_print(mod_hmac, "output: %s",
octet_string_hex_string((uint8_t*)hash_value, tag_len));
return err_status_ok;
}
/* begin test case 0 */
uint8_t
hmac_test_case_0_key[20] = {
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b
};
uint8_t
hmac_test_case_0_data[8] = {
0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */
};
uint8_t
hmac_test_case_0_tag[20] = {
0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e,
0xf1, 0x46, 0xbe, 0x00
};
auth_test_case_t
hmac_test_case_0 = {
20, /* octets in key */
hmac_test_case_0_key, /* key */
8, /* octets in data */
hmac_test_case_0_data, /* data */
20, /* octets in tag */
hmac_test_case_0_tag, /* tag */
NULL /* pointer to next testcase */
};
/* end test case 0 */
char hmac_description[] = "hmac sha-1 authentication function";
/*
* auth_type_t hmac is the hmac metaobject
*/
auth_type_t
hmac = {
(auth_alloc_func) hmac_alloc,
(auth_dealloc_func) hmac_dealloc,
(auth_init_func) hmac_init,
(auth_compute_func) hmac_compute,
(auth_update_func) hmac_update,
(auth_start_func) hmac_start,
(char*) hmac_description,
(int) 0, /* instance count */
(auth_test_case_t*) &hmac_test_case_0,
(debug_module_t*) &mod_hmac,
(auth_type_id_t) HMAC_SHA1
};

View File

@ -17,6 +17,8 @@
typedef struct { typedef struct {
v128_t state; /* cipher chaining state */ v128_t state; /* cipher chaining state */
v128_t previous; /* previous ciphertext block */ v128_t previous; /* previous ciphertext block */
uint8_t key[32];
int key_len;
aes_expanded_key_t expanded_key; /* the cipher key */ aes_expanded_key_t expanded_key; /* the cipher key */
} aes_cbc_ctx_t; } aes_cbc_ctx_t;
@ -31,10 +33,10 @@ 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,
int key_len, cipher_direction_t dir); int key_len);
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, int direction);
err_status_t err_status_t
aes_cbc_nist_encrypt(aes_cbc_ctx_t *c, aes_cbc_nist_encrypt(aes_cbc_ctx_t *c,

View File

@ -0,0 +1,62 @@
/*
* aes_gcm_ossl.h
*
* Header for AES Galois Counter Mode.
*
* John A. Foley
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013, 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 AES_GCM_OSSL_H
#define AES_GCM_OSSL_H
#include "cipher.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
typedef struct {
v256_t key;
int key_size;
int tag_len;
EVP_CIPHER_CTX ctx;
cipher_direction_t dir;
} aes_gcm_ctx_t;
#endif /* AES_GCM_OSSL_H */

View File

@ -29,7 +29,7 @@ aes_icm_context_init(aes_icm_ctx_t *c,
int key_len); 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, int direction);
err_status_t err_status_t
aes_icm_encrypt(aes_icm_ctx_t *c, aes_icm_encrypt(aes_icm_ctx_t *c,

View File

@ -0,0 +1,73 @@
/*
* aes_icm.h
*
* Header for AES Integer Counter Mode.
*
* David A. McGrew
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2001-2005,2012, 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 AES_ICM_H
#define AES_ICM_H
#include "cipher.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
#define SALT_SIZE 14
#define AES_128_KEYSIZE AES_BLOCK_SIZE
#define AES_192_KEYSIZE AES_BLOCK_SIZE + AES_BLOCK_SIZE / 2
#define AES_256_KEYSIZE AES_BLOCK_SIZE * 2
#define AES_128_KEYSIZE_WSALT AES_128_KEYSIZE + SALT_SIZE
#define AES_192_KEYSIZE_WSALT AES_192_KEYSIZE + SALT_SIZE
#define AES_256_KEYSIZE_WSALT AES_256_KEYSIZE + SALT_SIZE
typedef struct {
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
v256_t key;
int key_size;
EVP_CIPHER_CTX ctx;
} aes_icm_ctx_t;
err_status_t aes_icm_openssl_set_iv(aes_icm_ctx_t *c, void *iv, int dir);
#endif /* AES_ICM_H */

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2006, Cisco Systems, Inc. * Copyright (c) 2001-2006,2013 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
@ -84,11 +84,10 @@ typedef err_status_t (*cipher_alloc_func_t)
/* /*
* a cipher_init_func_t [re-]initializes a cipher_t with a given key * a cipher_init_func_t [re-]initializes a cipher_t with a given key
* and direction (i.e., encrypt or decrypt)
*/ */
typedef err_status_t (*cipher_init_func_t) typedef err_status_t (*cipher_init_func_t)
(void *state, const uint8_t *key, int key_len, cipher_direction_t dir); (void *state, const uint8_t *key, int key_len);
/* a cipher_dealloc_func_t de-allocates a cipher_t */ /* a cipher_dealloc_func_t de-allocates a cipher_t */
@ -99,6 +98,13 @@ typedef err_status_t (*cipher_dealloc_func_t)(cipher_pointer_t cp);
typedef err_status_t (*cipher_set_segment_func_t) typedef err_status_t (*cipher_set_segment_func_t)
(void *state, xtd_seq_num_t idx); (void *state, xtd_seq_num_t idx);
/*
* a cipher_set_aad_func_t processes the AAD data for AEAD ciphers
*/
typedef err_status_t (*cipher_set_aad_func_t)
(void *state, uint8_t *aad, unsigned int aad_len);
/* a cipher_encrypt_func_t encrypts data in-place */ /* a cipher_encrypt_func_t encrypts data in-place */
typedef err_status_t (*cipher_encrypt_func_t) typedef err_status_t (*cipher_encrypt_func_t)
@ -114,7 +120,15 @@ typedef err_status_t (*cipher_decrypt_func_t)
*/ */
typedef err_status_t (*cipher_set_iv_func_t) typedef err_status_t (*cipher_set_iv_func_t)
(cipher_pointer_t cp, void *iv); (cipher_pointer_t cp, void *iv, cipher_direction_t direction);
/*
* a cipher_get_tag_funct_t function is used to get the authentication
* tag that was calculated by an AEAD cipher.
*/
typedef err_status_t (*cipher_get_tag_func_t)
(void *state, void *tag, int *len);
/* /*
* cipher_test_case_t is a (list of) key, salt, xtd_seq_num_t, * cipher_test_case_t is a (list of) key, salt, xtd_seq_num_t,
@ -132,6 +146,8 @@ typedef struct cipher_test_case_t {
uint8_t *plaintext; /* plaintext */ uint8_t *plaintext; /* plaintext */
int ciphertext_length_octets; /* octets in plaintext */ int ciphertext_length_octets; /* octets in plaintext */
uint8_t *ciphertext; /* ciphertext */ uint8_t *ciphertext; /* ciphertext */
int aad_length_octets; /* octets in AAD */
uint8_t *aad; /* AAD */
struct cipher_test_case_t *next_test_case; /* pointer to next testcase */ struct cipher_test_case_t *next_test_case; /* pointer to next testcase */
} cipher_test_case_t; } cipher_test_case_t;
@ -141,9 +157,11 @@ typedef struct cipher_type_t {
cipher_alloc_func_t alloc; cipher_alloc_func_t alloc;
cipher_dealloc_func_t dealloc; cipher_dealloc_func_t dealloc;
cipher_init_func_t init; cipher_init_func_t init;
cipher_set_aad_func_t set_aad;
cipher_encrypt_func_t encrypt; cipher_encrypt_func_t encrypt;
cipher_encrypt_func_t decrypt; cipher_encrypt_func_t decrypt;
cipher_set_iv_func_t set_iv; cipher_set_iv_func_t set_iv;
cipher_get_tag_func_t get_tag;
char *description; char *description;
int ref_count; int ref_count;
cipher_test_case_t *test_data; cipher_test_case_t *test_data;
@ -160,9 +178,7 @@ typedef struct cipher_t {
cipher_type_t *type; cipher_type_t *type;
void *state; void *state;
int key_len; int key_len;
#ifdef FORCE_64BIT_ALIGN int algorithm;
int pad;
#endif
} cipher_t; } cipher_t;
/* some syntactic sugar on these function types */ /* some syntactic sugar on these function types */
@ -171,16 +187,23 @@ 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), ((c)->key_len), (dir))) #define cipher_init(c, k) (((c)->type)->init(((c)->state), (k), ((c)->key_len)))
#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)))
#define cipher_get_tag(c, buf, len) \
(((c)->type)->get_tag(((c)->state), (buf), (len)))
#define cipher_decrypt(c, buf, len) \ #define cipher_decrypt(c, buf, len) \
(((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, dir) \
((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)->state), (n))) : \ ((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)->state), (n), (dir))) : \
err_status_no_such_op)
#define cipher_set_aad(c, a, l) \
(((c) && (((c)->type)->set_aad)) ? \
(((c)->type)->set_aad(((c)->state), (a), (l))) : \
err_status_no_such_op) err_status_no_such_op)
err_status_t err_status_t

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2006 Cisco Systems, Inc. * Copyright(c) 2001-2006,2013 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
@ -141,6 +141,34 @@
*/ */
#define STRONGHOLD_CIPHER AES_ICM #define STRONGHOLD_CIPHER AES_ICM
/**
* @brief AES-192 Integer Counter Mode (AES ICM)
* AES-192 ICM is a deprecated alternate name for AES ICM.
*/
#define AES_192_ICM 4
/**
* @brief AES-256 Integer Counter Mode (AES ICM)
* AES-256 ICM is a deprecated alternate name for AES ICM.
*/
#define AES_256_ICM 5
/**
* @brief AES-128_GCM Galois Counter Mode (AES GCM)
*
* AES-128 GCM is the variant of galois counter mode that is used by
* Secure RTP. This cipher uses a 16-octet key.
*/
#define AES_128_GCM 6
/**
* @brief AES-256_GCM Galois Counter Mode (AES GCM)
*
* AES-256 GCM is the variant of galois counter mode that is used by
* Secure RTP. This cipher uses a 32-octet key.
*/
#define AES_256_GCM 7
/** /**
* @} * @}
*/ */

View File

@ -92,6 +92,12 @@ typedef union {
uint64_t v64[2]; uint64_t v64[2];
} v128_t; } v128_t;
typedef union {
uint8_t v8[32];
uint16_t v16[16];
uint32_t v32[8];
uint64_t v64[4];
} v256_t;
/* some useful and simple math functions */ /* some useful and simple math functions */

View File

@ -9,7 +9,7 @@
*/ */
/* /*
* *
* Copyright (c) 2001-2006, Cisco Systems, Inc. * Copyright (c) 2001-2006,2013, 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
@ -53,6 +53,10 @@ typedef struct {
uint8_t opad[64]; uint8_t opad[64];
sha1_ctx_t ctx; sha1_ctx_t ctx;
sha1_ctx_t init_ctx; sha1_ctx_t init_ctx;
#ifdef OPENSSL
int ctx_initialized;
int init_ctx_initialized;
#endif
} hmac_ctx_t; } hmac_ctx_t;
err_status_t err_status_t

View File

@ -12,7 +12,12 @@
#include "rand_source.h" /* for rand_source_func_t definition */ #include "rand_source.h" /* for rand_source_func_t definition */
#include "aes.h" /* for aes */ #include "aes.h" /* for aes */
//FIXME: this is temporary until we pull in the code to use OpenSSL for RNG
#ifdef OPENSSL
#include "aes_icm_ossl.h" /* for aes ctr */
#else
#include "aes_icm.h" /* for aes ctr */ #include "aes_icm.h" /* for aes ctr */
#endif
#define MAX_PRNG_OUT_LEN 0xffffffffU #define MAX_PRNG_OUT_LEN 0xffffffffU

View File

@ -48,6 +48,43 @@
#define SHA1_H #define SHA1_H
#include "err.h" #include "err.h"
#ifdef OPENSSL
#include <openssl/evp.h>
typedef EVP_MD_CTX sha1_ctx_t;
/*
* sha1_init(&ctx) initializes the SHA1 context ctx
*
* sha1_update(&ctx, msg, len) hashes the len octets starting at msg
* into the SHA1 context
*
* sha1_final(&ctx, output) performs the final processing of the SHA1
* context and writes the result to the 20 octets at output
*
* Return values are ignored on the EVP functions since all three
* of these functions return void.
*
*/
void inline sha1_init (sha1_ctx_t *ctx)
{
EVP_MD_CTX_init(ctx);
EVP_DigestInit(ctx, EVP_sha1());
}
void inline sha1_update (sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg)
{
EVP_DigestUpdate(ctx, M, octets_in_msg);
}
void inline sha1_final (sha1_ctx_t *ctx, uint32_t *output)
{
unsigned int len = 0;
EVP_DigestFinal(ctx, (unsigned char*)output, &len);
}
#else
#include "datatypes.h" #include "datatypes.h"
typedef struct { typedef struct {
@ -104,5 +141,7 @@ sha1_final(sha1_ctx_t *ctx, uint32_t output[5]);
void void
sha1_core(const uint32_t M[16], uint32_t hash_value[5]); sha1_core(const uint32_t M[16], uint32_t hash_value[5]);
#endif /* else OPENSSL */
#endif /* SHA1_H */ #endif /* SHA1_H */

View File

@ -8,7 +8,7 @@
*/ */
/* /*
* *
* Copyright(c) 2001-2006 Cisco Systems, Inc. * Copyright(c) 2001-2006,2013 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
@ -69,7 +69,12 @@ extern debug_module_t mod_alloc;
extern cipher_type_t null_cipher; extern cipher_type_t null_cipher;
extern cipher_type_t aes_icm; extern cipher_type_t aes_icm;
#ifndef OPENSSL
extern cipher_type_t aes_cbc; extern cipher_type_t aes_cbc;
#else
extern cipher_type_t aes_gcm_128_openssl;
extern cipher_type_t aes_gcm_256_openssl;
#endif
/* /*
@ -137,6 +142,7 @@ crypto_kernel_init() {
if (status) if (status)
return status; return status;
#ifndef OPENSSL
/* initialize pseudorandom number generator */ /* initialize pseudorandom number generator */
status = ctr_prng_init(rand_source_get_octet_string); status = ctr_prng_init(rand_source_get_octet_string);
if (status) if (status)
@ -146,6 +152,7 @@ crypto_kernel_init() {
status = stat_test_rand_source_with_repetition(ctr_prng_get_octet_string, MAX_RNG_TRIALS); status = stat_test_rand_source_with_repetition(ctr_prng_get_octet_string, MAX_RNG_TRIALS);
if (status) if (status)
return status; return status;
#endif
/* load cipher types */ /* load cipher types */
status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER); status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER);
@ -154,9 +161,20 @@ crypto_kernel_init() {
status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM); status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM);
if (status) if (status)
return status; return status;
#ifndef OPENSSL
status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC); status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC);
if (status) if (status)
return status; return status;
#else
status = crypto_kernel_load_cipher_type(&aes_gcm_128_openssl, AES_128_GCM);
if (status) {
return status;
}
status = crypto_kernel_load_cipher_type(&aes_gcm_256_openssl, AES_256_GCM);
if (status) {
return status;
}
#endif
/* load auth func types */ /* load auth func types */
status = crypto_kernel_load_auth_type(&null_auth, NULL_AUTH); status = crypto_kernel_load_auth_type(&null_auth, NULL_AUTH);
@ -567,7 +585,11 @@ crypto_kernel_set_debug_module(char *name, int on) {
err_status_t err_status_t
crypto_get_random(unsigned char *buffer, unsigned int length) { crypto_get_random(unsigned char *buffer, unsigned int length) {
if (crypto_kernel.state == crypto_kernel_state_secure) if (crypto_kernel.state == crypto_kernel_state_secure)
#ifdef OPENSSL
return rand_source_get_octet_string(buffer, length);
#else
return ctr_prng_get_octet_string(buffer, length); return ctr_prng_get_octet_string(buffer, length);
#endif
else else
return err_status_fail; return err_status_fail;
} }

View File

@ -66,7 +66,11 @@ 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 */
#ifdef OPENSSL
status = aes_icm_openssl_context_init(&ctr_prng.state, tmp_key, 30);
#else
status = aes_icm_context_init(&ctr_prng.state, tmp_key, 30); status = aes_icm_context_init(&ctr_prng.state, tmp_key, 30);
#endif
if (status) if (status)
return status; return status;

View File

@ -0,0 +1,66 @@
/*
* rand_source_ossl.c
*
* implements a random source based on OpenSSL RAND_bytes()
*
* John A. Foley
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2013, 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:crypto/test/aes_calc.c
*
* 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 "rand_source.h"
#include <openssl/rand.h>
err_status_t rand_source_init (void)
{
return err_status_ok;
}
err_status_t rand_source_get_octet_string (void *dest, uint32_t len)
{
if (RAND_bytes(dest, len) == 1) {
return err_status_ok;
} else {
return err_status_fail;
}
}
err_status_t rand_source_deinit (void)
{
return err_status_ok;
}

View File

@ -9,7 +9,7 @@
/* /*
* *
* Copyright (c) 2001-2006, Cisco Systems, Inc. * Copyright (c) 2001-2006,2013 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,12 @@
#include <string.h> /* for memset() */ #include <string.h> /* for memset() */
#include <unistd.h> /* for getopt() */ #include <unistd.h> /* for getopt() */
#include "cipher.h" #include "cipher.h"
#ifdef OPENSSL
#include "aes_icm_ossl.h"
#include "aes_gcm_ossl.h"
#else
#include "aes_icm.h" #include "aes_icm.h"
#endif
#include "null_cipher.h" #include "null_cipher.h"
#define PRINT_DEBUG 0 #define PRINT_DEBUG 0
@ -114,7 +119,14 @@ check_status(err_status_t s) {
extern cipher_type_t null_cipher; extern cipher_type_t null_cipher;
extern cipher_type_t aes_icm; extern cipher_type_t aes_icm;
#ifndef OPENSSL
extern cipher_type_t aes_cbc; extern cipher_type_t aes_cbc;
#else
extern cipher_type_t aes_icm_192;
extern cipher_type_t aes_icm_256;
extern cipher_type_t aes_gcm_128_openssl;
extern cipher_type_t aes_gcm_256_openssl;
#endif
int int
main(int argc, char *argv[]) { main(int argc, char *argv[]) {
@ -171,6 +183,7 @@ 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);
#ifndef OPENSSL
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, 46, num_cipher); cipher_driver_test_array_throughput(&aes_icm, 46, num_cipher);
@ -179,19 +192,41 @@ 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_cbc, 32, num_cipher); cipher_driver_test_array_throughput(&aes_cbc, 32, num_cipher);
#else
for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
cipher_driver_test_array_throughput(&aes_icm_192, 38, num_cipher);
for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8)
cipher_driver_test_array_throughput(&aes_icm_256, 46, num_cipher);
for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) {
cipher_driver_test_array_throughput(&aes_gcm_128_openssl, 30, num_cipher);
}
for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) {
cipher_driver_test_array_throughput(&aes_gcm_256_openssl, 46, num_cipher);
}
#endif
} }
if (do_validation) { if (do_validation) {
cipher_driver_self_test(&null_cipher); cipher_driver_self_test(&null_cipher);
cipher_driver_self_test(&aes_icm); cipher_driver_self_test(&aes_icm);
#ifndef OPENSSL
cipher_driver_self_test(&aes_cbc); cipher_driver_self_test(&aes_cbc);
#else
cipher_driver_self_test(&aes_icm_192);
cipher_driver_self_test(&aes_icm_256);
cipher_driver_self_test(&aes_gcm_128_openssl);
cipher_driver_self_test(&aes_gcm_256_openssl);
#endif
} }
/* do timing and/or buffer_test on null_cipher */ /* do timing and/or buffer_test on null_cipher */
status = cipher_type_alloc(&null_cipher, &c, 0); status = cipher_type_alloc(&null_cipher, &c, 0);
check_status(status); check_status(status);
status = cipher_init(c, NULL, direction_encrypt); status = cipher_init(c, NULL);
check_status(status); check_status(status);
if (do_timing_test) if (do_timing_test)
@ -211,7 +246,7 @@ main(int argc, char *argv[]) {
exit(status); exit(status);
} }
status = cipher_init(c, test_key, direction_encrypt); status = cipher_init(c, test_key);
check_status(status); check_status(status);
if (do_timing_test) if (do_timing_test)
@ -226,13 +261,17 @@ main(int argc, char *argv[]) {
check_status(status); check_status(status);
/* repeat the tests with 256-bit keys */ /* repeat the tests with 256-bit keys */
#ifndef OPENSSL
status = cipher_type_alloc(&aes_icm, &c, 46); status = cipher_type_alloc(&aes_icm, &c, 46);
#else
status = cipher_type_alloc(&aes_icm_256, &c, 46);
#endif
if (status) { if (status) {
fprintf(stderr, "error: can't allocate cipher\n"); fprintf(stderr, "error: can't allocate cipher\n");
exit(status); exit(status);
} }
status = cipher_init(c, test_key, direction_encrypt); status = cipher_init(c, test_key);
check_status(status); check_status(status);
if (do_timing_test) if (do_timing_test)
@ -245,8 +284,48 @@ main(int argc, char *argv[]) {
status = cipher_dealloc(c); status = cipher_dealloc(c);
check_status(status); check_status(status);
return 0; #ifdef OPENSSL
/* run the throughput test on the aes_gcm_128_openssl cipher */
status = cipher_type_alloc(&aes_gcm_128_openssl, &c, 30);
if (status) {
fprintf(stderr, "error: can't allocate GCM 128 cipher\n");
exit(status);
}
status = cipher_init(c, test_key);
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);
/* run the throughput test on the aes_gcm_256_openssl cipher */
status = cipher_type_alloc(&aes_gcm_256_openssl, &c, 46);
if (status) {
fprintf(stderr, "error: can't allocate GCM 256 cipher\n");
exit(status);
}
status = cipher_init(c, test_key);
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);
#endif
return 0;
} }
void void
@ -306,7 +385,7 @@ cipher_driver_test_buffering(cipher_t *c) {
buffer0[j] = buffer1[j] = 0; buffer0[j] = buffer1[j] = 0;
/* initialize cipher */ /* initialize cipher */
status = cipher_set_iv(c, idx); status = cipher_set_iv(c, idx, direction_encrypt);
if (status) if (status)
return status; return status;
@ -316,7 +395,7 @@ cipher_driver_test_buffering(cipher_t *c) {
return status; return status;
/* re-initialize cipher */ /* re-initialize cipher */
status = cipher_set_iv(c, idx); status = cipher_set_iv(c, idx, direction_encrypt);
if (status) if (status)
return status; return status;
@ -409,7 +488,7 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
key[j] = (uint8_t) rand(); key[j] = (uint8_t) rand();
for (; j < klen_pad; j++) for (; j < klen_pad; j++)
key[j] = 0; key[j] = 0;
status = cipher_init(*cipher_array, key, direction_encrypt); status = cipher_init(*cipher_array, key);
if (status) if (status)
return status; return status;
@ -476,7 +555,7 @@ cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher,
unsigned octets_to_encrypt = octets_in_buffer; 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, direction_encrypt);
cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_to_encrypt); cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_to_encrypt);
/* choose a cipher at random from the array*/ /* choose a cipher at random from the array*/

View File

@ -80,6 +80,7 @@ main(void) {
printf("using stdout for error reporting\t(ERR_REPORTING_STDOUT == 1)\n"); printf("using stdout for error reporting\t(ERR_REPORTING_STDOUT == 1)\n");
#endif #endif
#ifndef OPENSSL
#ifdef DEV_URANDOM #ifdef DEV_URANDOM
str = DEV_URANDOM; str = DEV_URANDOM;
#else #else
@ -90,6 +91,7 @@ main(void) {
if (strcmp("", str) == 0) { if (strcmp("", str) == 0) {
err_count++; err_count++;
} }
#endif
if (err_count) if (err_count)
printf("warning: configuration is probably in error " printf("warning: configuration is probably in error "

View File

@ -32,10 +32,14 @@ err_check(err_status_t s) {
int int
main (int argc, char *argv[]) { main (int argc, char *argv[]) {
uint8_t buffer[2500]; uint8_t buffer[2532];
unsigned int buf_len = 2500; unsigned int buf_len = 2500;
int i, j; int i, j;
extern cipher_type_t aes_icm; extern cipher_type_t aes_icm;
#ifdef OPENSSL
extern cipher_type_t aes_gcm_128_openssl;
extern cipher_type_t aes_gcm_256_openssl;
#endif
cipher_t *c; cipher_t *c;
uint8_t key[46] = { uint8_t key[46] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@ -73,8 +77,8 @@ main (int argc, char *argv[]) {
for (i=0; i < 2500; i++) for (i=0; i < 2500; i++)
buffer[i] = 0; buffer[i] = 0;
err_check(cipher_type_alloc(&aes_icm, &c, 30)); err_check(cipher_type_alloc(&aes_icm, &c, 30));
err_check(cipher_init(c, key, direction_encrypt)); err_check(cipher_init(c, key));
err_check(cipher_set_iv(c, &nonce)); err_check(cipher_set_iv(c, &nonce, direction_encrypt));
err_check(cipher_encrypt(c, buffer, &buf_len)); err_check(cipher_encrypt(c, buffer, &buf_len));
/* run tests on cipher outout */ /* run tests on cipher outout */
printf("monobit %d\n", stat_test_monobit(buffer)); printf("monobit %d\n", stat_test_monobit(buffer));
@ -89,7 +93,7 @@ main (int argc, char *argv[]) {
for (i=0; i < 2500; i++) for (i=0; i < 2500; i++)
buffer[i] = 0; buffer[i] = 0;
nonce.v32[3] = i; nonce.v32[3] = i;
err_check(cipher_set_iv(c, &nonce)); err_check(cipher_set_iv(c, &nonce, direction_encrypt));
err_check(cipher_encrypt(c, buffer, &buf_len)); err_check(cipher_encrypt(c, buffer, &buf_len));
if (stat_test_runs(buffer)) { if (stat_test_runs(buffer)) {
num_fail++; num_fail++;
@ -107,8 +111,8 @@ main (int argc, char *argv[]) {
for (i=0; i < 2500; i++) for (i=0; i < 2500; i++)
buffer[i] = 0; buffer[i] = 0;
err_check(cipher_type_alloc(&aes_icm, &c, 46)); err_check(cipher_type_alloc(&aes_icm, &c, 46));
err_check(cipher_init(c, key, direction_encrypt)); err_check(cipher_init(c, key));
err_check(cipher_set_iv(c, &nonce)); err_check(cipher_set_iv(c, &nonce, direction_encrypt));
err_check(cipher_encrypt(c, buffer, &buf_len)); err_check(cipher_encrypt(c, buffer, &buf_len));
/* run tests on cipher outout */ /* run tests on cipher outout */
printf("monobit %d\n", stat_test_monobit(buffer)); printf("monobit %d\n", stat_test_monobit(buffer));
@ -123,13 +127,75 @@ main (int argc, char *argv[]) {
for (i=0; i < 2500; i++) for (i=0; i < 2500; i++)
buffer[i] = 0; buffer[i] = 0;
nonce.v32[3] = i; nonce.v32[3] = i;
err_check(cipher_set_iv(c, &nonce)); err_check(cipher_set_iv(c, &nonce, direction_encrypt));
err_check(cipher_encrypt(c, buffer, &buf_len)); err_check(cipher_encrypt(c, buffer, &buf_len));
if (stat_test_runs(buffer)) { if (stat_test_runs(buffer)) {
num_fail++; num_fail++;
} }
} }
#ifdef OPENSSL
{
printf("running stat_tests on AES-128-GCM, expecting success\n");
/* set buffer to cipher output */
for (i=0; i < 2500; i++) {
buffer[i] = 0;
}
err_check(cipher_type_alloc(&aes_gcm_128_openssl, &c, 30));
err_check(cipher_init(c, key));
err_check(cipher_set_iv(c, &nonce, direction_encrypt));
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));
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, direction_encrypt));
err_check(cipher_encrypt(c, buffer, &buf_len));
buf_len = 2500;
if (stat_test_runs(buffer)) {
num_fail++;
}
}
printf("running stat_tests on AES-256-GCM, expecting success\n");
/* set buffer to cipher output */
for (i=0; i < 2500; i++) {
buffer[i] = 0;
}
err_check(cipher_type_alloc(&aes_gcm_256_openssl, &c, 46));
err_check(cipher_init(c, key));
err_check(cipher_set_iv(c, &nonce, direction_encrypt));
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));
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, direction_encrypt));
err_check(cipher_encrypt(c, buffer, &buf_len));
buf_len = 2500;
if (stat_test_runs(buffer)) {
num_fail++;
}
}
}
#endif
printf("%d failures in %d tests\n", num_fail, num_trials); printf("%d failures in %d tests\n", num_fail, num_trials);
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");

View File

@ -88,6 +88,13 @@ extern "C" {
*/ */
#define SRTP_MAX_TRAILER_LEN SRTP_MAX_TAG_LEN #define SRTP_MAX_TRAILER_LEN SRTP_MAX_TAG_LEN
/*
* SRTP_AEAD_SALT_LEN is the length of the SALT values used with
* GCM mode. GCM mode requires an IV. The SALT value is used
* as part of the IV formation logic applied to each RTP packet.
*/
#define SRTP_AEAD_SALT_LEN 12
/* /*
* nota bene: since libSRTP doesn't support the use of the MKI, the * nota bene: since libSRTP doesn't support the use of the MKI, the
* SRTP_MAX_TRAILER_LEN value is just the maximum tag length * SRTP_MAX_TRAILER_LEN value is just the maximum tag length
@ -663,6 +670,130 @@ void crypto_policy_set_aes_cm_256_hmac_sha1_80(crypto_policy_t *p);
void void
crypto_policy_set_aes_cm_256_hmac_sha1_32(crypto_policy_t *p); crypto_policy_set_aes_cm_256_hmac_sha1_32(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_cm_256_null_auth() sets a crypto
* policy structure to an encryption-only policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_cm_256_null_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-256 Counter Mode), but to use no authentication method. This
* policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5
* of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt).
*
* 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 policy is NOT RECOMMENDED for SRTP unless it is
* unavoidable, and it is NOT RECOMMENDED at all 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_null_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_128_8_auth() sets a crypto
* policy structure to an AEAD encryption policy.
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_128_8_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-128 Galois Counter Mode) with 8 octet auth tag. This
* policy applies confidentiality and authentication to both the
* RTP and RTCP packets.
*
* 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_gcm_128_8_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_256_8_auth() sets a crypto
* policy structure to an AEAD encryption policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_256_8_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-256 Galois Counter Mode) with 8 octet auth tag. This
* policy applies confidentiality and authentication to both the
* RTP and RTCP packets.
*
* 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_gcm_256_8_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_128_8_only_auth() sets a crypto
* policy structure to an AEAD authentication-only policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_128_8_only_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-128 Galois Counter Mode) with 8 octet auth tag. This policy
* applies confidentiality and authentication to the RTP packets,
* but only authentication to the RTCP packets.
*
* 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_gcm_128_8_only_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_256_8_only_auth() sets a crypto
* policy structure to an AEAD authentication-only policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_256_8_only_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-256 Galois Counter Mode) with 8 octet auth tag. This policy
* applies confidentiality and authentication to the RTP packets,
* but only authentication to the RTCP packets.
*
* 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_gcm_256_8_only_auth(crypto_policy_t *p);
/** /**
* @brief srtp_dealloc() deallocates storage for an SRTP session * @brief srtp_dealloc() deallocates storage for an SRTP session

View File

@ -77,7 +77,7 @@ typedef struct {
unsigned m:1; /* marker bit */ unsigned m:1; /* marker bit */
unsigned seq:16; /* sequence number */ unsigned seq:16; /* sequence number */
unsigned ts:32; /* timestamp */ unsigned ts:32; /* timestamp */
unsigned ssrc:32; /* synchronization source */ uint32_t ssrc; /* synchronization source */
} srtp_hdr_t; } srtp_hdr_t;
#else /* BIG_ENDIAN */ #else /* BIG_ENDIAN */
@ -91,7 +91,7 @@ typedef struct {
unsigned pt:7; /* payload type */ unsigned pt:7; /* payload type */
unsigned seq:16; /* sequence number */ unsigned seq:16; /* sequence number */
unsigned ts:32; /* timestamp */ unsigned ts:32; /* timestamp */
unsigned ssrc:32; /* synchronization source */ uint32_t ssrc; /* synchronization source */
} srtp_hdr_t; } srtp_hdr_t;
#endif #endif
@ -117,7 +117,7 @@ typedef struct {
unsigned version:2; /* protocol version */ unsigned version:2; /* protocol version */
unsigned pt:8; /* payload type */ unsigned pt:8; /* payload type */
unsigned len:16; /* length */ unsigned len:16; /* length */
unsigned ssrc:32; /* synchronization source */ uint32_t ssrc; /* synchronization source */
} srtcp_hdr_t; } srtcp_hdr_t;
typedef struct { typedef struct {
@ -220,6 +220,8 @@ typedef struct srtp_stream_ctx_t {
direction_t direction; direction_t direction;
int allow_repeat_tx; int allow_repeat_tx;
ekt_stream_t ekt; ekt_stream_t ekt;
uint8_t salt[SRTP_AEAD_SALT_LEN]; /* used with GCM mode for SRTP */
uint8_t c_salt[SRTP_AEAD_SALT_LEN]; /* used with GCM mode for SRTCP */
struct srtp_stream_ctx_t *next; /* linked list of streams */ struct srtp_stream_ctx_t *next; /* linked list of streams */
} srtp_stream_ctx_t; } srtp_stream_ctx_t;

View File

@ -149,10 +149,13 @@ ekt_stream_init_from_policy(ekt_stream_t stream_data, ekt_policy_t policy) {
void void
aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len) { aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len) {
#ifndef OPENSSL
//FIXME: need to get this working through the crypto module interface
aes_expanded_key_t expanded_key; aes_expanded_key_t expanded_key;
aes_expand_decryption_key(key, key_len, &expanded_key); aes_expand_decryption_key(key, key_len, &expanded_key);
aes_decrypt(ciphertext, &expanded_key); aes_decrypt(ciphertext, &expanded_key);
#endif
} }
/* /*

File diff suppressed because it is too large Load Diff

View File

@ -90,8 +90,7 @@
#define USEC_RATE (5e5) #define USEC_RATE (5e5)
#define MAX_WORD_LEN 128 #define MAX_WORD_LEN 128
#define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a)) #define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a))
#define MAX_KEY_LEN 64 #define MAX_KEY_LEN 96
#define MASTER_KEY_LEN 30
#ifndef HAVE_USLEEP #ifndef HAVE_USLEEP
@ -153,6 +152,8 @@ main (int argc, char *argv[]) {
sec_serv_t sec_servs = sec_serv_none; sec_serv_t sec_servs = sec_serv_none;
unsigned char ttl = 5; unsigned char ttl = 5;
int c; int c;
int key_size = 128;
int gcm_on = 0;
char *input_key = NULL; char *input_key = NULL;
char *address = NULL; char *address = NULL;
char key[MAX_KEY_LEN]; char key[MAX_KEY_LEN];
@ -187,7 +188,7 @@ main (int argc, char *argv[]) {
/* check args */ /* check args */
while (1) { while (1) {
c = getopt_s(argc, argv, "k:rsaeld:"); c = getopt_s(argc, argv, "k:rsgae:ld:");
if (c == -1) { if (c == -1) {
break; break;
} }
@ -196,11 +197,20 @@ main (int argc, char *argv[]) {
input_key = optarg_s; input_key = optarg_s;
break; break;
case 'e': case 'e':
key_size = atoi(optarg_s);
if (key_size != 128 && key_size != 256) {
printf("error: encryption key size must be 128 or 256 (%d)\n", key_size);
exit(1);
}
sec_servs |= sec_serv_conf; sec_servs |= sec_serv_conf;
break; break;
case 'a': case 'a':
sec_servs |= sec_serv_auth; sec_servs |= sec_serv_auth;
break; break;
case 'g':
gcm_on = 1;
sec_servs |= sec_serv_auth;
break;
case 'r': case 'r':
prog_type = receiver; prog_type = receiver;
break; break;
@ -331,16 +341,73 @@ main (int argc, char *argv[]) {
*/ */
switch (sec_servs) { switch (sec_servs) {
case sec_serv_conf_and_auth: case sec_serv_conf_and_auth:
crypto_policy_set_rtp_default(&policy.rtp); if (gcm_on) {
crypto_policy_set_rtcp_default(&policy.rtcp); #ifdef OPENSSL
switch (key_size) {
case 128:
crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
break;
case 256:
crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
break;
}
#else
printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n");
return 0;
#endif
} else {
switch (key_size) {
case 128:
crypto_policy_set_rtp_default(&policy.rtp);
crypto_policy_set_rtcp_default(&policy.rtcp);
break;
case 256:
crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
crypto_policy_set_rtcp_default(&policy.rtcp);
break;
}
}
break; break;
case sec_serv_conf: case sec_serv_conf:
crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); if (gcm_on) {
crypto_policy_set_rtcp_default(&policy.rtcp); printf("error: GCM mode must always be used with auth enabled\n");
return -1;
} else {
switch (key_size) {
case 128:
crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
crypto_policy_set_rtcp_default(&policy.rtcp);
break;
case 256:
crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
crypto_policy_set_rtcp_default(&policy.rtcp);
break;
}
}
break; break;
case sec_serv_auth: case sec_serv_auth:
crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); if (gcm_on) {
crypto_policy_set_rtcp_default(&policy.rtcp); #ifdef OPENSSL
switch (key_size) {
case 128:
crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp);
break;
case 256:
crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp);
break;
}
#else
printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n");
return 0;
#endif
} else {
crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
crypto_policy_set_rtcp_default(&policy.rtcp);
}
break; break;
default: default:
printf("error: unknown security service requested\n"); printf("error: unknown security service requested\n");
@ -359,21 +426,21 @@ main (int argc, char *argv[]) {
/* /*
* read key from hexadecimal on command line into an octet string * read key from hexadecimal on command line into an octet string
*/ */
len = hex_string_to_octet_string(key, input_key, MASTER_KEY_LEN*2); len = hex_string_to_octet_string(key, input_key, policy.rtp.cipher_key_len*2);
/* check that hex string is the right length */ /* check that hex string is the right length */
if (len < MASTER_KEY_LEN*2) { if (len < policy.rtp.cipher_key_len*2) {
fprintf(stderr, fprintf(stderr,
"error: too few digits in key/salt " "error: too few digits in key/salt "
"(should be %d hexadecimal digits, found %d)\n", "(should be %d hexadecimal digits, found %d)\n",
MASTER_KEY_LEN*2, len); policy.rtp.cipher_key_len*2, len);
exit(1); exit(1);
} }
if (strlen(input_key) > MASTER_KEY_LEN*2) { if (strlen(input_key) > policy.rtp.cipher_key_len*2) {
fprintf(stderr, fprintf(stderr,
"error: too many digits in key/salt " "error: too many digits in key/salt "
"(should be %d hexadecimal digits, found %u)\n", "(should be %d hexadecimal digits, found %u)\n",
MASTER_KEY_LEN*2, (unsigned)strlen(input_key)); policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key));
exit(1); exit(1);
} }
@ -541,7 +608,8 @@ usage(char *string) {
"[-s | -r] dest_ip dest_port\n" "[-s | -r] dest_ip dest_port\n"
"or %s -l\n" "or %s -l\n"
"where -a use message authentication\n" "where -a use message authentication\n"
" -e use encryption\n" " -e <key size> use encryption (use 128 or 256 for key size)\n"
" -g Use AES-GCM mode (must be used with -e)\n"
" -k <key> sets the srtp master key\n" " -k <key> sets the srtp master key\n"
" -s act as rtp sender\n" " -s act as rtp sender\n"
" -r act as rtp receiver\n" " -r act as rtp receiver\n"

View File

@ -10,7 +10,7 @@ DURATION=3
key=2b2edc5034f61a72345ca5986d7bfd0189aa6dc2ecab32fd9af74df6dfc6 key=2b2edc5034f61a72345ca5986d7bfd0189aa6dc2ecab32fd9af74df6dfc6
ARGS="-k $key -ae" ARGS="-k $key -a -e 128"
# First, we run "killall" to get rid of all existing rtpw processes. # 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 # This step also enables this script to clean up after itself; if this
@ -66,6 +66,55 @@ kill $sender_pid
wait $receiver_pid wait $receiver_pid
wait $sender_pid wait $sender_pid
key=033490ba9e82994fc21013395739038992b2edc5034f61a72345ca598d7bfd0189aa6dc2ecab32fd9af74df6dfc6
ARGS="-k $key -a -e 256"
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)" echo $0 ": done (test passed)"
else else

View File

@ -0,0 +1,119 @@
#!/bin/sh
#
# usage: rtpw_test <rtpw_commands>
#
# tests the rtpw sender and receiver functions
RTPW=./rtpw
DEST_PORT=9999
DURATION=3
# 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
GCMARGS128="-k 012345678901234567890123456789012345678901234567890123456789 -g -e 128"
echo $0 ": starting GCM mode 128-bit rtpw receiver process... "
exec $RTPW $* $GCMARGS128 -r 127.0.0.1 $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 GCM 128-bit rtpw sender process..."
exec $RTPW $* $GCMARGS128 -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
GCMARGS256="-k 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 -g -e 256"
echo $0 ": starting GCM mode 256-bit rtpw receiver process... "
exec $RTPW $* $GCMARGS256 -r 127.0.0.1 $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 GCM 256-bit rtpw sender process..."
exec $RTPW $* $GCMARGS256 -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
echo $0 ": done (test passed)"
else
echo "error: can't find executable" $RTPW
exit 1
fi
# EOF

View File

@ -104,7 +104,7 @@ srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len);
double double
mips_estimate(int num_trials, int *ignore); mips_estimate(int num_trials, int *ignore);
extern uint8_t test_key[30]; extern uint8_t test_key[46];
void void
usage(char *prog_name) { usage(char *prog_name) {
@ -288,6 +288,8 @@ main (int argc, char *argv[]) {
exit(1); exit(1);
} }
//FIXME: need to get this working with the OpenSSL AES module
#ifndef OPENSSL
/* /*
* run validation test against the reference packets for * run validation test against the reference packets for
* AES-256 * AES-256
@ -300,6 +302,7 @@ main (int argc, char *argv[]) {
printf("failed\n"); printf("failed\n");
exit(1); exit(1);
} }
#endif
/* /*
* test the function srtp_remove_stream() * test the function srtp_remove_stream()
@ -1527,10 +1530,12 @@ srtp_test_remove_stream() {
* srtp policy definitions - these definitions are used above * srtp policy definitions - these definitions are used above
*/ */
unsigned char test_key[30] = { unsigned char test_key[46] = {
0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb, 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6, 0xc1, 0x73,
0xc3, 0x17, 0xf2, 0xda, 0xbe, 0x35, 0x77, 0x93,
0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
}; };
@ -1660,6 +1665,108 @@ const srtp_policy_t hmac_only_policy = {
NULL NULL
}; };
#ifdef OPENSSL
const srtp_policy_t aes128_gcm_8_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{ /* SRTP policy */
AES_128_GCM, /* cipher type */
30, /* cipher key length in octets */
NULL_AUTH, /* authentication func type */
0, /* auth key length in octets */
8, /* auth tag length in octets */
sec_serv_conf_and_auth /* security services flag */
},
{ /* SRTCP policy */
AES_128_GCM, /* cipher type */
30, /* cipher key length in octets */
NULL_AUTH, /* authentication func type */
0, /* auth key length in octets */
8, /* auth tag length in octets */
sec_serv_conf_and_auth /* security services flag */
},
test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL
};
const srtp_policy_t aes128_gcm_8_cauth_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{ /* SRTP policy */
AES_128_GCM, /* cipher type */
30, /* cipher key length in octets */
NULL_AUTH, /* authentication func type */
0, /* auth key length in octets */
8, /* auth tag length in octets */
sec_serv_conf_and_auth /* security services flag */
},
{ /* SRTCP policy */
AES_128_GCM, /* cipher type */
30, /* cipher key length in octets */
NULL_AUTH, /* authentication func type */
0, /* auth key length in octets */
8, /* auth tag length in octets */
sec_serv_auth /* security services flag */
},
test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL
};
const srtp_policy_t aes256_gcm_8_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{ /* SRTP policy */
AES_256_GCM, /* cipher type */
46, /* cipher key length in octets */
NULL_AUTH, /* authentication func type */
0, /* auth key length in octets */
8, /* auth tag length in octets */
sec_serv_conf_and_auth /* security services flag */
},
{ /* SRTCP policy */
AES_256_GCM, /* cipher type */
46, /* cipher key length in octets */
NULL_AUTH, /* authentication func type */
0, /* auth key length in octets */
8, /* auth tag length in octets */
sec_serv_conf_and_auth /* security services flag */
},
test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL
};
const srtp_policy_t aes256_gcm_8_cauth_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */
{ /* SRTP policy */
AES_256_GCM, /* cipher type */
46, /* cipher key length in octets */
NULL_AUTH, /* authentication func type */
0, /* auth key length in octets */
8, /* auth tag length in octets */
sec_serv_conf_and_auth /* security services flag */
},
{ /* SRTCP policy */
AES_256_GCM, /* cipher type */
46, /* cipher key length in octets */
NULL_AUTH, /* authentication func type */
0, /* auth key length in octets */
8, /* auth tag length in octets */
sec_serv_auth /* security services flag */
},
test_key,
NULL, /* indicates that EKT is not in use */
128, /* replay window size */
0, /* retransmission not allowed */
NULL
};
#endif
const srtp_policy_t null_policy = { const srtp_policy_t null_policy = {
{ ssrc_any_outbound, 0 }, /* SSRC */ { ssrc_any_outbound, 0 }, /* SSRC */
{ {
@ -1783,6 +1890,12 @@ policy_array[] = {
&aes_tmmh_policy, &aes_tmmh_policy,
#endif #endif
&default_policy, &default_policy,
#ifdef OPENSSL
&aes128_gcm_8_policy,
&aes128_gcm_8_cauth_policy,
&aes256_gcm_8_policy,
&aes256_gcm_8_cauth_policy,
#endif
&null_policy, &null_policy,
&aes_256_hmac_policy, &aes_256_hmac_policy,
&hmac_only_with_ekt_policy, &hmac_only_with_ekt_policy,