update libsrtp to use openssl
parent
365f81b412
commit
80c7eb85e6
|
@ -5,28 +5,37 @@ AM_CFLAGS = $(new_AM_CFLAGS) -I./src -Icrypto/include -I$(srcdir)/include -I$
|
|||
AM_CPPFLAGS = $(AM_CFLAGS)
|
||||
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
|
||||
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/cipher/aes_cbc.c \
|
||||
crypto/hash/null_auth.c crypto/hash/sha1.c \
|
||||
crypto/hash/hmac.c crypto/hash/auth.c \
|
||||
crypto/hash/null_auth.c crypto/hash/auth.c \
|
||||
crypto/math/datatypes.c crypto/math/stat.c \
|
||||
crypto/kernel/crypto_kernel.c crypto/kernel/alloc.c \
|
||||
crypto/kernel/key.c \
|
||||
crypto/rng/prng.c crypto/rng/ctr_prng.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
|
||||
|
||||
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
|
||||
libsrtp_la_SOURCES += crypto/rng/rand_linux_kernel.c
|
||||
EXTRA_DIST += crypto/rng/rand_source.c
|
||||
else
|
||||
libsrtp_la_SOURCES += crypto/rng/rand_source.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if GDOI
|
||||
libsrtp_la_SOURCES += gdoi/srtp+gdoi.c
|
||||
|
|
|
@ -26,9 +26,10 @@ 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.
|
||||
By default, debbuging is enabled and stdout is used for debugging.
|
||||
You can use the above configure options to have the debugging output
|
||||
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
|
||||
|
@ -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.
|
||||
|
@ -86,25 +87,15 @@ or rtpw -l
|
|||
which the dictionary will be sent, respectively.
|
||||
|
||||
options:
|
||||
|
||||
-s (s)rtp sender - causes app to send words
|
||||
|
||||
-r (s)rtp receive - causes app to receive words
|
||||
|
||||
-k <key> use srtp master key <key>, where the
|
||||
key is a hexadecimal value (without the
|
||||
leading "0x")
|
||||
|
||||
-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>
|
||||
|
||||
-a use message authentication
|
||||
-e <key size> use encryption (use 128, 192, or 256 for key size)
|
||||
-g Use AES-GCM mode (must be used with -e)
|
||||
-k <key> sets the srtp master key
|
||||
-s act as rtp sender
|
||||
-r act as rtp receiver
|
||||
-l list debug modules
|
||||
-d <debug> turn on debugging for module <debug>
|
||||
-i specify input/output file
|
||||
|
||||
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
|
||||
|
@ -119,7 +110,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 +120,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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#! /bin/sh
|
||||
srcpath=$(dirname $0 2>/dev/null ) || srcpath="."
|
||||
$srcpath/configure "$@" --disable-shared --with-pic
|
||||
$srcpath/configure "$@" --disable-shared --with-pic --enable-openssl
|
||||
|
||||
|
|
|
@ -143,22 +143,6 @@ if test "$cross_compiling" != 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)
|
||||
AM_CONDITIONAL(RNG_OBJS_LINUX, test x$enable_kernel_linux = xyes)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(stdlib.h)
|
||||
|
@ -273,6 +257,56 @@ 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
|
||||
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_ARG_ENABLE(syslog,
|
||||
[AS_HELP_STRING([--enable-syslog], [use syslog for error reporting])],
|
||||
|
|
|
@ -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
|
||||
|
@ -41,9 +41,13 @@ 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 +62,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."
|
||||
@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
|
||||
|
||||
%.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
|
||||
|
||||
|
|
|
@ -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,6 +533,8 @@ 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 */
|
||||
};
|
||||
|
||||
|
@ -527,9 +542,11 @@ 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,
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||