update libsrtp to use openssl

v1.4
Michael Jerris 2014-02-24 09:20:03 -05:00
parent 365f81b412
commit 80c7eb85e6
36 changed files with 3541 additions and 197 deletions

View File

@ -5,28 +5,37 @@ AM_CFLAGS = $(new_AM_CFLAGS) -I./src -Icrypto/include -I$(srcdir)/include -I$
AM_CPPFLAGS = $(AM_CFLAGS)
AM_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

View File

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

View File

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

View File

@ -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])],

View File

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

View File

@ -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,

View File

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

View File

@ -9,7 +9,7 @@
/*
*
* Copyright (c) 2001-2006, Cisco Systems, Inc.
* Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* 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 File

@ -0,0 +1,537 @@
/*
* aes_icm_ossl.c
*
* AES Integer Counter Mode
*
* John A. Foley
* Cisco Systems, Inc.
*
* 2/24/2012: This module was modified to use CiscoSSL for AES counter
* mode. Eddy Lem contributed the code to allow this.
*
* 12/20/2012: Added support for AES-192 and AES-256.
*/
/*
*
* Copyright (c) 2013, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <openssl/evp.h>
#include "aes_icm_ossl.h"
#include "crypto_types.h"
#include "alloc.h"
#include "crypto_types.h"
debug_module_t mod_aes_icm = {
0, /* debugging is off by default */
"aes icm ossl" /* printable module name */
};
extern cipher_test_case_t aes_icm_test_case_0;
extern cipher_type_t aes_icm;
extern cipher_type_t aes_icm_192;
extern cipher_type_t aes_icm_256;
/*
* integer counter mode works as follows:
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | pakcet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30, 38, or 46 for
* AES-128, AES-192, and AES-256 respectively. Note, this key_len
* value is inflated, as it also accounts for the 112 bit salt
* value.
*/
err_status_t aes_icm_openssl_alloc (cipher_t **c, int key_len, int x)
{
aes_icm_ctx_t *icm;
int tmp;
uint8_t *allptr;
debug_print(mod_aes_icm, "allocating cipher with key length %d", key_len);
/*
* Verify the key_len is valid for one of: AES-128/192/256
*/
if (key_len != AES_128_KEYSIZE_WSALT && key_len != AES_192_KEYSIZE_WSALT &&
key_len != AES_256_KEYSIZE_WSALT) {
return err_status_bad_param;
}
/* allocate memory a cipher of type aes_icm */
tmp = sizeof(cipher_t) + sizeof(aes_icm_ctx_t);
allptr = (uint8_t*)crypto_alloc(tmp);
if (allptr == NULL) {
return err_status_alloc_fail;
}
/* set pointers */
*c = (cipher_t*)allptr;
(*c)->state = allptr + sizeof(cipher_t);
icm = (aes_icm_ctx_t*)(*c)->state;
/* increment ref_count */
switch (key_len) {
case AES_128_KEYSIZE_WSALT:
(*c)->algorithm = AES_128_ICM;
(*c)->type = &aes_icm;
aes_icm.ref_count++;
((aes_icm_ctx_t*)(*c)->state)->key_size = AES_128_KEYSIZE;
break;
case AES_192_KEYSIZE_WSALT:
(*c)->algorithm = AES_192_ICM;
(*c)->type = &aes_icm_192;
aes_icm_192.ref_count++;
((aes_icm_ctx_t*)(*c)->state)->key_size = AES_192_KEYSIZE;
break;
case AES_256_KEYSIZE_WSALT:
(*c)->algorithm = AES_256_ICM;
(*c)->type = &aes_icm_256;
aes_icm_256.ref_count++;
((aes_icm_ctx_t*)(*c)->state)->key_size = AES_256_KEYSIZE;
break;
}
/* set key size */
(*c)->key_len = key_len;
EVP_CIPHER_CTX_init(&icm->ctx);
return err_status_ok;
}
/*
* This function deallocates an instance of this engine
*/
err_status_t aes_icm_openssl_dealloc (cipher_t *c)
{
aes_icm_ctx_t *ctx;
if (c == NULL) {
return err_status_bad_param;
}
/*
* Free the EVP context
*/
ctx = (aes_icm_ctx_t*)c->state;
if (ctx != NULL) {
EVP_CIPHER_CTX_cleanup(&ctx->ctx);
/* decrement ref_count for the appropriate engine */
switch (ctx->key_size) {
case AES_256_KEYSIZE:
aes_icm_256.ref_count--;
break;
case AES_192_KEYSIZE:
aes_icm_192.ref_count--;
break;
case AES_128_KEYSIZE:
aes_icm.ref_count--;
break;
default:
return err_status_dealloc_fail;
break;
}
}
/* zeroize entire state*/
octet_string_set_to_zero((uint8_t*)c,
sizeof(cipher_t) + sizeof(aes_icm_ctx_t));
/* free memory */
crypto_free(c);
return err_status_ok;
}
/*
* aes_icm_openssl_context_init(...) initializes the aes_icm_context
* using the value in key[].
*
* the key is the secret key
*
* the salt is unpredictable (but not necessarily secret) data which
* randomizes the starting point in the keystream
*/
err_status_t aes_icm_openssl_context_init (aes_icm_ctx_t *c, const uint8_t *key)
{
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
memcpy(&c->counter, key + c->key_size, SALT_SIZE);
memcpy(&c->offset, key + c->key_size, SALT_SIZE);
/* force last two octets of the offset to zero (for srtp compatibility) */
c->offset.v8[SALT_SIZE] = c->offset.v8[SALT_SIZE + 1] = 0;
c->counter.v8[SALT_SIZE] = c->counter.v8[SALT_SIZE + 1] = 0;
/* copy key to be used later when CiscoSSL crypto context is created */
v128_copy_octet_string((v128_t*)&c->key, key);
/* if the key is greater than 16 bytes, copy the second
* half. Note, we treat AES-192 and AES-256 the same here
* for simplicity. The storage location receiving the
* key is statically allocated to handle a full 32 byte key
* regardless of the cipher in use.
*/
if (c->key_size == AES_256_KEYSIZE || c->key_size == AES_192_KEYSIZE) {
debug_print(mod_aes_icm, "Copying last 16 bytes of key: %s",
v128_hex_string((v128_t*)(key + AES_128_KEYSIZE)));
v128_copy_octet_string(((v128_t*)(&c->key.v8)) + 1, key + AES_128_KEYSIZE);
}
debug_print(mod_aes_icm, "key: %s", v128_hex_string((v128_t*)&c->key));
debug_print(mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
EVP_CIPHER_CTX_cleanup(&c->ctx);
return err_status_ok;
}
/*
* aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
err_status_t aes_icm_openssl_set_iv (aes_icm_ctx_t *c, void *iv, int dir)
{
const EVP_CIPHER *evp;
v128_t *nonce = (v128_t*)iv;
debug_print(mod_aes_icm, "setting iv: %s", v128_hex_string(nonce));
v128_xor(&c->counter, &c->offset, nonce);
debug_print(mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter));
switch (c->key_size) {
case AES_256_KEYSIZE:
evp = EVP_aes_256_ctr();
break;
case AES_192_KEYSIZE:
evp = EVP_aes_192_ctr();
break;
case AES_128_KEYSIZE:
evp = EVP_aes_128_ctr();
break;
default:
return err_status_bad_param;
break;
}
if (!EVP_EncryptInit_ex(&c->ctx, evp,
NULL, c->key.v8, c->counter.v8)) {
return err_status_fail;
} else {
return err_status_ok;
}
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
err_status_t aes_icm_openssl_encrypt (aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len)
{
int len = 0;
debug_print(mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter));
if (!EVP_EncryptUpdate(&c->ctx, buf, &len, buf, *enc_len)) {
return err_status_cipher_fail;
}
*enc_len = len;
if (!EVP_EncryptFinal_ex(&c->ctx, buf, (int*)&len)) {
return err_status_cipher_fail;
}
*enc_len += len;
return err_status_ok;
}
/*
* Abstraction layer for encrypt.
*/
err_status_t aes_icm_output (aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output)
{
unsigned int len = num_octets_to_output;
/* zeroize the buffer */
octet_string_set_to_zero(buffer, num_octets_to_output);
/* exor keystream into buffer */
return aes_icm_openssl_encrypt(c, buffer, &len);
}
/*
* Name of this crypto engine
*/
char aes_icm_openssl_description[] = "AES-128 counter mode using openssl";
char aes_icm_192_openssl_description[] = "AES-192 counter mode using openssl";
char aes_icm_256_openssl_description[] = "AES-256 counter mode using openssl";
/*
* KAT values for AES self-test. These
* values came from the legacy libsrtp code.
*/
uint8_t aes_icm_test_case_0_key[AES_128_KEYSIZE_WSALT] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
};
uint8_t aes_icm_test_case_0_nonce[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t aes_icm_test_case_0_plaintext[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
uint8_t aes_icm_test_case_0_ciphertext[32] = {
0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
};
cipher_test_case_t aes_icm_test_case_0 = {
AES_128_KEYSIZE_WSALT, /* octets in key */
aes_icm_test_case_0_key, /* key */
aes_icm_test_case_0_nonce, /* packet index */
32, /* octets in plaintext */
aes_icm_test_case_0_plaintext, /* plaintext */
32, /* octets in ciphertext */
aes_icm_test_case_0_ciphertext, /* ciphertext */
0,
NULL,
NULL /* pointer to next testcase */
};
/*
* KAT values for AES-192-CTR self-test. These
* values came from section 7 of RFC 6188.
*/
uint8_t aes_icm_192_test_case_1_key[AES_192_KEYSIZE_WSALT] = {
0xea, 0xb2, 0x34, 0x76, 0x4e, 0x51, 0x7b, 0x2d,
0x3d, 0x16, 0x0d, 0x58, 0x7d, 0x8c, 0x86, 0x21,
0x97, 0x40, 0xf6, 0x5f, 0x99, 0xb6, 0xbc, 0xf7,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
};
uint8_t aes_icm_192_test_case_1_nonce[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t aes_icm_192_test_case_1_plaintext[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
uint8_t aes_icm_192_test_case_1_ciphertext[32] = {
0x35, 0x09, 0x6c, 0xba, 0x46, 0x10, 0x02, 0x8d,
0xc1, 0xb5, 0x75, 0x03, 0x80, 0x4c, 0xe3, 0x7c,
0x5d, 0xe9, 0x86, 0x29, 0x1d, 0xcc, 0xe1, 0x61,
0xd5, 0x16, 0x5e, 0xc4, 0x56, 0x8f, 0x5c, 0x9a
};
cipher_test_case_t aes_icm_192_test_case_1 = {
AES_192_KEYSIZE_WSALT, /* octets in key */
aes_icm_192_test_case_1_key, /* key */
aes_icm_192_test_case_1_nonce, /* packet index */
32, /* octets in plaintext */
aes_icm_192_test_case_1_plaintext, /* plaintext */
32, /* octets in ciphertext */
aes_icm_192_test_case_1_ciphertext, /* ciphertext */
0,
NULL,
NULL /* pointer to next testcase */
};
/*
* KAT values for AES-256-CTR self-test. These