Fixes for building ARMv8. Adds missing SHA224 and AES KeyWrap. Fixes for FE/GE warning with Aarch32. Fix possible build error with `ed25519_test` with `ret` not defined.

This commit is contained in:
David Garske 2017-07-07 15:12:51 -07:00
parent b6854d620f
commit 205da48416
4 changed files with 360 additions and 37 deletions

View File

@ -4645,6 +4645,177 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
#endif /* HAVE_AES_DECRYPT */
#endif /* WOLFSSL_AES_DIRECT */
#ifdef HAVE_AES_KEYWRAP
/* Initialize key wrap counter with value */
static INLINE void InitKeyWrapCounter(byte* inOutCtr, word32 value)
{
int i;
word32 bytes;
bytes = sizeof(word32);
for (i = 0; i < (int)sizeof(word32); i++) {
inOutCtr[i+sizeof(word32)] = (value >> ((bytes - 1) * 8)) & 0xFF;
bytes--;
}
}
/* Increment key wrap counter */
static INLINE void IncrementKeyWrapCounter(byte* inOutCtr)
{
int i;
/* in network byte order so start at end and work back */
for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) {
if (++inOutCtr[i]) /* we're done unless we overflow */
return;
}
}
/* Decrement key wrap counter */
static INLINE void DecrementKeyWrapCounter(byte* inOutCtr)
{
int i;
for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) {
if (--inOutCtr[i] != 0xFF) /* we're done unless we underflow */
return;
}
}
/* perform AES key wrap (RFC3394), return out sz on success, negative on err */
int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
byte* out, word32 outSz, const byte* iv)
{
Aes aes;
byte* r;
word32 i;
int ret, j;
byte t[KEYWRAP_BLOCK_SIZE];
byte tmp[AES_BLOCK_SIZE];
/* n must be at least 2, output size is n + 8 bytes */
if (key == NULL || in == NULL || inSz < 2 ||
out == NULL || outSz < (inSz + KEYWRAP_BLOCK_SIZE))
return BAD_FUNC_ARG;
/* input must be multiple of 64-bits */
if (inSz % KEYWRAP_BLOCK_SIZE != 0)
return BAD_FUNC_ARG;
/* user IV is optional */
if (iv == NULL) {
XMEMSET(tmp, 0xA6, KEYWRAP_BLOCK_SIZE);
} else {
XMEMCPY(tmp, iv, KEYWRAP_BLOCK_SIZE);
}
r = out + 8;
XMEMCPY(r, in, inSz);
XMEMSET(t, 0, sizeof(t));
ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_ENCRYPTION);
if (ret != 0)
return ret;
for (j = 0; j <= 5; j++) {
for (i = 1; i <= inSz / KEYWRAP_BLOCK_SIZE; i++) {
/* load R[i] */
XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE);
wc_AesEncryptDirect(&aes, tmp, tmp);
/* calculate new A */
IncrementKeyWrapCounter(t);
xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE);
/* save R[i] */
XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE);
r += KEYWRAP_BLOCK_SIZE;
}
r = out + KEYWRAP_BLOCK_SIZE;
}
/* C[0] = A */
XMEMCPY(out, tmp, KEYWRAP_BLOCK_SIZE);
return inSz + KEYWRAP_BLOCK_SIZE;
}
int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
byte* out, word32 outSz, const byte* iv)
{
Aes aes;
byte* r;
word32 i, n;
int ret, j;
byte t[KEYWRAP_BLOCK_SIZE];
byte tmp[AES_BLOCK_SIZE];
const byte* expIv;
const byte defaultIV[] = {
0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
};
(void)iv;
if (key == NULL || in == NULL || inSz < 3 ||
out == NULL || outSz < (inSz - KEYWRAP_BLOCK_SIZE))
return BAD_FUNC_ARG;
/* input must be multiple of 64-bits */
if (inSz % KEYWRAP_BLOCK_SIZE != 0)
return BAD_FUNC_ARG;
/* user IV optional */
if (iv != NULL) {
expIv = iv;
} else {
expIv = defaultIV;
}
/* A = C[0], R[i] = C[i] */
XMEMCPY(tmp, in, KEYWRAP_BLOCK_SIZE);
XMEMCPY(out, in + KEYWRAP_BLOCK_SIZE, inSz - KEYWRAP_BLOCK_SIZE);
XMEMSET(t, 0, sizeof(t));
ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_DECRYPTION);
if (ret != 0)
return ret;
/* initialize counter to 6n */
n = (inSz - 1) / KEYWRAP_BLOCK_SIZE;
InitKeyWrapCounter(t, 6 * n);
for (j = 5; j >= 0; j--) {
for (i = n; i >= 1; i--) {
/* calculate A */
xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE);
DecrementKeyWrapCounter(t);
/* load R[i], starting at end of R */
r = out + ((i - 1) * KEYWRAP_BLOCK_SIZE);
XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE);
wc_AesDecryptDirect(&aes, tmp, tmp);
/* save R[i] */
XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE);
}
}
/* verify IV */
if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0)
return BAD_KEYWRAP_IV_E;
return inSz - KEYWRAP_BLOCK_SIZE;
}
#endif /* HAVE_AES_KEYWRAP */
int wc_AesGetKeySize(Aes* aes, word32* keySize)
{
int ret = 0;

View File

@ -26,7 +26,9 @@
#include <wolfssl/wolfcrypt/settings.h>
#if !defined(NO_SHA256) && defined(WOLFSSL_ARMASM)
#ifdef WOLFSSL_ARMASM
#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224)
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
@ -56,7 +58,7 @@ static const ALIGN32 word32 K[64] = {
};
int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId)
static int InitSha256(Sha256* sha256)
{
int ret = 0;
@ -77,41 +79,25 @@ int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId)
sha256->loLen = 0;
sha256->hiLen = 0;
(void)heap;
(void)devId;
return ret;
}
int wc_InitSha256(Sha256* sha256)
{
return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
}
void wc_Sha256Free(Sha256* sha256)
{
(void)sha256;
}
static INLINE void AddLength(Sha256* sha256, word32 len)
{
word32 tmp = sha256->loLen;
if ( (sha256->loLen += len) < tmp)
if ((sha256->loLen += len) < tmp)
sha256->hiLen++; /* carry low to high */
}
#ifdef __aarch64__
/* ARMv8 hardware accleration */
int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len)
static INLINE int Sha256Update(Sha256* sha256, const byte* data, word32 len)
{
word32 add;
word32 numBlocks;
if (sha256 == NULL || (data == NULL && len != 0)) {
return BAD_FUNC_ARG;
}
/* only perform actions if a buffer is passed in */
if (len > 0) {
/* fill leftover buffer with data */
@ -320,14 +306,10 @@ int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len)
}
int wc_Sha256Final(Sha256* sha256, byte* hash)
static INLINE int Sha256Final(Sha256* sha256, byte* hash)
{
byte* local;
if (sha256 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
local = (byte*)sha256->buffer;
AddLength(sha256, sha256->buffLen); /* before adding pads */
@ -667,20 +649,17 @@ int wc_Sha256Final(Sha256* sha256, byte* hash)
"v22", "v23", "v24", "v25"
);
return wc_InitSha256(sha256); /* reset state */
return 0;
}
#else /* not using 64 bit */
/* ARMv8 hardware accleration Aarch32 */
int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len)
static INLINE int Sha256Update(Sha256* sha256, const byte* data, word32 len)
{
word32 add;
word32 numBlocks;
if (sha256 == NULL || (data == NULL && len != 0)) {
return BAD_FUNC_ARG;
}
/* only perform actions if a buffer is passed in */
if (len > 0) {
/* fill leftover buffer with data */
@ -903,7 +882,7 @@ int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len)
}
int wc_Sha256Final(Sha256* sha256, byte* hash)
static INLINE int Sha256Final(Sha256* sha256, byte* hash)
{
byte* local;
@ -1298,12 +1277,66 @@ int wc_Sha256Final(Sha256* sha256, byte* hash)
"q15"
);
return wc_InitSha256(sha256); /* reset state */
return 0;
}
#endif /* __aarch64__ */
#ifndef NO_SHA256
int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId)
{
int ret = 0;
if (sha256 == NULL)
return BAD_FUNC_ARG;
sha256->heap = heap;
ret = InitSha256(sha256);
if (ret != 0)
return ret;
(void)devId;
return ret;
}
int wc_InitSha256(Sha256* sha256)
{
return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
}
void wc_Sha256Free(Sha256* sha256)
{
(void)sha256;
}
int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len)
{
if (sha256 == NULL || (data == NULL && len != 0)) {
return BAD_FUNC_ARG;
}
return Sha256Update(sha256, data, len);
}
int wc_Sha256Final(Sha256* sha256, byte* hash)
{
int ret;
if (sha256 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = Sha256Final(sha256, hash);
if (ret != 0)
return ret;
return InitSha256(sha256); /* reset state */
}
int wc_Sha256GetHash(Sha256* sha256, byte* hash)
{
int ret;
@ -1331,4 +1364,122 @@ int wc_Sha256Copy(Sha256* src, Sha256* dst)
return ret;
}
#endif /* NO_SHA256 and WOLFSSL_ARMASM */
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA224
static int InitSha224(Sha224* sha224)
{
int ret = 0;
if (sha224 == NULL) {
return BAD_FUNC_ARG;
}
sha224->digest[0] = 0xc1059ed8;
sha224->digest[1] = 0x367cd507;
sha224->digest[2] = 0x3070dd17;
sha224->digest[3] = 0xf70e5939;
sha224->digest[4] = 0xffc00b31;
sha224->digest[5] = 0x68581511;
sha224->digest[6] = 0x64f98fa7;
sha224->digest[7] = 0xbefa4fa4;
sha224->buffLen = 0;
sha224->loLen = 0;
sha224->hiLen = 0;
return ret;
}
int wc_InitSha224_ex(Sha224* sha224, void* heap, int devId)
{
int ret = 0;
if (sha224 == NULL)
return BAD_FUNC_ARG;
sha224->heap = heap;
ret = InitSha224(sha224);
if (ret != 0)
return ret;
(void)devId;
return ret;
}
int wc_InitSha224(Sha224* sha224)
{
return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID);
}
int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len)
{
int ret;
if (sha224 == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
ret = Sha256Update((Sha256 *)sha224, data, len);
return ret;
}
int wc_Sha224Final(Sha224* sha224, byte* hash)
{
int ret;
word32 hashTmp[SHA256_DIGEST_SIZE/sizeof(word32)];
if (sha224 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = Sha256Final((Sha256*)sha224, (byte*)hashTmp);
if (ret != 0)
return ret;
XMEMCPY(hash, hashTmp, SHA224_DIGEST_SIZE);
return InitSha224(sha224); /* reset state */
}
void wc_Sha224Free(Sha224* sha224)
{
if (sha224 == NULL)
return;
}
int wc_Sha224GetHash(Sha224* sha224, byte* hash)
{
int ret;
Sha224 tmpSha224;
if (sha224 == NULL || hash == NULL)
return BAD_FUNC_ARG;
ret = wc_Sha224Copy(sha224, &tmpSha224);
if (ret == 0) {
ret = wc_Sha224Final(&tmpSha224, hash);
}
return ret;
}
int wc_Sha224Copy(Sha224* src, Sha224* dst)
{
int ret = 0;
if (src == NULL || dst == NULL)
return BAD_FUNC_ARG;
XMEMCPY(dst, src, sizeof(Sha224));
return ret;
}
#endif /* WOLFSSL_SHA224 */
#endif /* !NO_SHA256 || WOLFSSL_SHA224 */
#endif /* WOLFSSL_ARMASM */

View File

@ -11693,6 +11693,7 @@ done:
int ed25519_test(void)
{
int ret;
WC_RNG rng;
#if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) &&\
defined(HAVE_ED25519_KEY_IMPORT)
@ -11701,7 +11702,7 @@ int ed25519_test(void)
byte exportSKey[ED25519_KEY_SIZE];
word32 exportPSz;
word32 exportSSz;
int i, ret;
int i;
word32 outlen;
#ifdef HAVE_ED25519_VERIFY
int verify;

View File

@ -90,7 +90,7 @@ WOLFSSL_LOCAL void fe_mul121666(fe,fe);
WOLFSSL_LOCAL void fe_cmov(fe,const fe, int);
WOLFSSL_LOCAL void fe_pow22523(fe,const fe);
#if defined(HAVE___UINT128_T)
#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL)
/* 64 type needed for SHA512 */
WOLFSSL_LOCAL uint64_t load_3(const unsigned char *in);
WOLFSSL_LOCAL uint64_t load_4(const unsigned char *in);