Thumb2 AES GCM support for GCM_SMALL. ZD 17225

This commit is contained in:
David Garske
2024-01-09 15:45:36 -08:00
parent 6500444b26
commit 7c836c8371

View File

@ -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);
extern void AES_CTR_encrypt(const unsigned char* in, unsigned char* out,
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. */
extern void GCM_gmult_len(byte* x, /* const */ byte m[32][AES_BLOCK_SIZE],
const unsigned char* data, unsigned long len);
#endif
extern void AES_GCM_encrypt(const unsigned char* in, unsigned char* out,
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;
}
#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
void GenerateM0(Gcm* gcm)
{
int i;
@ -17047,6 +17050,7 @@ void GenerateM0(Gcm* gcm)
m32[3] = ByteReverseWord32(m32[3]);
}
}
#endif /* GCM_TABLE */
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) {
AES_ECB_encrypt(iv, aes->gcm.H, AES_BLOCK_SIZE,
(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;
@ -17101,6 +17107,44 @@ static WC_INLINE void FlattenSzInBits(byte* buf, word32 sz)
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,
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;
partial = aSz % AES_BLOCK_SIZE;
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;
}
if (partial != 0) {
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
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;
partial = cSz % AES_BLOCK_SIZE;
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;
}
if (partial != 0) {
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
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 */
FlattenSzInBits(&scratch[0], aSz);
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. */
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;
partial = authInSz % AES_BLOCK_SIZE;
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;
}
if (partial != 0) {
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
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) {
AES_GCM_encrypt(in, out, blocks * AES_BLOCK_SIZE,
(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;
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);
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 */
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
FlattenSzInBits(&scratch[0], authInSz);
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) {
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;
partial = authInSz % AES_BLOCK_SIZE;
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;
}
if (partial != 0) {
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
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;
/* do as many blocks as possible */
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,
(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) {
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
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,
(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);
FlattenSzInBits(&scratch[0], authInSz);
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,
(const unsigned char*)aes->key, aes->rounds);
xorbuf(x, scratch, authTagSz);