Permalink
Browse files

Merge pull request #34 from cisco/feature-openssl

Merge feature openssl branch
  • Loading branch information...
2 parents b1b8016 + bce4f85 commit f34baf31327f5cd5a844ad9d25edbcd80f833d41 @jfigus jfigus committed Mar 2, 2014
View
31 Makefile.in
@@ -9,10 +9,13 @@
# test builds test applications
# libcrypt.a static library implementing crypto engine
# libsrtp.a static library implementing srtp
+# libsrtp.so shared library implementing srtp
# clean removes objects, libs, and executables
# distribution cleans and builds a .tgz
# tags builds etags file from all .c and .h files
+USE_OPENSSL = @USE_OPENSSL@
+
.PHONY: all test build_table_apps
all: test
@@ -27,6 +30,9 @@ runtest: build_table_apps test
test/replay_driver$(EXE) -v >/dev/null
test/dtls_srtp_driver$(EXE) >/dev/null
cd test; $(abspath $(srcdir))/test/rtpw_test.sh >/dev/null
+ifeq (1, $(USE_OPENSSL))
+ cd test; $(abspath $(srcdir))/test/rtpw_test_gcm.sh >/dev/null
+endif
@echo "libsrtp test applications passed."
$(MAKE) -C crypto runtest
@@ -55,6 +61,9 @@ gdoi = @GDOI_OBJS@
# Random source.
RNG_OBJS = @RNG_OBJS@
+HMAC_OBJS = @HMAC_OBJS@
+RNG_EXTRA_OBJS = @RNG_EXTRA_OBJS@
+AES_ICM_OBJS = @AES_ICM_OBJS@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
@@ -77,11 +86,10 @@ libdir = @libdir@
# libcrypt.a (the crypto engine)
ciphers = crypto/cipher/cipher.o crypto/cipher/null_cipher.o \
- crypto/cipher/aes.o crypto/cipher/aes_icm.o \
- crypto/cipher/aes_cbc.o
+ $(AES_ICM_OBJS)
-hashes = crypto/hash/null_auth.o crypto/hash/sha1.o \
- crypto/hash/hmac.o crypto/hash/auth.o # crypto/hash/tmmhv2.o
+hashes = crypto/hash/null_auth.o crypto/hash/auth.o \
+ $(HMAC_OBJS)
replay = crypto/replay/rdb.o crypto/replay/rdbx.o \
crypto/replay/ut_sim.o
@@ -90,7 +98,7 @@ math = crypto/math/datatypes.o crypto/math/stat.o
ust = crypto/ust/ust.o
-rng = crypto/rng/$(RNG_OBJS) crypto/rng/prng.o crypto/rng/ctr_prng.o
+rng = crypto/rng/$(RNG_OBJS) $(RNG_EXTRA_OBJS)
err = crypto/kernel/err.o
@@ -107,6 +115,10 @@ libsrtp.a: $(srtpobj) $(cryptobj) $(gdoi)
ar cr libsrtp.a $^
$(RANLIB) libsrtp.a
+libsrtp.so: $(srtpobj) $(cryptobj) $(gdoi)
+ $(CC) -shared -Wl,-soname,libsrtp.so $(LDFLAGS) \
+ -o libsrtp.so $^
+
# libcryptomath.a contains general-purpose routines that are used to
# generate tables and verify cryptoalgorithm implementations - this
# library is not meant to be included in production code
@@ -119,8 +131,11 @@ libcryptomath.a: $(cryptomath)
# test applications
+ifneq (1, $(USE_OPENSSL))
+AES_CALC = crypto/test/aes_calc$(EXE)
+endif
-crypto_testapp = crypto/test/aes_calc$(EXE) crypto/test/cipher_driver$(EXE) \
+crypto_testapp = $(AES_CALC) crypto/test/cipher_driver$(EXE) \
crypto/test/datatypes_driver$(EXE) crypto/test/kernel_driver$(EXE) \
crypto/test/rand_gen$(EXE) crypto/test/sha1_driver$(EXE) \
crypto/test/stat_driver$(EXE)
@@ -200,15 +215,17 @@ install:
cp $(srcdir)/crypto/include/*.h $(DESTDIR)$(includedir)/srtp
if [ "$(srcdir)" != "." ]; then cp crypto/include/*.h $(DESTDIR)$(includedir)/srtp; fi
if [ -f libsrtp.a ]; then cp libsrtp.a $(DESTDIR)$(libdir)/; fi
+ if [ -f libsrtp.so ]; then cp libsrtp.so $(DESTDIR)$(libdir)/; fi
uninstall:
rm -f $(DESTDIR)$(includedir)/srtp/*.h
rm -f $(DESTDIR)$(libdir)/libsrtp.a
+ rm -f $(DESTDIR)$(libdir)/libsrtp.so
-rmdir $(DESTDIR)$(includedir)/srtp
clean:
rm -rf $(cryptobj) $(srtpobj) $(cryptomath) TAGS \
- libcryptomath.a libsrtp.a core *.core test/core
+ libcryptomath.a libsrtp.a libsrtp.so core *.core test/core
for a in * */* */*/*; do \
if [ -f "$$a~" ] ; then rm -f $$a~; fi; \
done;
View
14 README
@@ -26,6 +26,7 @@ The configure script accepts the following options:
--enable-syslog use syslog for error reporting
--disable-stdout use stdout 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)
By default, debugging is enabled and stdout is used for debugging.
@@ -77,7 +78,7 @@ Applications
Manual srtp keying uses the -k option; automated key management
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
Either the -s (sender) or -r (receiver) option must be chosen.
@@ -95,15 +96,20 @@ or rtpw -l
key is a hexadecimal value (without the
leading "0x")
- -e encrypt/decrypt (for data confidentiality)
+ -e <keysize> encrypt/decrypt (for data confidentiality)
(requires use of -k option as well)
+ (use 128, 192, or 256 for keysize)
+
+ -g use AES-GCM mode (must be used with -e)
-a message authentication
(requires use of -k option as well)
-l list debug modules
-d <debug> turn on debugging for module <debug>
+ -i specify input/output file
+ (instead of using dictionary file)
In order to get random 30-byte values for use as key/salt pairs , you
@@ -119,7 +125,7 @@ An example of an SRTP session using two rtpw programs follows:
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
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
setting SSRC to 2078917053
@@ -129,7 +135,7 @@ sending word: aa
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
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
19 octets received from SSRC 2078917053 word: A
View
3 config_in.h
@@ -141,6 +141,9 @@
/* Define to use GDOI. */
#undef SRTP_GDOI
+/* Define to use OpenSSL crypto. */
+#undef OPENSSL
+
/* Define to compile for kernel contexts. */
#undef SRTP_KERNEL
View
11,841 configure
4,816 additions, 7,025 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
63 configure.in
@@ -4,7 +4,7 @@ AC_INIT(srtp)
dnl Must come before AC_PROG_CC
if test -z "$CFLAGS"; then
dnl Default value for CFLAGS if not specified.
- CFLAGS="-Wall -O4 -fexpensive-optimizations -funroll-loops"
+ CFLAGS="-fPIC -Wall -O4 -fexpensive-optimizations -funroll-loops"
fi
dnl Checks for programs.
@@ -67,20 +67,6 @@ if test "$cross_compiling" != yes -a "$HOST_IS_WINDOWS" != yes; then
[AC_CHECK_FILE(/dev/random, DEV_URANDOM=/dev/random)])
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)
dnl Checks for header files.
@@ -151,6 +137,53 @@ if test "$enable_generic_aesicm" = "yes"; then
fi
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
+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_ARG_ENABLE(syslog,
[AS_HELP_STRING([--enable-syslog], [use syslog for error reporting])],
View
56 crypto/Makefile.in
@@ -9,14 +9,14 @@ top_builddir = @top_builddir@
VPATH = @srcdir@
CC = @CC@
-INCDIR = -Iinclude -I$(srcdir)/include
+INCDIR = -Iinclude -I$(srcdir)/include
DEFS = @DEFS@
CPPFLAGS= @CPPFLAGS@
CFLAGS = @CFLAGS@
LIBS = @LIBS@
-LDFLAGS = @LDFLAGS@ -L.
+LDFLAGS = @LDFLAGS@ -L. -L..
COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS)
-CRYPTOLIB = -lcryptomodule
+CRYPTOLIB = -lsrtp
RANLIB = @RANLIB@
@@ -25,7 +25,7 @@ RANLIB = @RANLIB@
# `make clean` will work on the cygwin platform
EXE = @EXE@
# Random source.
-RNG_OBJS = @RNG_OBJS@
+USE_OPENSSL = @USE_OPENSSL@
ifdef ARCH
DEFS += -D$(ARCH)=1
@@ -40,10 +40,13 @@ endif
dummy : all runtest
# test applications
+ifneq (1, $(USE_OPENSSL))
+AES_CALC = test/aes_calc$(EXE)
+endif
testapp = test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \
test/stat_driver$(EXE) test/sha1_driver$(EXE) \
- test/kernel_driver$(EXE) test/aes_calc$(EXE) test/rand_gen$(EXE) \
+ test/kernel_driver$(EXE) $(AES_CALC) test/rand_gen$(EXE) \
test/env$(EXE)
# data values used to test the aes_calc application for AES-128
@@ -58,60 +61,31 @@ p256=00112233445566778899aabbccddeeff
c256=8ea2b7ca516745bfeafc49904b496089
-runtest: libcryptomodule.a $(testapp)
+runtest: $(testapp)
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 $(k256) $(p256)` = $(c256)
+endif
test/cipher_driver$(EXE) -v >/dev/null
test/datatypes_driver$(EXE) -v >/dev/null
test/stat_driver$(EXE) >/dev/null
test/sha1_driver$(EXE) -v >/dev/null
test/kernel_driver$(EXE) -v >/dev/null
test/rand_gen$(EXE) -n 256 >/dev/null
- @echo "libcryptomodule 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
+ @echo "crypto test applications passed."
-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
%.o: %.c
$(COMPILE) -c $< -o $@
-%$(EXE): %.c libcryptomodule.a
+%$(EXE): %.c
$(COMPILE) $(LDFLAGS) $< -o $@ $(CRYPTOLIB) $(LIBS)
-ifndef AR
- AR=ar
-endif
-
-# and the crypto module library itself
-
-libcryptomodule.a: $(cryptobj)
- $(AR) cr libcryptomodule.a $(cryptobj)
- $(RANLIB) libcryptomodule.a
-
-all: libcryptomodule.a $(testapp)
+all: $(testapp)
# housekeeping functions
View
57 crypto/cipher/aes_cbc.c
@@ -104,36 +104,25 @@ aes_cbc_dealloc(cipher_t *c) {
}
err_status_t
-aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, int key_len,
- cipher_direction_t dir) {
- err_status_t status;
+aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, int key_len) {
debug_print(mod_aes_cbc,
"key: %s", octet_string_hex_string(key, key_len));
- /* expand key for the appropriate direction */
- switch (dir) {
- case (direction_encrypt):
- status = aes_expand_encryption_key(key, key_len, &c->expanded_key);
- if (status)
- return status;
- 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;
- }
-
+ /*
+ * Save the key until we have the IV later. We don't
+ * know the direction until the IV is set.
+ */
+ c->key_len = (key_len <= 32 ? key_len : 32);
+ memcpy(c->key, key, c->key_len);
return err_status_ok;
}
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;
/* v128_t *input = 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));
+ /* 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;
}
@@ -375,6 +382,8 @@ cipher_test_case_t aes_cbc_test_case_0 = {
aes_cbc_test_case_0_plaintext, /* plaintext */
32, /* octets in ciphertext */
aes_cbc_test_case_0_ciphertext, /* ciphertext */
+ 0,
+ NULL,
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 */
80, /* octets in ciphertext */
aes_cbc_test_case_1_ciphertext, /* ciphertext */
+ 0,
+ NULL,
&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 */
32, /* octets in ciphertext */
aes_cbc_test_case_2_ciphertext, /* ciphertext */
+ 0,
+ NULL,
&aes_cbc_test_case_1 /* pointer to next testcase */
};
@@ -520,16 +533,20 @@ cipher_test_case_t aes_cbc_test_case_3 = {
aes_cbc_test_case_3_plaintext, /* plaintext */
80, /* octets in ciphertext */
aes_cbc_test_case_3_ciphertext, /* ciphertext */
+ 0,
+ NULL,
&aes_cbc_test_case_2 /* pointer to next testcase */
};
cipher_type_t aes_cbc = {
(cipher_alloc_func_t) aes_cbc_alloc,
(cipher_dealloc_func_t) aes_cbc_dealloc,
(cipher_init_func_t) aes_cbc_context_init,
+ (cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_cbc_nist_encrypt,
(cipher_decrypt_func_t) aes_cbc_nist_decrypt,
(cipher_set_iv_func_t) aes_cbc_set_iv,
+ (cipher_get_tag_func_t) 0,
(char *) aes_cbc_description,
(int) 0, /* instance count */
(cipher_test_case_t *) &aes_cbc_test_case_3,
View
529 crypto/cipher/aes_gcm_ossl.c
@@ -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
10 crypto/cipher/aes_icm.c
@@ -9,7 +9,7 @@
/*
*
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* 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
-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;
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 */
32, /* octets in ciphertext */
aes_icm_test_case_0_ciphertext, /* ciphertext */
+ 0,
+ NULL,
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 */
32, /* octets in ciphertext */
aes_icm_test_case_1_ciphertext, /* ciphertext */
+ 0,
+ NULL,
&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_dealloc_func_t) aes_icm_dealloc,
(cipher_init_func_t) aes_icm_context_init,
+ (cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_icm_encrypt,
(cipher_decrypt_func_t) aes_icm_encrypt,
(cipher_set_iv_func_t) aes_icm_set_iv,
+ (cipher_get_tag_func_t) 0,
(char *) aes_icm_description,
(int) 0, /* instance count */
(cipher_test_case_t *) &aes_icm_test_case_1,
View
537 crypto/cipher/aes_icm_ossl.c
@@ -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
111 crypto/cipher/cipher.c
@@ -10,7 +10,7 @@
/*
*
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
*/
#include "cipher.h"
+#include "crypto_types.h"
#include "rand_source.h" /* used in invertibiltiy tests */
#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;
uint8_t buffer[SELF_TEST_BUF_OCTETS];
uint8_t buffer2[SELF_TEST_BUF_OCTETS];
+ int tag_len;
unsigned int len;
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
*/
while (test_case != NULL) {
-
/* allocate cipher */
status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
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);
/* initialize cipher */
- status = cipher_init(c, test_case->key, direction_encrypt);
+ status = cipher_init(c, test_case->key);
if (status) {
cipher_dealloc(c);
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));
/* set the initialization vector */
- status = cipher_set_iv(c, test_case->idx);
+ status = cipher_set_iv(c, test_case->idx, direction_encrypt);
if (status) {
cipher_dealloc(c);
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 */
len = test_case->plaintext_length_octets;
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;
}
+ 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",
octet_string_hex_string(buffer,
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);
/* re-initialize cipher for decryption */
- status = cipher_init(c, test_case->key, direction_decrypt);
+ status = cipher_init(c, test_case->key);
if (status) {
cipher_dealloc(c);
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));
/* set the initialization vector */
- status = cipher_set_iv(c, test_case->idx);
+ status = cipher_set_iv(c, test_case->idx, direction_decrypt);
if (status) {
cipher_dealloc(c);
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 */
len = test_case->ciphertext_length_octets;
status = cipher_decrypt(c, buffer, &len);
@@ -297,43 +343,83 @@ cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
if (status) return status;
/* initialize cipher */
- status = cipher_init(c, key, direction_encrypt);
+ status = cipher_init(c, key);
if (status) {
cipher_dealloc(c);
return status;
}
/* set initialization vector */
- status = cipher_set_iv(c, test_case->idx);
+ status = cipher_set_iv(c, test_case->idx, direction_encrypt);
if (status) {
cipher_dealloc(c);
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 */
plaintext_len = length;
status = cipher_encrypt(c, buffer, &length);
if (status) {
cipher_dealloc(c);
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",
octet_string_hex_string(buffer, length));
/*
* re-initialize cipher for decryption, re-set the iv, then
* decrypt the ciphertext
*/
- status = cipher_init(c, key, direction_decrypt);
+ status = cipher_init(c, key);
if (status) {
cipher_dealloc(c);
return status;
}
- status = cipher_set_iv(c, test_case->idx);
+ status = cipher_set_iv(c, test_case->idx, direction_decrypt);
if (status) {
cipher_dealloc(c);
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);
if (status) {
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));
/* compare the resulting plaintext with the original one */
- if (length != plaintext_len)
+ if (length != plaintext_len) {
return err_status_algo_fail;
+ }
status = err_status_ok;
for (i=0; i < plaintext_len; 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);
timer = clock();
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);
}
timer = clock() - timer;
View
6 crypto/cipher/null_cipher.c
@@ -10,7 +10,7 @@
/*
*
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -129,6 +129,8 @@ null_cipher_test_0 = {
NULL, /* plaintext */
0, /* octets in plaintext */
NULL, /* ciphertext */
+ 0,
+ NULL,
NULL /* pointer to next testcase */
};
@@ -141,9 +143,11 @@ cipher_type_t null_cipher = {
(cipher_alloc_func_t) null_cipher_alloc,
(cipher_dealloc_func_t) null_cipher_dealloc,
(cipher_init_func_t) null_cipher_init,
+ (cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) null_cipher_encrypt,
(cipher_decrypt_func_t) null_cipher_encrypt,
(cipher_set_iv_func_t) null_cipher_set_iv,
+ (cipher_get_tag_func_t) 0,
(char *) null_cipher_description,
(int) 0,
(cipher_test_case_t *) &null_cipher_test_0,
View
297 crypto/hash/hmac_ossl.c
@@ -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
6 crypto/include/aes_cbc.h
@@ -17,6 +17,8 @@
typedef struct {
v128_t state; /* cipher chaining state */
v128_t previous; /* previous ciphertext block */
+ uint8_t key[32];
+ int key_len;
aes_expanded_key_t expanded_key; /* the cipher key */
} aes_cbc_ctx_t;
@@ -31,10 +33,10 @@ aes_cbc_encrypt(aes_cbc_ctx_t *c,
err_status_t
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
-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
aes_cbc_nist_encrypt(aes_cbc_ctx_t *c,
View
62 crypto/include/aes_gcm_ossl.h
@@ -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
2 crypto/include/aes_icm.h
@@ -29,7 +29,7 @@ aes_icm_context_init(aes_icm_ctx_t *c,
int key_len);
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
aes_icm_encrypt(aes_icm_ctx_t *c,
View
73 crypto/include/aes_icm_ossl.h
@@ -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 product