inital AES-CBC with af_alg

progress on AES-GCM with AF_ALG and add SHA256

add aes-gcm test cases and finish logic of aes-gcm with AF_ALG

formating of tabs and white space

add files to dist

adding ecb and ctr mode with af_alg

make length of buffers for ctr be AES_BLOCK_SIZE

formating and add support for sha256 copy/gethash

sanity checks on arguments

cast return values and valgrind tests

make it easier to use sha256 with af_alg

remove hard tabs

add endif for after rebase
pull/1728/head
JacobBarthelmeh 2018-07-18 17:26:25 -06:00 committed by Jacob Barthelmeh
parent 2b3f94944d
commit cb756397b3
21 changed files with 1496 additions and 13 deletions

View File

@ -977,6 +977,22 @@ fi
AM_CONDITIONAL([BUILD_AESNI], [test "x$ENABLED_AESNI" = "xyes"])
# Linux af_alg
AC_ARG_ENABLE([afalg],
[AS_HELP_STRING([--enable-afalg],[Enable Linux af_alg use for crypto (default: disabled)])],
[ ENABLED_AFALG=$enableval ],
[ ENABLED_AFALG=no ]
)
if test "$ENABLED_AFALG" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG"
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_HASH"
fi
AM_CONDITIONAL([BUILD_AFALG], [test "x$ENABLED_AFALG" = "xyes"])
# Camellia
AC_ARG_ENABLE([camellia],
[AS_HELP_STRING([--enable-camellia],[Enable wolfSSL Camellia support (default: disabled)])],
@ -2114,7 +2130,7 @@ AM_CONDITIONAL([BUILD_SELFTEST], [test "x$ENABLED_SELFTEST" = "xyes"])
SHA224_DEFAULT=no
if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64"
then
if test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2"
if test "x$ENABLED_AFALG" = "xno" && ( test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" )
then
SHA224_DEFAULT=yes
fi
@ -3276,6 +3292,12 @@ then
then
AC_MSG_ERROR([please disable ecc if disabling asn.])
fi
if test "$ENABLED_AFALG" = "yes"
then
# for TLS connections the intermediate hash needs to store buffer
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_HASH_KEEP"
fi
fi
@ -4211,6 +4233,10 @@ AS_IF([test "x$ENABLED_SCTP" = "xyes"],
AS_IF([test "x$ENABLED_MCAST" = "xyes"],
[AM_CFLAGS="-DWOLFSSL_MULTICAST $AM_CFLAGS"])
# WOLFSSL_AFALG does not support SHA224 yet
AS_IF([(test "x$ENABLED_AFALG" = "xyes") && (test "x$ENABLED_SHA224" = "xyes")],
[AC_MSG_ERROR([--enable-sha224 with --enable-afalg not yet supported])])
# SCTP and Multicast require DTLS
AS_IF([(test "x$ENABLED_DTLS" = "xno") && \
(test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_MCAST" = "xyes")],
@ -4564,6 +4590,7 @@ echo " * Write duplicate: $ENABLED_WRITEDUP"
echo " * Intel Quick Assist: $ENABLED_INTEL_QA"
echo " * Xilinx Hardware Acc.: $ENABLED_XILINX"
echo " * Inline Code: $ENABLED_INLINE"
echo " * Linux AF_ALG: $ENABLED_AFALG"
echo ""
echo "---"

View File

@ -148,6 +148,10 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/sha256.c
endif
endif
if BUILD_AFALG
src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/afalg_hash.c
endif
if BUILD_WOLFEVENT
src_libwolfssl_la_SOURCES += wolfcrypt/src/wolfevent.c
endif
@ -193,6 +197,9 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/aes.c
if BUILD_ARMASM
src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-aes.c
endif
if BUILD_AFALG
src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/afalg_aes.c
endif
endif
endif
@ -375,6 +382,10 @@ if BUILD_IDEA
src_libwolfssl_la_SOURCES += wolfcrypt/src/idea.c
endif
if BUILD_AFALG
src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/wc_afalg.c
endif
if !BUILD_CRYPTONLY
# ssl files
src_libwolfssl_la_SOURCES += \

View File

@ -8697,7 +8697,9 @@ static int test_wc_AesGcmSetKey (void)
static int test_wc_AesGcmEncryptDecrypt (void)
{
int ret = 0;
#if !defined(NO_AES) && defined(HAVE_AESGCM) && defined(WOLFSSL_AES_256)
/* WOLFSSL_AFALG requires 12 byte IV */
#if !defined(NO_AES) && defined(HAVE_AESGCM) && defined(WOLFSSL_AES_256) && \
!defined(WOLFSSL_AFALG)
Aes aes;
byte key32[] =

View File

@ -1733,6 +1733,7 @@ static void bench_aesgcm_internal(int doAsync, const byte* key, word32 keySz,
{
int ret = 0, i, count = 0, times, pending = 0;
Aes enc[BENCH_MAX_PENDING];
Aes dec[BENCH_MAX_PENDING];
double start;
DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT);
@ -1789,7 +1790,21 @@ exit_aes_gcm:
bench_stats_sym_finish(encLabel, doAsync, count, bench_size, start, ret);
#ifdef HAVE_AES_DECRYPT
/* GCM uses same routine in backend for both encrypt and decrypt */
/* init keys */
for (i = 0; i < BENCH_MAX_PENDING; i++) {
if ((ret = wc_AesInit(&dec[i], HEAP_HINT,
doAsync ? devId : INVALID_DEVID)) != 0) {
printf("AesInit failed, ret = %d\n", ret);
goto exit;
}
ret = wc_AesGcmSetKey(&dec[i], key, keySz);
if (ret != 0) {
printf("AesGcmSetKey failed, ret = %d\n", ret);
goto exit;
}
}
bench_stats_start(&count, &start);
do {
for (times = 0; times < numBlocks || pending > 0; ) {
@ -1797,12 +1812,12 @@ exit_aes_gcm:
/* while free pending slots in queue, submit ops */
for (i = 0; i < BENCH_MAX_PENDING; i++) {
if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, &times, numBlocks, &pending)) {
ret = wc_AesGcmDecrypt(&enc[i], bench_plain,
if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, &times, numBlocks, &pending)) {
ret = wc_AesGcmDecrypt(&dec[i], bench_plain,
bench_cipher, BENCH_SIZE,
iv, ivSz, bench_tag, AES_AUTH_TAG_SZ,
bench_additional, aesAuthAddSz);
if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, &times, &pending)) {
if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, &times, &pending)) {
goto exit_aes_gcm_dec;
}
}
@ -1812,6 +1827,10 @@ exit_aes_gcm:
} while (bench_stats_sym_check(start));
exit_aes_gcm_dec:
bench_stats_sym_finish(decLabel, doAsync, count, bench_size, start, ret);
for (i = 0; i < BENCH_MAX_PENDING; i++) {
wc_AesFree(&dec[i]);
}
#endif /* HAVE_AES_DECRYPT */
(void)decLabel;

View File

@ -726,6 +726,9 @@
wc_AesEncryptDirect(aes, outBlock, inBlock);
return 0;
}
#elif defined(WOLFSSL_AFALG)
#else
/* using wolfCrypt software AES implementation */
@ -1936,6 +1939,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
/* implemented in wolfcrypt/src/port/caam/caam_aes.c */
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#else
static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen,
const byte* iv, int dir)
@ -2253,6 +2259,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
/* implemented in wolfcrypt/src/port/caam/caam_aes.c */
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#else
/* Allow direct access to one block encrypt */
void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
@ -2775,6 +2784,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
/* implemented in wolfcrypt/src/port/caam/caam_aes.c */
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#else
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
@ -3096,6 +3108,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
/* implemented in wolfcrypt/src/port/caam/caam_aes.c */
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#else
/* Use software based AES counter */
@ -3205,6 +3220,10 @@ static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
#ifdef WOLFSSL_ARMASM
/* implementation is located in wolfcrypt/src/port/arm/armv8-aes.c */
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/afalg/afalg_aes.c */
#else /* software + AESNI implementation */
#if !defined(FREESCALE_LTC_AES_GCM)
@ -8932,6 +8951,7 @@ int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz,
if (ret == 0)
ret = wc_AesGcmEncrypt_ex(&aes, NULL, NULL, 0, iv, ivSz,
authTag, authTagSz, authIn, authInSz);
wc_AesFree(&aes);
ForceZero(&aes, sizeof(aes));
return ret;
@ -8956,6 +8976,7 @@ int wc_GmacVerify(const byte* key, word32 keySz,
if (ret == 0)
ret = wc_AesGcmDecrypt(&aes, NULL, NULL, 0, iv, ivSz,
authTag, authTagSz, authIn, authInSz);
wc_AesFree(&aes);
ForceZero(&aes, sizeof(aes));
return ret;
@ -9390,6 +9411,11 @@ int wc_AesInit(Aes* aes, void* heap, int devId)
(void)devId;
#endif /* WOLFSSL_ASYNC_CRYPT */
#ifdef WOLFSSL_AFALG
aes->alFd = -1;
aes->rdFd = -1;
#endif
return ret;
}
@ -9402,6 +9428,14 @@ void wc_AesFree(Aes* aes)
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
wolfAsync_DevCtxFree(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES);
#endif /* WOLFSSL_ASYNC_CRYPT */
#ifdef WOLFSSL_AFALG
if (aes->rdFd > 0) { /* negative is error case */
close(aes->rdFd);
}
if (aes->alFd > 0) {
close(aes->alFd);
}
#endif /* WOLFSSL_AFALG */
}
@ -9442,6 +9476,10 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize)
#ifdef HAVE_AES_ECB
#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
/* implemented in wolfcrypt/src/port/caam/caam_aes.c */
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#else
/* software implementation */

View File

@ -482,6 +482,9 @@ const char* wc_GetErrorString(int error)
case DH_CHECK_PRIV_E:
return "DH Check Private Key failure";
case WC_AFALG_SOCK_E:
return "AF_ALG socket error";
default:
return "unknown error number";

View File

@ -840,6 +840,7 @@ int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type)
}
wc_Sha256Free(sha256);
}
wc_Sha256Free(sha256);
#ifdef WOLFSSL_SMALL_STACK

View File

@ -1070,6 +1070,43 @@ void wc_HmacFree(Hmac* hmac)
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC);
#endif /* WOLFSSL_ASYNC_CRYPT */
switch (hmac->macType) {
#ifndef NO_MD5
case WC_MD5:
wc_Md5Free(&hmac->hash.md5);
break;
#endif /* !NO_MD5 */
#ifndef NO_SHA
case WC_SHA:
wc_ShaFree(&hmac->hash.sha);
break;
#endif /* !NO_SHA */
#ifdef WOLFSSL_SHA224
case WC_SHA224:
wc_Sha224Free(&hmac->hash.sha224);
break;
#endif /* WOLFSSL_SHA224 */
#ifndef NO_SHA256
case WC_SHA256:
wc_Sha256Free(&hmac->hash.sha256);
break;
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA512
#ifdef WOLFSSL_SHA384
case WC_SHA384:
wc_Sha384Free(&hmac->hash.sha384);
break;
#endif /* WOLFSSL_SHA384 */
case WC_SHA512:
wc_Sha512Free(&hmac->hash.sha512);
break;
#endif /* WOLFSSL_SHA512 */
}
}
int wolfSSL_GetHmacMaxSize(void)

View File

@ -62,7 +62,9 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \
wolfcrypt/src/port/caam/caam_sha.c \
wolfcrypt/src/port/caam/caam_doc.pdf \
wolfcrypt/src/port/st/stm32.c \
wolfcrypt/src/port/st/stsafe.c
wolfcrypt/src/port/st/stsafe.c \
wolfcrypt/src/port/af_alg/afalg_aes.c \
wolfcrypt/src/port/af_alg/afalg_hash.c
if BUILD_CRYPTODEV
src_libwolfssl_la_SOURCES += wolfcrypt/src/cryptodev.c

View File

@ -0,0 +1,691 @@
/* afalg_aes.c
*
* Copyright (C) 2006-2018 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#if !defined(NO_AES) && defined(WOLFSSL_AFALG)
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
#include <sys/uio.h> /* for readv */
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
static const char WC_TYPE_SYMKEY[] = "skcipher";
static const char WC_NAME_AESCBC[] = "cbc(aes)";
static int wc_AesSetup(Aes* aes, const char* type, const char* name, int ivSz, int aadSz)
{
aes->rdFd = wc_Afalg_CreateRead(aes->alFd, type, name);
if (aes->rdFd < 0) {
WOLFSSL_MSG("Unable to accept and get AF_ALG read socket");
aes->rdFd = WC_SOCK_NOTSET;
return aes->rdFd;
}
if (setsockopt(aes->alFd, SOL_ALG, ALG_SET_KEY, (byte*)aes->key, aes->keylen) != 0) {
WOLFSSL_MSG("Unable to set AF_ALG key");
aes->rdFd = WC_SOCK_NOTSET;
return WC_AFALG_SOCK_E;
}
ForceZero((byte*)aes->key, sizeof(aes->key));
/* set up CMSG headers */
XMEMSET((byte*)&(aes->msg), 0, sizeof(struct msghdr));
aes->msg.msg_control = (byte*)(aes->key); /* use existing key buffer for
* control buffer */
aes->msg.msg_controllen = CMSG_SPACE(4);
if (aadSz > 0) {
aes->msg.msg_controllen += CMSG_SPACE(4);
}
if (ivSz > 0) {
aes->msg.msg_controllen += CMSG_SPACE((sizeof(struct af_alg_iv) + ivSz));
}
if (wc_Afalg_SetOp(CMSG_FIRSTHDR(&(aes->msg)), aes->dir) < 0) {
WOLFSSL_MSG("Error with setting AF_ALG operation");
aes->rdFd = WC_SOCK_NOTSET;
return -1;
}
return 0;
}
int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
const byte* iv, int dir)
{
#if defined(AES_MAX_KEY_SIZE)
const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
#endif
if (aes == NULL ||
!((keylen == 16) || (keylen == 24) || (keylen == 32))) {
return BAD_FUNC_ARG;
}
#if defined(AES_MAX_KEY_SIZE)
/* Check key length */
if (keylen > max_key_len) {
return BAD_FUNC_ARG;
}
#endif
aes->keylen = keylen;
aes->rounds = keylen/4 + 6;
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif
aes->rdFd = WC_SOCK_NOTSET;
aes->alFd = wc_Afalg_Socket();
if (aes->alFd < 0) {
WOLFSSL_MSG("Unable to open an AF_ALG socket");
return WC_AFALG_SOCK_E;
}
/* save key until type is known i.e. CBC, ECB, ... */
XMEMCPY((byte*)(aes->key), userKey, keylen);
aes->dir = dir;
return wc_AesSetIV(aes, iv);
}
/* AES-CBC */
#ifdef HAVE_AES_CBC
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct cmsghdr* cmsg;
struct iovec iov;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCBC,
AES_IV_SIZE, 0)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
}
sz = sz - (sz % AES_BLOCK_SIZE);
if ((sz / AES_BLOCK_SIZE) > 0) {
/* update IV */
cmsg = CMSG_FIRSTHDR(&(aes->msg));
ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg),
(byte*)(aes->reg), AES_IV_SIZE);
if (ret < 0) {
WOLFSSL_MSG("Error setting IV");
return ret;
}
/* set data to be encrypted */
iov.iov_base = (byte*)in;
iov.iov_len = sz;
aes->msg.msg_iov = &iov;
aes->msg.msg_iovlen = 1; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
ret = (int)read(aes->rdFd, out, sz);
if (ret < 0) {
return ret;
}
/* set IV for next CBC call */
XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
}
return 0;
}
#ifdef HAVE_AES_DECRYPT
int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct cmsghdr* cmsg;
struct iovec iov;
int ret;
if (aes == NULL || out == NULL || in == NULL
|| sz % AES_BLOCK_SIZE != 0) {
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCBC,
AES_IV_SIZE, 0)) != 0) {
return ret;
}
}
if ((sz / AES_BLOCK_SIZE) > 0) {
/* update IV */
cmsg = CMSG_FIRSTHDR(&(aes->msg));
ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg),
(byte*)(aes->reg), AES_IV_SIZE);
if (ret != 0) {
return ret;
}
/* set data to be decrypted */
iov.iov_base = (byte*)in;
iov.iov_len = sz;
aes->msg.msg_iov = &iov;
aes->msg.msg_iovlen = 1; /* # of iov structures */
/* set IV for next CBC call */
XMEMCPY(aes->reg, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
ret = (int)read(aes->rdFd, out, sz);
if (ret < 0) {
return ret;
}
}
return 0;
}
#endif
#endif /* HAVE_AES_CBC */
/* AES-DIRECT */
#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AES_ECB)
static const char WC_NAME_AESECB[] = "ecb(aes)";
/* common code between ECB encrypt and decrypt
* returns 0 on success */
static int wc_Afalg_AesDirect(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct iovec iov;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESECB,
0, 0)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
}
/* set data to be encrypted */
iov.iov_base = (byte*)in;
iov.iov_len = sz;
aes->msg.msg_iov = &iov;
aes->msg.msg_iovlen = 1; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
ret = (int)read(aes->rdFd, out, sz);
if (ret < 0) {
return ret;
}
return 0;
}
#endif
#if defined(WOLFSSL_AES_DIRECT)
void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
{
if (wc_Afalg_AesDirect(aes, out, in, AES_BLOCK_SIZE) != 0) {
WOLFSSL_MSG("Error with AES encrypt direct call");
}
}
void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
{
if (wc_Afalg_AesDirect(aes, out, in, AES_BLOCK_SIZE) != 0) {
WOLFSSL_MSG("Error with AES decrypt direct call");
}
}
int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
const byte* iv, int dir)
{
return wc_AesSetKey(aes, userKey, keylen, iv, dir);
}
#endif
/* AES-CTR */
#if defined(WOLFSSL_AES_COUNTER)
static const char WC_NAME_AESCTR[] = "ctr(aes)";
/* Increment AES counter */
static WC_INLINE void IncrementAesCounter(byte* inOutCtr)
{
/* in network byte order so start at end and work back */
int i;
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
if (++inOutCtr[i]) /* we're done unless we overflow */
return;
}
}
int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct cmsghdr* cmsg;
struct iovec iov[2];
int ret;
byte* tmp;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
/* consume any unused bytes left in aes->tmp */
tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
while (aes->left && sz) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
sz--;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCTR,
AES_IV_SIZE, 0)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
}
if (sz > 0) {
aes->left = sz % AES_BLOCK_SIZE;
/* clear previously leftover data */
tmp = (byte*)aes->tmp;
XMEMSET(tmp, 0, AES_BLOCK_SIZE);
/* update IV */
cmsg = CMSG_FIRSTHDR(&(aes->msg));
ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg),
(byte*)(aes->reg), AES_IV_SIZE);
if (ret < 0) {
WOLFSSL_MSG("Error setting IV");
return ret;
}
/* set data to be encrypted */
iov[0].iov_base = (byte*)in;
iov[0].iov_len = sz - aes->left;
iov[1].iov_base = tmp;
if (aes->left > 0) {
XMEMCPY(tmp, in + sz - aes->left, aes->left);
iov[1].iov_len = AES_BLOCK_SIZE;
}
else {
iov[1].iov_len = 0;
}
aes->msg.msg_iov = iov;
aes->msg.msg_iovlen = 2; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
/* set buffers to hold result and left over stream */
iov[0].iov_base = (byte*)out;
iov[0].iov_len = sz - aes->left;
iov[1].iov_base = tmp;
if (aes->left > 0) {
iov[1].iov_len = AES_BLOCK_SIZE;
}
else {
iov[1].iov_len = 0;
}
ret = (int)readv(aes->rdFd, iov, 2);
if (ret < 0) {
return ret;
}
if (aes->left > 0) {
XMEMCPY(out + sz - aes->left, tmp, aes->left);
aes->left = AES_BLOCK_SIZE - aes->left;
}
}
/* adjust counter after call to hardware */
while (sz >= AES_BLOCK_SIZE) {
IncrementAesCounter((byte*)aes->reg);
sz -= AES_BLOCK_SIZE;
}
if (aes->left > 0) {
IncrementAesCounter((byte*)aes->reg);
}
return 0;
}
#endif /* WOLFSSL_AES_COUNTER */
#ifdef HAVE_AESGCM
static const char WC_TYPE_AEAD[] = "aead";
static const char WC_NAME_AESGCM[] = "gcm(aes)";
#ifndef WC_SYSTEM_AESGCM_IV
/* size of IV allowed on system for AES-GCM */
#define WC_SYSTEM_AESGCM_IV 12
#endif
#ifndef WOLFSSL_MAX_AUTH_TAG_SZ
/* size of tag is restricted by system for AES-GCM
* check 'cat /proc/crypto' to see restricted size */
#define WOLFSSL_MAX_AUTH_TAG_SZ 16
#endif
int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
{
#if defined(AES_MAX_KEY_SIZE)
const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
#endif
if (aes == NULL ||
!((len == 16) || (len == 24) || (len == 32))) {
return BAD_FUNC_ARG;
}
#if defined(AES_MAX_KEY_SIZE)
/* Check key length */
if (len > max_key_len) {
return BAD_FUNC_ARG;
}
#endif
aes->keylen = len;
aes->rounds = len/4 + 6;
aes->rdFd = WC_SOCK_NOTSET;
aes->alFd = wc_Afalg_Socket();
if (aes->alFd < 0) {
WOLFSSL_MSG("Unable to open an AF_ALG socket");
return WC_AFALG_SOCK_E;
}
/* save key until direction is known i.e. encrypt or decrypt */
XMEMCPY((byte*)(aes->key), key, len);
return 0;
}
int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* iv, word32 ivSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
struct cmsghdr* cmsg;
struct iovec iov[3];
int ret;
struct msghdr* msg;
byte scratch[16];
/* argument checks */
if (aes == NULL || authTagSz > AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
if (ivSz != WC_SYSTEM_AESGCM_IV || authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ) {
WOLFSSL_MSG("IV/AAD size not supported on system");
return BAD_FUNC_ARG;
}
if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
aes->dir = AES_ENCRYPTION;
if ((ret = wc_AesSetup(aes, WC_TYPE_AEAD, WC_NAME_AESGCM, ivSz,
authInSz)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
/* note that if the ivSz was to change, the msg_controllen would need
reset */
/* set auth tag
* @TODO case where tag size changes between calls? */
ret = setsockopt(aes->alFd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL,
authTagSz);
if (ret != 0) {
perror("set tag");
WOLFSSL_MSG("Unable to set AF_ALG tag size ");
return WC_AFALG_SOCK_E;
}
}
msg = &(aes->msg);
cmsg = CMSG_FIRSTHDR(msg);
cmsg = CMSG_NXTHDR(msg, cmsg);
/* set IV and AAD size */
ret = wc_Afalg_SetIv(cmsg, (byte*)iv, ivSz);
if (ret < 0) {
WOLFSSL_MSG("Error setting IV");
return ret;
}
if (authInSz > 0) {
cmsg = CMSG_NXTHDR(msg, cmsg);
ret = wc_Afalg_SetAad(cmsg, authInSz);
if (ret < 0) {
WOLFSSL_MSG("Unable to set AAD size");
return ret;
}
}
/* set data to be encrypted*/
iov[0].iov_base = (byte*)authIn;
iov[0].iov_len = authInSz;
iov[1].iov_base = (byte*)in;
iov[1].iov_len = sz;
aes->msg.msg_iov = iov;
aes->msg.msg_iovlen = 2; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
perror("sendmsg error");
return ret;
}
/* first 16 bytes was all 0's */
iov[0].iov_base = scratch;
iov[0].iov_len = authInSz;
iov[1].iov_base = out;
iov[1].iov_len = sz;
iov[2].iov_base = authTag;
iov[2].iov_len = authTagSz;
ret = (int)readv(aes->rdFd, iov, 3);
if (ret < 0) {
perror("read error");
return ret;
}
return 0;
}
#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT)
int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* iv, word32 ivSz,
const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
struct cmsghdr* cmsg;
struct iovec iov[3];
int ret;
struct msghdr* msg;
byte scratch[16];
/* argument checks */
if (aes == NULL || authTagSz > AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
if (ivSz != WC_SYSTEM_AESGCM_IV || authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ) {
WOLFSSL_MSG("IV/AAD size not supported on system");
return BAD_FUNC_ARG;
}
if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
aes->dir = AES_DECRYPTION;
if ((ret = wc_AesSetup(aes, WC_TYPE_AEAD, WC_NAME_AESGCM, ivSz,
authInSz)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
/* set auth tag
* @TODO case where tag size changes between calls? */
ret = setsockopt(aes->alFd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL,
authTagSz);
if (ret != 0) {
WOLFSSL_MSG("Unable to set AF_ALG tag size ");
return WC_AFALG_SOCK_E;
}
}
/* set IV and AAD size */
msg = &(aes->msg);
cmsg = CMSG_FIRSTHDR(msg);
cmsg = CMSG_NXTHDR(msg, cmsg);
ret = wc_Afalg_SetIv(cmsg, (byte*)iv, ivSz);
if (ret < 0) {
return ret;
}
if (authInSz > 0) {
cmsg = CMSG_NXTHDR(msg, cmsg);
ret = wc_Afalg_SetAad(cmsg, authInSz);
if (ret < 0) {
return ret;
}
}
/* set data to be decrypted*/
iov[0].iov_base = (byte*)authIn;
iov[0].iov_len = authInSz;
iov[1].iov_base = (byte*)in;
iov[1].iov_len = sz;
iov[2].iov_base = (byte*)authTag;
iov[2].iov_len = authTagSz;
aes->msg.msg_iov = iov;
aes->msg.msg_iovlen = 3; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
iov[0].iov_base = scratch;
iov[0].iov_len = authInSz;
iov[1].iov_base = out;
iov[1].iov_len = sz;
ret = (int)readv(aes->rdFd, iov, 2);
if (ret < 0) {
return AES_GCM_AUTH_E;
}
return 0;
}
#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */
#endif /* HAVE_AESGCM */
#ifdef HAVE_AES_ECB
int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_Afalg_AesDirect(aes, out, in, sz);
}
int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_Afalg_AesDirect(aes, out, in, sz);
}
#endif /* HAVE_AES_ECB */
#endif /* !NO_AES && WOLFSSL_AFALG */

View File

@ -0,0 +1,193 @@
/* afalg_hash.c
*
* Copyright (C) 2006-2018 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_AFALG_HASH)
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
static const char WC_TYPE_HASH[] = "hash";
#if !defined(NO_SHA256)
#include <wolfssl/wolfcrypt/sha256.h>
static const char WC_NAME_SHA256[] = "sha256";
/* create AF_ALG sockets for SHA256 operation */
int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
{
if (sha == NULL) {
return BAD_FUNC_ARG;
}
(void)devId; /* no async for now */
XMEMSET(sha, 0, sizeof(wc_Sha256));
sha->heap = heap;
sha->len = 0;
sha->used = 0;
sha->msg = NULL;
sha->alFd = -1;
sha->rdFd = -1;
sha->alFd = wc_Afalg_Socket();
if (sha->alFd < 0) {
return WC_AFALG_SOCK_E;
}
sha->rdFd = wc_Afalg_CreateRead(sha->alFd, WC_TYPE_HASH, WC_NAME_SHA256);
if (sha->rdFd < 0) {
return WC_AFALG_SOCK_E;
}
return 0;
}
int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz)
{
if (sha == NULL || (sz > 0 && in == NULL)) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_AFALG_HASH_KEEP
/* keep full message to hash at end instead of incremental updates */
if (sha->len < sha->used + sz) {
if (sha->msg == NULL) {
sha->msg = (byte*)XMALLOC(sha->used + sz, sha->heap,
DYNAMIC_TYPE_TMP_BUFFER);
} else {
byte* pt = (byte*)XREALLOC(sha->msg, sha->used + sz, sha->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pt == NULL) {
return MEMORY_E;
}
sha->msg = pt;
}
if (sha->msg == NULL) {
return MEMORY_E;
}
sha->len = sha->used + sz;
}
XMEMCPY(sha->msg + sha->used, in, sz);
sha->used += sz;
#else
int ret;
if ((ret = (int)send(sha->rdFd, in, sz, MSG_MORE)) < 0) {
return ret;
}
#endif
return 0;
}
int wc_Sha256Final(wc_Sha256* sha, byte* hash)
{
int ret;
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_AFALG_HASH_KEEP
/* keep full message to hash at end instead of incremental updates */
if ((ret = (int)send(sha->rdFd, sha->msg, sha->used, 0)) < 0) {
return ret;
}
XFREE(sha->msg, sha->heap, DYNAMIC_TYPE_TMP_BUFFER);
sha->msg = NULL;
#else
if ((ret = (int)send(sha->rdFd, NULL, 0, 0)) < 0) {
return ret;
}
#endif
if ((ret = (int)read(sha->rdFd, hash, WC_SHA256_DIGEST_SIZE)) !=
WC_SHA256_DIGEST_SIZE) {
return ret;
}
wc_Sha256Free(sha);
return wc_InitSha256_ex(sha, sha->heap, 0);
}
int wc_Sha256GetHash(wc_Sha256* sha, byte* hash)
{
int ret;
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
(void)ret;
#ifdef WOLFSSL_AFALG_HASH_KEEP
if ((ret = (int)send(sha->rdFd, sha->msg, sha->used, 0)) < 0) {
return ret;
}
if ((ret = (int)read(sha->rdFd, hash, WC_SHA256_DIGEST_SIZE)) !=
WC_SHA256_DIGEST_SIZE) {
return ret;
}
return 0;
#else
(void)sha;
(void)hash;
WOLFSSL_MSG("Compile with WOLFSSL_AFALG_HASH_KEEP for this feature");
return NOT_COMPILED_IN;
#endif
}
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
XMEMCPY(dst, src, sizeof(wc_Sha256));
dst->rdFd = accept(src->rdFd, NULL, 0);
dst->alFd = accept(src->alFd, NULL, 0);
if (dst->rdFd == -1 || dst->alFd == -1) {
return -1;
}
return 0;
}
#endif /* !NO_SHA256 */
#endif /* WOLFSSL_AFALG */

View File

@ -0,0 +1,141 @@
/* wc_afalg.c
*
* Copyright (C) 2006-2017 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#if !defined(NO_AES) && defined(WOLFSSL_AFALG)
#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
#include <linux/if_alg.h>
/* Sets the type of socket address to use */
void wc_Afalg_SockAddr(struct sockaddr_alg* in, const char* type, const char* name)
{
in->salg_family = AF_ALG;
XSTRNCPY((char*)in->salg_type, type, XSTRLEN(type));
in->salg_type[XSTRLEN(type)] = '\0';
XSTRNCPY((char*)in->salg_name, name, XSTRLEN(name));
in->salg_name[XSTRLEN(name)] = '\0';
}
/* returns the socket accepting on with success
* negative values are returned in fail cases */
int wc_Afalg_Accept(struct sockaddr_alg* in, int inSz, int sock)
{
if (bind(sock, (const struct sockaddr*)in, inSz) < 0) {
WOLFSSL_MSG("Failed to bind with AF_ALG");
return WC_AFALG_SOCK_E;
}
return accept(sock, NULL, 0);
}
/* creates a new AF_ALG socket and returns it
* negative values are returned in fail cases */
int wc_Afalg_Socket(void)
{
int sock;
if ((sock = socket(AF_ALG, SOCK_SEQPACKET, 0)) < 0) {
WOLFSSL_MSG("Failed to get AF_ALG socket");
return WC_AFALG_SOCK_E;
}
return sock;
}
/* binds and creates the read fd */
int wc_Afalg_CreateRead(int sock, const char* type, const char* name)
{
struct sockaddr_alg sa = {};
wc_Afalg_SockAddr(&sa, type, name);
return wc_Afalg_Accept(&sa, sizeof(sa), sock);
}
/* sets the IV in CMSG structure, returns 0 on success */
int wc_Afalg_SetIv(struct cmsghdr* cmsg, byte* iv, word32 ivSz)
{
struct af_alg_iv* afIv;
if (cmsg == NULL || iv == NULL) {
WOLFSSL_MSG("Null cmsg or iv passed in");
return BAD_FUNC_ARG;
}
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_IV;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct af_alg_iv) + ivSz);
afIv = (void*)CMSG_DATA(cmsg);
afIv->ivlen = ivSz;
XMEMCPY(afIv->iv, iv, ivSz);
return 0;
}
/* sets the AAD size in CMSG structure, returns 0 on success */
int wc_Afalg_SetAad(struct cmsghdr* cmsg, word32 sz)
{
if (cmsg == NULL) {
WOLFSSL_MSG("Null cmsg passed in");
return BAD_FUNC_ARG;
}
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
cmsg->cmsg_len = CMSG_LEN(sizeof(word32));
*((word32*)CMSG_DATA(cmsg)) = sz;
return 0;
}
/* sets the operation type in CMSG structure, returns 0 on success
*
* dir 0 is encryption 1 is decryption
*/
int wc_Afalg_SetOp(struct cmsghdr* cmsg, int dir)
{
if (cmsg == NULL) {
return BAD_FUNC_ARG;
}
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_OP;
cmsg->cmsg_len = CMSG_LEN(4);
*((word32*)CMSG_DATA(cmsg)) = (dir == 1)? ALG_OP_DECRYPT : ALG_OP_ENCRYPT;
return 0;
}
#endif /* !NO_AES && WOLFSSL_AFALG */

View File

@ -135,7 +135,8 @@
#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \
(!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH))
(!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH)) && \
!defined(WOLFSSL_AFALG_HASH)
static int InitSha256(wc_Sha256* sha256)
{
int ret = 0;
@ -439,6 +440,10 @@ static int InitSha256(wc_Sha256* sha256)
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
/* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
#elif defined(WOLFSSL_AFALG_HASH)
/* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
#else
#define NEED_SOFT_SHA256
@ -2572,6 +2577,10 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
/* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
//#elif defined(WOLFSSL_AFALG_HASH)
// /* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
#else
#define NEED_SOFT_SHA224
@ -2735,10 +2744,24 @@ void wc_Sha256Free(wc_Sha256* sha256)
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
wolfAsync_DevCtxFree(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256);
#endif /* WOLFSSL_ASYNC_CRYPT */
#ifdef WOLFSSL_PIC32MZ_HASH
wc_Sha256Pic32Free(sha256);
#endif
#if defined(WOLFSSL_AFALG_HASH)
if (sha256->alFd > 0) {
close(sha256->alFd);
}
if (sha256->rdFd > 0) {
close(sha256->rdFd);
}
#if defined(WOLFSSL_AFALG_HASH_KEEP)
if (sha256->msg != NULL) {
XFREE(sha256->msg, sha256->heap, DYNAMIC_TYPE_TMP_BUFFER);
sha256->msg = NULL;
}
#endif
#endif /* WOLFSSL_AFALG_HASH */
}
#endif /* !WOLFSSL_TI_HASH */
@ -2782,6 +2805,10 @@ void wc_Sha256Free(wc_Sha256* sha256)
}
#endif /* WOLFSSL_SHA224 */
#ifdef WOLFSSL_AFALG_HASH
/* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
#else
int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
{
int ret;
@ -2818,6 +2845,7 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
return ret;
}
#endif
#endif /* !WOLFSSL_TI_HASH */
#endif /* NO_SHA256 */

View File

@ -164,6 +164,10 @@ int wolfCrypt_Init(void)
WOLFSSL_MSG("Using ARM hardware acceleration");
#endif
#ifdef WOLFSSL_AFALG
WOLFSSL_MSG("Using AF_ALG for crypto acceleration");
#endif
#if !defined(WOLFCRYPT_ONLY) && \
( defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) )
wolfSSL_EVP_init();

View File

@ -270,6 +270,7 @@ int aes256_test(void);
int cmac_test(void);
int poly1305_test(void);
int aesgcm_test(void);
int aesgcm_default_test(void);
int gmac_test(void);
int aesccm_test(void);
int aeskeywrap_test(void);
@ -751,10 +752,19 @@ initDefaultName();
printf( "AES256 test passed!\n");
#endif
#ifdef HAVE_AESGCM
#ifndef WOLFSSL_AFALG
if ( (ret = aesgcm_test()) != 0)
return err_sys("AES-GCM test failed!\n", ret);
else
printf( "AES-GCM test passed!\n");
#endif
{
if ((ret = aesgcm_default_test()) != 0) {
return err_sys("AES-GCM test failed!\n", ret);
}
else {
printf( "AES-GCM test passed!\n");
}
}
#endif
#if defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128)
@ -2045,8 +2055,9 @@ int sha256_test(void)
for (i = 0; i < times; ++i) {
ret = wc_Sha256Update(&sha, (byte*)test_sha[i].input,
(word32)test_sha[i].inLen);
if (ret != 0)
if (ret != 0) {
ERROR_OUT(-2202 - i, exit);
}
ret = wc_Sha256GetHash(&sha, hashcopy);
if (ret != 0)
ERROR_OUT(-2203 - i, exit);
@ -6542,6 +6553,173 @@ int aes256_test(void)
#ifdef HAVE_AESGCM
static int aesgcm_default_test_helper(byte* key, int keySz, byte* iv, int ivSz,
byte* plain, int plainSz, byte* cipher, int cipherSz,
byte* aad, int aadSz, byte* tag, int tagSz)
{
Aes enc;
Aes dec;
byte resultT[AES_BLOCK_SIZE];
byte resultP[AES_BLOCK_SIZE * 3];
byte resultC[AES_BLOCK_SIZE * 3];
int result;
XMEMSET(resultT, 0, sizeof(resultT));
XMEMSET(resultC, 0, sizeof(resultC));
XMEMSET(resultP, 0, sizeof(resultP));
if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) {
return -5700;
}
result = wc_AesGcmSetKey(&enc, key, keySz);
if (result != 0)
return -4701;
/* AES-GCM encrypt and decrypt both use AES encrypt internally */
result = wc_AesGcmEncrypt(&enc, resultC, plain, plainSz, iv, ivSz,
resultT, tagSz, aad, aadSz);
#if defined(WOLFSSL_ASYNC_CRYPT)
result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (result != 0)
return -4702;
if (XMEMCMP(cipher, resultC, cipherSz))
return -4703;
if (XMEMCMP(tag, resultT, tagSz))
return -4704;
wc_AesFree(&enc);
#ifdef HAVE_AES_DECRYPT
result = wc_AesGcmSetKey(&dec, key, keySz);
if (result != 0)
return -4705;
result = wc_AesGcmDecrypt(&dec, resultP, resultC, cipherSz,
iv, ivSz, resultT, tagSz, aad, aadSz);
#if defined(WOLFSSL_ASYNC_CRYPT)
result = wc_AsyncWait(result, &dec.asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (result != 0)
return -4706;
if (XMEMCMP(plain, resultP, plainSz))
return -4707;
wc_AesFree(&dec);
#endif /* HAVE_AES_DECRYPT */
return 0;
}
/* tests that only use 12 byte IV and 16 or less byte AAD
* test vectors are from NIST SP 800-38D
* https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES*/
int aesgcm_default_test(void)
{
byte key1[] = {
0x29, 0x8e, 0xfa, 0x1c, 0xcf, 0x29, 0xcf, 0x62,
0xae, 0x68, 0x24, 0xbf, 0xc1, 0x95, 0x57, 0xfc
};
byte iv1[] = {
0x6f, 0x58, 0xa9, 0x3f, 0xe1, 0xd2, 0x07, 0xfa,
0xe4, 0xed, 0x2f, 0x6d
};
byte plain1[] = {
0xcc, 0x38, 0xbc, 0xcd, 0x6b, 0xc5, 0x36, 0xad,
0x91, 0x9b, 0x13, 0x95, 0xf5, 0xd6, 0x38, 0x01,
0xf9, 0x9f, 0x80, 0x68, 0xd6, 0x5c, 0xa5, 0xac,
0x63, 0x87, 0x2d, 0xaf, 0x16, 0xb9, 0x39, 0x01
};
byte aad1[] = {
0x02, 0x1f, 0xaf, 0xd2, 0x38, 0x46, 0x39, 0x73,
0xff, 0xe8, 0x02, 0x56, 0xe5, 0xb1, 0xc6, 0xb1
};
byte cipher1[] = {
0xdf, 0xce, 0x4e, 0x9c, 0xd2, 0x91, 0x10, 0x3d,
0x7f, 0xe4, 0xe6, 0x33, 0x51, 0xd9, 0xe7, 0x9d,
0x3d, 0xfd, 0x39, 0x1e, 0x32, 0x67, 0x10, 0x46,
0x58, 0x21, 0x2d, 0xa9, 0x65, 0x21, 0xb7, 0xdb
};
byte tag1[] = {
0x54, 0x24, 0x65, 0xef, 0x59, 0x93, 0x16, 0xf7,
0x3a, 0x7a, 0x56, 0x05, 0x09, 0xa2, 0xd9, 0xf2
};
byte key2[] = {
0x01, 0x6d, 0xbb, 0x38, 0xda, 0xa7, 0x6d, 0xfe,
0x7d, 0xa3, 0x84, 0xeb, 0xf1, 0x24, 0x03, 0x64
};
byte iv2[] = {
0x07, 0x93, 0xef, 0x3a, 0xda, 0x78, 0x2f, 0x78,
0xc9, 0x8a, 0xff, 0xe3
};
byte plain2[] = {
0x4b, 0x34, 0xa9, 0xec, 0x57, 0x63, 0x52, 0x4b,
0x19, 0x1d, 0x56, 0x16, 0xc5, 0x47, 0xf6, 0xb7
};
byte cipher2[] = {
0x60, 0x9a, 0xa3, 0xf4, 0x54, 0x1b, 0xc0, 0xfe,
0x99, 0x31, 0xda, 0xad, 0x2e, 0xe1, 0x5d, 0x0c
};
byte tag2[] = {
0x33, 0xaf, 0xec, 0x59, 0xc4, 0x5b, 0xaf, 0x68,
0x9a, 0x5e, 0x1b, 0x13, 0xae, 0x42, 0x36, 0x19
};
byte key3[] = {
0xb0, 0x1e, 0x45, 0xcc, 0x30, 0x88, 0xaa, 0xba,
0x9f, 0xa4, 0x3d, 0x81, 0xd4, 0x81, 0x82, 0x3f
};
byte iv3[] = {
0x5a, 0x2c, 0x4a, 0x66, 0x46, 0x87, 0x13, 0x45,
0x6a, 0x4b, 0xd5, 0xe1
};
byte tag3[] = {
0x01, 0x42, 0x80, 0xf9, 0x44, 0xf5, 0x3c, 0x68,
0x11, 0x64, 0xb2, 0xff
};
int ret;
ret = aesgcm_default_test_helper(key1, sizeof(key1), iv1, sizeof(iv1),
plain1, sizeof(plain1), cipher1, sizeof(cipher1),
aad1, sizeof(aad1), tag1, sizeof(tag1));
if (ret != 0) {
return ret;
}
ret = aesgcm_default_test_helper(key2, sizeof(key2), iv2, sizeof(iv2),
plain2, sizeof(plain2), cipher2, sizeof(cipher2),
NULL, 0, tag2, sizeof(tag2));
if (ret != 0) {
return ret;
}
ret = aesgcm_default_test_helper(key3, sizeof(key3), iv3, sizeof(iv3),
NULL, 0, NULL, 0,
NULL, 0, tag3, sizeof(tag3));
if (ret != 0) {
return ret;
}
return 0;
}
int aesgcm_test(void)
{
Aes enc;

View File

@ -68,6 +68,11 @@
#include "xsecure_aes.h"
#endif
#ifdef WOLFSSL_AFALG
/* included for struct msghdr */
#include <sys/socket.h>
#endif
#if defined(HAVE_AESGCM) && !defined(WC_NO_RNG)
#include <wolfssl/wolfcrypt/random.h>
#endif
@ -150,6 +155,12 @@ typedef struct Aes {
XCsuDma dma;
word32 key_init[8];
word32 kup;
#endif
#ifdef WOLFSSL_AFALG
int alFd; /* server socket to bind to */
int rdFd; /* socket to read from */
struct msghdr msg;
int dir; /* flag for encrpyt or decrypt */
#endif
void* heap; /* memory hint to use */
} Aes;

View File

@ -213,7 +213,9 @@ enum {
RSA_KEY_PAIR_E = -262, /* RSA Key Pair-Wise Consistency check fail. */
DH_CHECK_PRIV_E = -263, /* DH Check Priv Key error */
WC_LAST_E = -263, /* Update this to indicate last error */
WC_AFALG_SOCK_E = -264, /* AF_ALG socket error */
WC_LAST_E = -264, /* Update this to indicate last error */
MIN_CODE_E = -300 /* errors -101 - -299 */
/* add new companion error id strings for any new error codes

View File

@ -77,7 +77,9 @@ noinst_HEADERS+= \
wolfssl/wolfcrypt/port/caam/wolfcaam.h \
wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h \
wolfssl/wolfcrypt/port/st/stm32.h \
wolfssl/wolfcrypt/port/st/stsafe.h
wolfssl/wolfcrypt/port/st/stsafe.h \
wolfssl/wolfcrypt/port/af_alg/afalg_hash.h \
wolfssl/wolfcrypt/port/af_alg/wc_afalg.h
if BUILD_ASYNCCRYPT
nobase_include_HEADERS+= wolfssl/wolfcrypt/async.h

View File

@ -0,0 +1,47 @@
/* afalg_hash.h
*
* Copyright (C) 2006-2018 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef WOLF_CRYPT_AFALG_HASH_H
#define WOLF_CRYPT_AFALG_HASH_H
#include <wolfssl/wolfcrypt/types.h>
#undef WOLFSSL_NO_HASH_RAW
#define WOLFSSL_NO_HASH_RAW
typedef struct {
byte* msg;
void* heap;
word32 used;
word32 len;
int alFd;
int rdFd;
} wolfssl_AFALG_Hash;
#if !defined(NO_SHA256)
typedef wolfssl_AFALG_Hash wc_Sha256;
#endif
#endif /* WOLF_CRYPT_AFALG_HASH_H */

View File

@ -0,0 +1,44 @@
/* wc_afalg.h
*
* Copyright (C) 2006-2017 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef WOLFSSL_AFALG_H
#define WOLFSSL_AFALG_H
#include <wolfssl/wolfcrypt/types.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
#include <linux/socket.h>
#define WC_SOCK_NOTSET -1
WOLFSSL_LOCAL void wc_Afalg_SockAddr(struct sockaddr_alg* in, const char* type, const char* name);
WOLFSSL_LOCAL int wc_Afalg_Accept(struct sockaddr_alg* in, int inSz, int sock);
WOLFSSL_LOCAL int wc_Afalg_Socket(void);
WOLFSSL_LOCAL int wc_Afalg_CreateRead(int sock, const char* type, const char* name);
WOLFSSL_LOCAL int wc_Afalg_SetIv(struct cmsghdr* cmsg, byte* iv, word32 ivSz);
WOLFSSL_LOCAL int wc_Afalg_SetOp(struct cmsghdr* cmsg, int dir);
WOLFSSL_LOCAL int wc_Afalg_SetAad(struct cmsghdr* cmsg, word32 sz);
#endif /* WOLFSSL_AFALG_H */

View File

@ -113,6 +113,8 @@ enum {
#include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
#elif defined(WOLFSSL_IMX6_CAAM)
#include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
#elif defined(WOLFSSL_AFALG_HASH)
#include "wolfssl/wolfcrypt/port/af_alg/afalg_hash.h"
#else
/* wc_Sha256 digest */
typedef struct wc_Sha256 {