forked from wolfSSL/wolfssl
Merge pull request #7291 from dgarske/armasm_thumb_gcmsmall
Thumb2 AES GCM support for GCM_SMALL
This commit is contained in:
@ -16493,9 +16493,11 @@ extern void AES_CBC_decrypt(const unsigned char* in, unsigned char* out,
|
|||||||
unsigned long len, const unsigned char* ks, int nr, unsigned char* iv);
|
unsigned long len, const unsigned char* ks, int nr, unsigned char* iv);
|
||||||
extern void AES_CTR_encrypt(const unsigned char* in, unsigned char* out,
|
extern void AES_CTR_encrypt(const unsigned char* in, unsigned char* out,
|
||||||
unsigned long len, const unsigned char* ks, int nr, unsigned char* ctr);
|
unsigned long len, const unsigned char* ks, int nr, unsigned char* ctr);
|
||||||
|
#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
|
||||||
/* in pre-C2x C, constness conflicts for dimensioned arrays can't be resolved. */
|
/* in pre-C2x C, constness conflicts for dimensioned arrays can't be resolved. */
|
||||||
extern void GCM_gmult_len(byte* x, /* const */ byte m[32][AES_BLOCK_SIZE],
|
extern void GCM_gmult_len(byte* x, /* const */ byte m[32][AES_BLOCK_SIZE],
|
||||||
const unsigned char* data, unsigned long len);
|
const unsigned char* data, unsigned long len);
|
||||||
|
#endif
|
||||||
extern void AES_GCM_encrypt(const unsigned char* in, unsigned char* out,
|
extern void AES_GCM_encrypt(const unsigned char* in, unsigned char* out,
|
||||||
unsigned long len, const unsigned char* ks, int nr, unsigned char* ctr);
|
unsigned long len, const unsigned char* ks, int nr, unsigned char* ctr);
|
||||||
|
|
||||||
@ -16992,6 +16994,7 @@ static WC_INLINE void RIGHTSHIFTX(byte* x)
|
|||||||
x[0] ^= borrow;
|
x[0] ^= borrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
|
||||||
void GenerateM0(Gcm* gcm)
|
void GenerateM0(Gcm* gcm)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -17047,6 +17050,7 @@ void GenerateM0(Gcm* gcm)
|
|||||||
m32[3] = ByteReverseWord32(m32[3]);
|
m32[3] = ByteReverseWord32(m32[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* GCM_TABLE */
|
||||||
|
|
||||||
int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
|
int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
|
||||||
{
|
{
|
||||||
@ -17067,7 +17071,9 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
|
|||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
AES_ECB_encrypt(iv, aes->gcm.H, AES_BLOCK_SIZE,
|
AES_ECB_encrypt(iv, aes->gcm.H, AES_BLOCK_SIZE,
|
||||||
(const unsigned char*)aes->key, aes->rounds);
|
(const unsigned char*)aes->key, aes->rounds);
|
||||||
GenerateM0(&aes->gcm);
|
#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
|
||||||
|
GenerateM0(&aes->gcm);
|
||||||
|
#endif /* GCM_TABLE */
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -17101,6 +17107,44 @@ static WC_INLINE void FlattenSzInBits(byte* buf, word32 sz)
|
|||||||
buf[7] = sz & 0xff;
|
buf[7] = sz & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
|
||||||
|
/* GCM_gmult_len implementation in armv8-32-aes-asm or thumb2-aes-asm */
|
||||||
|
#define GCM_GMULT_LEN(aes, x, a, len) GCM_gmult_len(x, aes->gcm.M0, a, len)
|
||||||
|
#elif defined(GCM_SMALL)
|
||||||
|
static void GCM_gmult_len(byte* x, const byte* h,
|
||||||
|
const unsigned char* a, unsigned long len)
|
||||||
|
{
|
||||||
|
byte Z[AES_BLOCK_SIZE];
|
||||||
|
byte V[AES_BLOCK_SIZE];
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
while (len >= AES_BLOCK_SIZE) {
|
||||||
|
xorbuf(x, a, AES_BLOCK_SIZE);
|
||||||
|
|
||||||
|
XMEMSET(Z, 0, AES_BLOCK_SIZE);
|
||||||
|
XMEMCPY(V, x, AES_BLOCK_SIZE);
|
||||||
|
for (i = 0; i < AES_BLOCK_SIZE; i++) {
|
||||||
|
byte y = h[i];
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
if (y & 0x80) {
|
||||||
|
xorbuf(Z, V, AES_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
RIGHTSHIFTX(V);
|
||||||
|
y = y << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XMEMCPY(x, Z, AES_BLOCK_SIZE);
|
||||||
|
|
||||||
|
len -= AES_BLOCK_SIZE;
|
||||||
|
a += AES_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#define GCM_GMULT_LEN(aes, x, a, len) GCM_gmult_len(x, aes->gcm.H, a, len)
|
||||||
|
#else
|
||||||
|
#error ARMv8 AES only supports GCM_TABLE or GCM_TABLE_4BIT or GCM_SMALL
|
||||||
|
#endif /* GCM_TABLE */
|
||||||
|
|
||||||
static void gcm_ghash_arm32(Aes* aes, const byte* a, word32 aSz, const byte* c,
|
static void gcm_ghash_arm32(Aes* aes, const byte* a, word32 aSz, const byte* c,
|
||||||
word32 cSz, byte* s, word32 sSz)
|
word32 cSz, byte* s, word32 sSz)
|
||||||
{
|
{
|
||||||
@ -17119,13 +17163,13 @@ static void gcm_ghash_arm32(Aes* aes, const byte* a, word32 aSz, const byte* c,
|
|||||||
blocks = aSz / AES_BLOCK_SIZE;
|
blocks = aSz / AES_BLOCK_SIZE;
|
||||||
partial = aSz % AES_BLOCK_SIZE;
|
partial = aSz % AES_BLOCK_SIZE;
|
||||||
if (blocks > 0) {
|
if (blocks > 0) {
|
||||||
GCM_gmult_len(x, aes->gcm.M0, a, blocks * AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, a, blocks * AES_BLOCK_SIZE);
|
||||||
a += blocks * AES_BLOCK_SIZE;
|
a += blocks * AES_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
if (partial != 0) {
|
if (partial != 0) {
|
||||||
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
||||||
XMEMCPY(scratch, a, partial);
|
XMEMCPY(scratch, a, partial);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17134,20 +17178,20 @@ static void gcm_ghash_arm32(Aes* aes, const byte* a, word32 aSz, const byte* c,
|
|||||||
blocks = cSz / AES_BLOCK_SIZE;
|
blocks = cSz / AES_BLOCK_SIZE;
|
||||||
partial = cSz % AES_BLOCK_SIZE;
|
partial = cSz % AES_BLOCK_SIZE;
|
||||||
if (blocks > 0) {
|
if (blocks > 0) {
|
||||||
GCM_gmult_len(x, aes->gcm.M0, c, blocks * AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, c, blocks * AES_BLOCK_SIZE);
|
||||||
c += blocks * AES_BLOCK_SIZE;
|
c += blocks * AES_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
if (partial != 0) {
|
if (partial != 0) {
|
||||||
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
||||||
XMEMCPY(scratch, c, partial);
|
XMEMCPY(scratch, c, partial);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hash in the lengths of A and C in bits */
|
/* Hash in the lengths of A and C in bits */
|
||||||
FlattenSzInBits(&scratch[0], aSz);
|
FlattenSzInBits(&scratch[0], aSz);
|
||||||
FlattenSzInBits(&scratch[8], cSz);
|
FlattenSzInBits(&scratch[8], cSz);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
|
|
||||||
/* Copy the result into s. */
|
/* Copy the result into s. */
|
||||||
XMEMCPY(s, x, sSz);
|
XMEMCPY(s, x, sSz);
|
||||||
@ -17198,13 +17242,13 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
blocks = authInSz / AES_BLOCK_SIZE;
|
blocks = authInSz / AES_BLOCK_SIZE;
|
||||||
partial = authInSz % AES_BLOCK_SIZE;
|
partial = authInSz % AES_BLOCK_SIZE;
|
||||||
if (blocks > 0) {
|
if (blocks > 0) {
|
||||||
GCM_gmult_len(x, aes->gcm.M0, authIn, blocks * AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, authIn, blocks * AES_BLOCK_SIZE);
|
||||||
authIn += blocks * AES_BLOCK_SIZE;
|
authIn += blocks * AES_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
if (partial != 0) {
|
if (partial != 0) {
|
||||||
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
||||||
XMEMCPY(scratch, authIn, partial);
|
XMEMCPY(scratch, authIn, partial);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17214,7 +17258,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
if (blocks > 0) {
|
if (blocks > 0) {
|
||||||
AES_GCM_encrypt(in, out, blocks * AES_BLOCK_SIZE,
|
AES_GCM_encrypt(in, out, blocks * AES_BLOCK_SIZE,
|
||||||
(const unsigned char*)aes->key, aes->rounds, counter);
|
(const unsigned char*)aes->key, aes->rounds, counter);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, out, blocks * AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, out, blocks * AES_BLOCK_SIZE);
|
||||||
in += blocks * AES_BLOCK_SIZE;
|
in += blocks * AES_BLOCK_SIZE;
|
||||||
out += blocks * AES_BLOCK_SIZE;
|
out += blocks * AES_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
@ -17227,14 +17271,14 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
|
|
||||||
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
||||||
XMEMCPY(scratch, out, partial);
|
XMEMCPY(scratch, out, partial);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hash in the lengths of A and C in bits */
|
/* Hash in the lengths of A and C in bits */
|
||||||
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
||||||
FlattenSzInBits(&scratch[0], authInSz);
|
FlattenSzInBits(&scratch[0], authInSz);
|
||||||
FlattenSzInBits(&scratch[8], sz);
|
FlattenSzInBits(&scratch[8], sz);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
if (authTagSz > AES_BLOCK_SIZE) {
|
if (authTagSz > AES_BLOCK_SIZE) {
|
||||||
XMEMCPY(authTag, x, AES_BLOCK_SIZE);
|
XMEMCPY(authTag, x, AES_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
@ -17286,13 +17330,13 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
blocks = authInSz / AES_BLOCK_SIZE;
|
blocks = authInSz / AES_BLOCK_SIZE;
|
||||||
partial = authInSz % AES_BLOCK_SIZE;
|
partial = authInSz % AES_BLOCK_SIZE;
|
||||||
if (blocks > 0) {
|
if (blocks > 0) {
|
||||||
GCM_gmult_len(x, aes->gcm.M0, authIn, blocks * AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, authIn, blocks * AES_BLOCK_SIZE);
|
||||||
authIn += blocks * AES_BLOCK_SIZE;
|
authIn += blocks * AES_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
if (partial != 0) {
|
if (partial != 0) {
|
||||||
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
||||||
XMEMCPY(scratch, authIn, partial);
|
XMEMCPY(scratch, authIn, partial);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17300,7 +17344,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
partial = sz % AES_BLOCK_SIZE;
|
partial = sz % AES_BLOCK_SIZE;
|
||||||
/* do as many blocks as possible */
|
/* do as many blocks as possible */
|
||||||
if (blocks > 0) {
|
if (blocks > 0) {
|
||||||
GCM_gmult_len(x, aes->gcm.M0, in, blocks * AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, in, blocks * AES_BLOCK_SIZE);
|
||||||
|
|
||||||
AES_GCM_encrypt(in, out, blocks * AES_BLOCK_SIZE,
|
AES_GCM_encrypt(in, out, blocks * AES_BLOCK_SIZE,
|
||||||
(const unsigned char*)aes->key, aes->rounds, counter);
|
(const unsigned char*)aes->key, aes->rounds, counter);
|
||||||
@ -17310,7 +17354,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
if (partial != 0) {
|
if (partial != 0) {
|
||||||
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
||||||
XMEMCPY(scratch, in, partial);
|
XMEMCPY(scratch, in, partial);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
|
|
||||||
AES_GCM_encrypt(in, scratch, AES_BLOCK_SIZE,
|
AES_GCM_encrypt(in, scratch, AES_BLOCK_SIZE,
|
||||||
(const unsigned char*)aes->key, aes->rounds, counter);
|
(const unsigned char*)aes->key, aes->rounds, counter);
|
||||||
@ -17320,7 +17364,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
|
||||||
FlattenSzInBits(&scratch[0], authInSz);
|
FlattenSzInBits(&scratch[0], authInSz);
|
||||||
FlattenSzInBits(&scratch[8], sz);
|
FlattenSzInBits(&scratch[8], sz);
|
||||||
GCM_gmult_len(x, aes->gcm.M0, scratch, AES_BLOCK_SIZE);
|
GCM_GMULT_LEN(aes, x, scratch, AES_BLOCK_SIZE);
|
||||||
AES_ECB_encrypt(initialCounter, scratch, AES_BLOCK_SIZE,
|
AES_ECB_encrypt(initialCounter, scratch, AES_BLOCK_SIZE,
|
||||||
(const unsigned char*)aes->key, aes->rounds);
|
(const unsigned char*)aes->key, aes->rounds);
|
||||||
xorbuf(x, scratch, authTagSz);
|
xorbuf(x, scratch, authTagSz);
|
||||||
|
Reference in New Issue
Block a user