Merge pull request #1832 from JacobBarthelmeh/HardwareAcc

Linux /dev/crypto SHA256 and AES
This commit is contained in:
David Garske
2018-09-20 18:05:35 -07:00
committed by GitHub
17 changed files with 1063 additions and 11 deletions

View File

@@ -728,6 +728,8 @@
}
#elif defined(WOLFSSL_AFALG)
#elif defined(WOLFSSL_DEVCRYPTO_AES)
/* if all AES is enabled with devcrypto then tables are not needed */
#else
@@ -1543,7 +1545,8 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT || HAVE_AESGCM */
#if defined(HAVE_AES_DECRYPT)
#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT)
#if (defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT)) && \
!defined(WOLFSSL_DEVCRYPTO_CBC)
/* load 4 Td Tables into cache by cache line stride */
static WC_INLINE word32 PreFetchTd(void)
@@ -1944,6 +1947,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#elif defined(WOLFSSL_DEVCRYPTO_AES)
/* implemented in wolfcrypt/src/port/devcrypto/devcrypto_aes.c */
#else
static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen,
const byte* iv, int dir)
@@ -2170,6 +2176,11 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
#if defined(WOLFSSL_DEVCRYPTO) && \
(defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))
aes->ctx.cfd = -1;
XMEMCPY(aes->devKey, userKey, keylen);
#endif
#ifdef WOLFSSL_IMX6_CAAM_BLOB
ForceZero(local, sizeof(local));
#endif
@@ -2264,6 +2275,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#elif defined(WOLFSSL_DEVCRYPTO_AES)
/* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
#else
/* Allow direct access to one block encrypt */
void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
@@ -2805,6 +2819,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#elif defined(WOLFSSL_DEVCRYPTO_CBC)
/* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
#else
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
@@ -3129,6 +3146,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#elif defined(WOLFSSL_DEVCRYPTO_AES)
/* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
#else
/* Use software based AES counter */
@@ -3242,6 +3262,9 @@ static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/afalg/afalg_aes.c */
#elif defined(WOLFSSL_DEVCRYPTO_AES)
/* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
#else /* software + AESNI implementation */
#if !defined(FREESCALE_LTC_AES_GCM)
@@ -9435,6 +9458,10 @@ int wc_AesInit(Aes* aes, void* heap, int devId)
aes->alFd = -1;
aes->rdFd = -1;
#endif
#if defined(WOLFSSL_DEVCRYPTO) && \
(defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))
aes->ctx.cfd = -1;
#endif
return ret;
}
@@ -9456,6 +9483,11 @@ void wc_AesFree(Aes* aes)
close(aes->alFd);
}
#endif /* WOLFSSL_AFALG */
#if defined(WOLFSSL_DEVCRYPTO) && \
(defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))
wc_DevCryptoFree(&aes->ctx);
ForceZero((byte*)aes->devKey, AES_MAX_KEY_SIZE/WOLFSSL_BIT_SIZE);
#endif
}
@@ -9500,6 +9532,9 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize)
#elif defined(WOLFSSL_AFALG)
/* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
#elif defined(WOLFSSL_DEVCRYPTO_AES)
/* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
#else
/* software implementation */

View File

@@ -485,6 +485,9 @@ const char* wc_GetErrorString(int error)
case WC_AFALG_SOCK_E:
return "AF_ALG socket error";
case WC_DEVCRYPTO_E:
return "Error with /dev/crypto";
default:
return "unknown error number";

View File

@@ -65,12 +65,21 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \
wolfcrypt/src/port/st/stsafe.c \
wolfcrypt/src/port/st/README.md \
wolfcrypt/src/port/af_alg/afalg_aes.c \
wolfcrypt/src/port/af_alg/afalg_hash.c
wolfcrypt/src/port/af_alg/afalg_hash.c \
wolfcrypt/src/port/devcrypto/devcrypto_hash.c \
wolfcrypt/src/port/devcrypto/wc_devcrypto.c \
wolfcrypt/src/port/devcrypto/README.md
if BUILD_CRYPTODEV
src_libwolfssl_la_SOURCES += wolfcrypt/src/cryptodev.c
endif
if BUILD_DEVCRYPTO
src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/devcrypto_hash.c
src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/devcrypto_aes.c
src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/wc_devcrypto.c
endif
if BUILD_CAVIUM
src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c

View File

@@ -0,0 +1,43 @@
# Description
Used to build with cryptodev-linux library with Linux OS.
# Quick Start
## Installing cryptodev module
If not already installed then the cryptodev-linux module will need installed.
```
git clone https://github.com/cryptodev-linux/cryptodev-linux.git
cd cryptodev-linux
make
sudo make install
modprobe cryptodev
```
## Options for building wolfSSL
For default build with all supported features use:
```
./configure --enable-cryptodev
```
Or for more control over features used:
```
./configure --enable-devcrypto=cbc
./configure --enable-devcrypto=hash
./configure --enable-devcrypto=aes
./configure --enable-devcrypto=all
```
Then build the wolfSSL library with:
```
make
sudo make install
./wolfcrypt/test/testwolfcrypt
```

View File

@@ -0,0 +1,384 @@
/* devcrypto_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_DEVCRYPTO)
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#if defined(HAVE_AES_CBC) && defined(WOLFSSL_DEVCRYPTO_CBC)
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct crypt_op crt;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
/* encrypt only up to AES block size of date */
sz = sz - (sz % AES_BLOCK_SIZE);
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CBC,
(byte*)aes->devKey, aes->keylen);
if (ret != 0)
return ret;
}
wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg,
COP_ENCRYPT);
ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt);
if (ret != 0) {
return WC_DEVCRYPTO_E;
}
/* store iv for next 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 crypt_op crt;
int ret;
if (aes == NULL || out == NULL || in == NULL || sz % AES_BLOCK_SIZE != 0) {
return BAD_FUNC_ARG;
}
XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CBC,
(byte*)aes->devKey, aes->keylen);
if (ret != 0)
return ret;
}
wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg,
COP_DECRYPT);
ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt);
if (ret != 0) {
return WC_DEVCRYPTO_E;
}
XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
return 0;
}
#endif /* HAVE_AES_DECRYPT */
#endif /* HAVE_AES_CBC && WOLFSSL_DEVCRYPTO_CBC */
#ifdef WOLFSSL_DEVCRYPTO_AES /* all AES algorithms supported */
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->ctx.cfd = -1;
XMEMCPY(aes->devKey, userKey, keylen);
(void)dir;
return wc_AesSetIV(aes, iv);
}
/* AES-DIRECT */
#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AES_ECB)
/* common code between ECB encrypt and decrypt
* returns 0 on success */
static int wc_DevCrypto_AesDirect(Aes* aes, byte* out, const byte* in,
word32 sz, int dir)
{
int ret;
struct crypt_op crt;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_ECB, (byte*)aes->devKey,
aes->keylen);
if (ret != 0)
return ret;
}
wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, NULL, dir);
ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt);
if (ret != 0) {
return WC_DEVCRYPTO_E;
}
return 0;
}
#endif
#if defined(WOLFSSL_AES_DIRECT)
void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
{
wc_DevCrypto_AesDirect(aes, out, in, AES_BLOCK_SIZE, COP_ENCRYPT);
}
void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
{
wc_DevCrypto_AesDirect(aes, out, in, AES_BLOCK_SIZE, COP_DECRYPT);
}
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)
/* 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)
{
int ret;
struct crypt_op crt;
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->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CTR, (byte*)aes->devKey,
aes->keylen);
if (ret != 0)
return ret;
}
if (sz > 0) {
/* clear previously leftover data */
tmp = (byte*)aes->tmp;
XMEMSET(tmp, 0, AES_BLOCK_SIZE);
/* update IV */
wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg,
COP_ENCRYPT);
ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt);
if (ret != 0) {
return WC_DEVCRYPTO_E;
}
/* adjust counter after call to hardware */
while (sz >= AES_BLOCK_SIZE) {
IncrementAesCounter((byte*)aes->reg);
sz -= AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
}
}
/* create key stream for later if needed */
if (sz > 0) {
Aes tmpAes;
wc_AesSetKey(&tmpAes, (byte*)aes->devKey, aes->keylen, (byte*)aes->reg,
AES_ENCRYPTION);
wc_AesEncryptDirect(&tmpAes, (byte*)aes->tmp, (const byte*)aes->reg);
wc_AesFree(&tmpAes);
IncrementAesCounter((byte*)aes->reg);
aes->left = AES_BLOCK_SIZE - (sz % AES_BLOCK_SIZE);
}
return 0;
}
#endif /* WOLFSSL_AES_COUNTER */
#ifdef HAVE_AESGCM
int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
{
return wc_AesSetKey(aes, key, len, NULL, AES_ENCRYPTION);
}
/* common code for AES-GCM encrypt/decrypt */
static int wc_DevCrypto_AesGcm(Aes* aes, byte* out, byte* in, word32 sz,
const byte* iv, word32 ivSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz,
int dir)
{
struct crypt_auth_op crt = {0};
int ret;
byte scratch[AES_BLOCK_SIZE];
/* argument checks */
if (aes == NULL || authTagSz > AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
/* Account for NULL in/out buffers. Up to tag size is still written into
* in/out buffers */
if (out == NULL)
out = scratch;
if (in == NULL)
in = scratch;
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_GCM, (byte*)aes->devKey,
aes->keylen);
if (ret != 0)
return ret;
}
/* if decrypting then the tag is expected to be at the end of "in" buffer */
if (dir == COP_DECRYPT) {
XMEMCPY(in + sz, authTag, authTagSz);
sz += authTagSz;
}
else{
/* get full tag from hardware */
authTagSz = AES_BLOCK_SIZE;
}
wc_SetupCryptAead(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)iv, ivSz,
dir, (byte*)authIn, authInSz, authTag, authTagSz);
ret = ioctl(aes->ctx.cfd, CIOCAUTHCRYPT, &crt);
if (ret != 0) {
if (dir == COP_DECRYPT) {
return AES_GCM_AUTH_E;
}
else {
return WC_DEVCRYPTO_E;
}
}
/* after encryption the tag has been placed at the end of "out" buffer */
if (dir == COP_ENCRYPT) {
XMEMCPY(authTag, out + sz, authTagSz);
}
return 0;
}
/* it is assumed that "out" buffer has enough room for cipher text + tag */
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)
{
if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
return BAD_FUNC_ARG;
}
return wc_DevCrypto_AesGcm(aes, out, (byte*)in, sz, iv, ivSz,
authTag, authTagSz, authIn, authInSz,
COP_ENCRYPT);
}
#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT)
/* it is assumed that "in" buffer has enough room for cipher text + tag */
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)
{
return wc_DevCrypto_AesGcm(aes, out, (byte*)in, sz, iv, ivSz,
(byte*)authTag, authTagSz, authIn, authInSz,
COP_DECRYPT);
}
#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_DevCrypto_AesDirect(aes, out, in, sz, COP_ENCRYPT);
}
int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_DevCrypto_AesDirect(aes, out, in, sz, COP_DECRYPT);
}
#endif /* HAVE_AES_ECB */
#endif /* WOLFSSL_DEVCRYPTO_AES */
#endif /* !NO_AES && WOLFSSL_DEVCRYPTO */

View File

@@ -0,0 +1,248 @@
/* devcrypto_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_DEVCRYPTO_HASH)
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
#if !defined(NO_SHA256)
#include <wolfssl/wolfcrypt/sha256.h>
#endif
/* dereference structure based on type to get cryptodev context pointer
* can return NULL on fail case */
static WC_CRYPTODEV* GetHashContext(void* ctx, int type)
{
switch (type) {
case CRYPTO_SHA2_256:
return &((wc_Sha256*)ctx)->ctx;
default:
return NULL;
}
return NULL;
}
/* generic hash initialization
* key is for hmac algorithms and keySz is for the size of key buffer
* key should be null in the case of non hmac algorithms
* return 0 on success */
static int HashInit(void* ctx, int type, byte* key, word32 keySz)
{
WC_CRYPTODEV* cdev;
if ((cdev = GetHashContext(ctx, type)) == NULL) {
WOLFSSL_MSG("Unsupported hash type");
return BAD_FUNC_ARG;
}
return wc_DevCryptoCreate(cdev, type, key, keySz);
}
/* generic function for updated hash structure
* returns 0 on success */
static int HashUpdate(void* ctx, int type, const byte* input, word32 inputSz)
{
WC_CRYPTODEV* dev;
struct crypt_op crt;
byte digest[64];
if (inputSz == 0) {
return 0;
}
if ((dev = GetHashContext(ctx, type)) == NULL) {
WOLFSSL_MSG("Unsuported hash type");
return BAD_FUNC_ARG;
}
wc_SetupCrypt(&crt, dev, (byte*)input, inputSz, NULL, digest, COP_FLAG_UPDATE);
if (ioctl(dev->cfd, CIOCCRYPT, &crt)) {
WOLFSSL_MSG("Error with call to ioctl");
return WC_DEVCRYPTO_E;
}
return 0;
}
/* generic function for getting final digest value */
static int GetDigest(void* ctx, int type, byte* out)
{
WC_CRYPTODEV* dev;
struct crypt_op crt;
if ((dev = GetHashContext(ctx, type)) == NULL) {
WOLFSSL_MSG("Unsuported hash type");
return BAD_FUNC_ARG;
}
wc_SetupCrypt(&crt, dev, NULL, 0, NULL, out, COP_FLAG_FINAL);
if (ioctl(dev->cfd, CIOCCRYPT, &crt)) {
WOLFSSL_MSG("Error with call to ioctl");
return WC_DEVCRYPTO_E;
}
return 0;
}
#if !defined(NO_SHA256)
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;
return HashInit((void*)sha, CRYPTO_SHA2_256, NULL, 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_DEVCRYPTO_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;
return 0;
#else
return HashUpdate(sha, CRYPTO_SHA2_256, in, sz);
#endif
}
int wc_Sha256Final(wc_Sha256* sha, byte* hash)
{
int ret;
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
/* help static analysis tools out */
XMEMSET(hash, 0, WC_SHA256_DIGEST_SIZE);
#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP
/* keep full message to hash at end instead of incremental updates */
if ((ret = HashUpdate(sha, CRYPTO_SHA2_256, sha->msg, sha->used)) < 0) {
return ret;
}
XFREE(sha->msg, sha->heap, DYNAMIC_TYPE_TMP_BUFFER);
sha->msg = NULL;
#endif
ret = GetDigest(sha, CRYPTO_SHA2_256, hash);
if (ret != 0) {
return ret;
}
wc_Sha256Free(sha);
return wc_InitSha256_ex(sha, sha->heap, 0);
}
int wc_Sha256GetHash(wc_Sha256* sha, byte* hash)
{
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP
{
int ret;
wc_Sha256 cpy;
wc_Sha256Copy(sha, &cpy);
if ((ret = HashUpdate(&cpy, CRYPTO_SHA2_256, cpy.msg, cpy.used)) == 0) {
/* help static analysis tools out */
XMEMSET(hash, 0, WC_SHA256_DIGEST_SIZE);
ret = GetDigest(&cpy, CRYPTO_SHA2_256, hash);
}
wc_Sha256Free(&cpy);
return ret;
}
#else
(void)sha;
(void)hash;
WOLFSSL_MSG("Compile with WOLFSSL_DEVCRYPTO_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;
}
wc_InitSha256_ex(dst, src->heap, 0);
#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP
dst->len = src->len;
dst->used = src->used;
dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (dst->msg == NULL) {
return MEMORY_E;
}
XMEMCPY(dst->msg, src->msg, src->len);
#endif
return 0;
}
#endif /* !NO_SHA256 */
#endif /* WOLFSSL_DEVCRYPTO */

View File

@@ -0,0 +1,167 @@
/* wc_devcrypto.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_DEVCRYPTO)
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
/* sets up a context for talking to /dev/crypto
* return 0 on success */
int wc_DevCryptoCreate(WC_CRYPTODEV* ctx, int type, byte* key, word32 keySz)
{
int fd;
int isHash = 0; /* flag for if hashing algorithm */
if (ctx == NULL) {
return BAD_FUNC_ARG;
}
/* sanity check on session type before creating descriptor */
XMEMSET(ctx, 0, sizeof(WC_CRYPTODEV));
switch (type) {
case CRYPTO_SHA1:
case CRYPTO_SHA2_256:
isHash = 1;
break;
#ifndef NO_AES
case CRYPTO_AES_CTR:
case CRYPTO_AES_ECB:
case CRYPTO_AES_GCM:
case CRYPTO_AES_CBC:
isHash = 0;
break;
#endif
default:
WOLFSSL_MSG("Unknown / Unimplemented algorithm type");
return BAD_FUNC_ARG;
}
/* create descriptor */
if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
WOLFSSL_MSG("Error opening /dev/crypto is cryptodev module loaded?");
return WC_DEVCRYPTO_E;
}
if (fcntl(fd, F_SETFD, 1) == -1) {
WOLFSSL_MSG("Error setting F_SETFD with fcntl");
close(fd);
return WC_DEVCRYPTO_E;
}
/* set up session */
ctx->cfd = fd;
if (isHash) {
ctx->sess.mac = type;
}
else {
ctx->sess.cipher = type;
ctx->sess.key = (void*)key;
ctx->sess.keylen = keySz;
}
if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
close(fd);
WOLFSSL_MSG("Error starting cryptodev session");
return WC_DEVCRYPTO_E;
}
(void)key;
(void)keySz;
return 0;
}
/* free up descriptor and session used with ctx */
void wc_DevCryptoFree(WC_CRYPTODEV* ctx)
{
if (ctx != NULL && ctx->cfd >= 0) {
if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
WOLFSSL_MSG("Error stopping cryptodev session");
}
close(ctx->cfd);
}
}
/* setup crypt_op structure */
void wc_SetupCrypt(struct crypt_op* crt, WC_CRYPTODEV* dev,
byte* src, int srcSz, byte* dst, byte* dig, int flag)
{
XMEMSET(crt, 0, sizeof(struct crypt_op));
crt->ses = dev->sess.ses;
crt->src = src;
crt->len = srcSz;
crt->dst = dst;
crt->mac = dig;
crt->flags = flag;
}
/* setup crypt_op structure for symmetric key operations */
void wc_SetupCryptSym(struct crypt_op* crt, WC_CRYPTODEV* dev,
byte* src, word32 srcSz, byte* dst, byte* iv, int flag)
{
XMEMSET(crt, 0, sizeof(struct crypt_op));
crt->ses = dev->sess.ses;
crt->src = src;
crt->len = srcSz;
crt->dst = dst;
crt->iv = iv;
crt->op = flag;
}
/* setup crypt_auth_op structure for aead operations */
void wc_SetupCryptAead(struct crypt_auth_op* crt, WC_CRYPTODEV* dev,
byte* src, word32 srcSz, byte* dst, byte* iv, word32 ivSz, int flag,
byte* authIn, word32 authInSz, byte* authTag, word32 authTagSz)
{
XMEMSET(crt, 0, sizeof(struct crypt_op));
crt->ses = dev->sess.ses;
crt->src = src;
crt->len = srcSz;
crt->dst = dst;
crt->iv = iv;
crt->iv_len = ivSz;
crt->op = flag;
/* also set auth in and tag */
crt->auth_src = authIn;
crt->auth_len = authInSz;
crt->tag = authTag;
crt->tag_len = authTagSz;
}
#endif /* WOLFSSL_DEVCRYPTO */

View File

@@ -108,6 +108,11 @@
#include <wolfcrypt/src/misc.c>
#endif
#ifdef WOLFSSL_DEVCRYPTO_HASH
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
#endif
#if defined(USE_INTEL_SPEEDUP)
#define HAVE_INTEL_AVX1
@@ -136,7 +141,7 @@
#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \
(!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH)) && \
!defined(WOLFSSL_AFALG_HASH)
!defined(WOLFSSL_AFALG_HASH) && !defined(WOLFSSL_DEVCRYPTO_HASH)
static int InitSha256(wc_Sha256* sha256)
{
int ret = 0;
@@ -444,6 +449,9 @@ static int InitSha256(wc_Sha256* sha256)
#elif defined(WOLFSSL_AFALG_HASH)
/* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
#elif defined(WOLFSSL_DEVCRYPTO_HASH)
/* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
#else
#define NEED_SOFT_SHA256
@@ -2581,6 +2589,9 @@ SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
#elif defined(WOLFSSL_AFALG_HASH)
#error SHA224 currently not supported with AF_ALG enabled
#elif defined(WOLFSSL_DEVCRYPTO_HASH)
/* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
#else
#define NEED_SOFT_SHA224
@@ -2756,14 +2767,17 @@ void wc_Sha256Free(wc_Sha256* sha256)
close(sha256->rdFd);
sha256->rdFd = -1; /* avoid possible double close on socket */
}
#if defined(WOLFSSL_AFALG_HASH_KEEP)
#endif /* WOLFSSL_AFALG_HASH */
#ifdef WOLFSSL_DEVCRYPTO_HASH
wc_DevCryptoFree(&sha256->ctx);
#endif /* WOLFSSL_DEVCRYPTO */
#if defined(WOLFSSL_AFALG_HASH_KEEP) || \
(defined(WOLFSSL_DEVCRYPTO_HASH) && defined(WOLFSSL_DEVCRYPTO_HASH_KEEP))
if (sha256->msg != NULL) {
XFREE(sha256->msg, sha256->heap, DYNAMIC_TYPE_TMP_BUFFER);
sha256->msg = NULL;
}
#endif
#endif /* WOLFSSL_AFALG_HASH */
#endif
}
#endif /* !WOLFSSL_TI_HASH */
@@ -2809,6 +2823,10 @@ void wc_Sha256Free(wc_Sha256* sha256)
#ifdef WOLFSSL_AFALG_HASH
/* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
#elif defined(WOLFSSL_DEVCRYPTO_HASH)
/* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
#else
int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)