forked from wolfSSL/wolfssl
Merge branch 'master' into blake2
This commit is contained in:
@@ -1807,8 +1807,6 @@ void AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
||||
*/
|
||||
|
||||
enum {
|
||||
IMPLICIT_IV_SZ = 4,
|
||||
EXPLICIT_IV_SZ = 8,
|
||||
CTR_SZ = 4
|
||||
};
|
||||
|
||||
@@ -1834,36 +1832,6 @@ static INLINE void IncrementGcmCounter(byte* inOutCtr)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The explicit IV is set by the caller. A common practice is to treat it as
|
||||
* a sequence number seeded with a random number. The caller manages
|
||||
* incrementing the explicit IV when appropriate.
|
||||
*/
|
||||
|
||||
void AesGcmSetExpIV(Aes* aes, const byte* iv)
|
||||
{
|
||||
XMEMCPY((byte*)aes->reg + IMPLICIT_IV_SZ, iv, EXPLICIT_IV_SZ);
|
||||
}
|
||||
|
||||
|
||||
void AesGcmGetExpIV(Aes* aes, byte* iv)
|
||||
{
|
||||
XMEMCPY(iv, (byte*)aes->reg + IMPLICIT_IV_SZ, EXPLICIT_IV_SZ);
|
||||
}
|
||||
|
||||
|
||||
void AesGcmIncExpIV(Aes* aes)
|
||||
{
|
||||
int i;
|
||||
byte* iv = (byte*)aes->reg + IMPLICIT_IV_SZ;
|
||||
|
||||
for (i = EXPLICIT_IV_SZ - 1; i >= 0; i--) {
|
||||
if (++iv[i])
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(GCM_SMALL) || defined(GCM_TABLE)
|
||||
|
||||
static INLINE void FlattenSzInBits(byte* buf, word32 sz)
|
||||
@@ -1929,20 +1897,17 @@ static void GenerateM0(Aes* aes)
|
||||
#endif /* GCM_TABLE */
|
||||
|
||||
|
||||
void AesGcmSetKey(Aes* aes, const byte* key, word32 len,
|
||||
const byte* implicitIV)
|
||||
void AesGcmSetKey(Aes* aes, const byte* key, word32 len)
|
||||
{
|
||||
byte fullIV[AES_BLOCK_SIZE];
|
||||
byte iv[AES_BLOCK_SIZE];
|
||||
|
||||
if (!((len == 16) || (len == 24) || (len == 32)))
|
||||
return;
|
||||
|
||||
XMEMSET(fullIV, 0, AES_BLOCK_SIZE);
|
||||
XMEMCPY(fullIV, implicitIV, IMPLICIT_IV_SZ);
|
||||
AesSetKeyLocal(aes, key, len, fullIV, AES_ENCRYPTION);
|
||||
XMEMSET(iv, 0, AES_BLOCK_SIZE);
|
||||
AesSetKeyLocal(aes, key, len, iv, AES_ENCRYPTION);
|
||||
|
||||
XMEMSET(fullIV, 0, AES_BLOCK_SIZE);
|
||||
AesEncrypt(aes, fullIV, aes->H);
|
||||
AesEncrypt(aes, iv, aes->H);
|
||||
#ifdef GCM_TABLE
|
||||
GenerateM0(aes);
|
||||
#endif /* GCM_TABLE */
|
||||
@@ -2449,6 +2414,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz,
|
||||
|
||||
|
||||
void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
const byte* iv, word32 ivSz,
|
||||
byte* authTag, word32 authTagSz,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
@@ -2461,9 +2427,8 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
|
||||
CYASSL_ENTER("AesGcmEncrypt");
|
||||
|
||||
/* Initialize the counter with the MS 96 bits of IV, and the counter
|
||||
* portion set to "1". */
|
||||
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE);
|
||||
XMEMSET(ctr, 0, AES_BLOCK_SIZE);
|
||||
XMEMCPY(ctr, iv, ivSz);
|
||||
InitGcmCounter(ctr);
|
||||
|
||||
while (blocks--) {
|
||||
@@ -2489,6 +2454,7 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
|
||||
|
||||
int 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)
|
||||
{
|
||||
@@ -2501,9 +2467,8 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
|
||||
CYASSL_ENTER("AesGcmDecrypt");
|
||||
|
||||
/* Initialize the counter with the MS 96 bits of IV, and the counter
|
||||
* portion set to "1". */
|
||||
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE);
|
||||
XMEMSET(ctr, 0, AES_BLOCK_SIZE);
|
||||
XMEMCPY(ctr, iv, ivSz);
|
||||
InitGcmCounter(ctr);
|
||||
|
||||
/* Calculate the authTag again using the received auth data and the
|
||||
@@ -2541,6 +2506,224 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
|
||||
#endif /* HAVE_AESGCM */
|
||||
|
||||
#ifdef HAVE_AESCCM
|
||||
|
||||
void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
|
||||
{
|
||||
byte nonce[AES_BLOCK_SIZE];
|
||||
|
||||
if (!((keySz == 16) || (keySz == 24) || (keySz == 32)))
|
||||
return;
|
||||
|
||||
XMEMSET(nonce, 0, sizeof(nonce));
|
||||
AesSetKeyLocal(aes, key, keySz, nonce, AES_ENCRYPTION);
|
||||
}
|
||||
|
||||
|
||||
static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out)
|
||||
{
|
||||
/* process the bulk of the data */
|
||||
while (inSz >= AES_BLOCK_SIZE) {
|
||||
xorbuf(out, in, AES_BLOCK_SIZE);
|
||||
in += AES_BLOCK_SIZE;
|
||||
inSz -= AES_BLOCK_SIZE;
|
||||
|
||||
AesEncrypt(aes, out, out);
|
||||
}
|
||||
|
||||
/* process remainder of the data */
|
||||
if (inSz > 0) {
|
||||
xorbuf(out, in, inSz);
|
||||
AesEncrypt(aes, out, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out)
|
||||
{
|
||||
word32 authLenSz;
|
||||
word32 remainder;
|
||||
|
||||
/* encode the length in */
|
||||
if (inSz <= 0xFEFF) {
|
||||
authLenSz = 2;
|
||||
out[0] ^= ((inSz & 0xFF00) >> 8);
|
||||
out[1] ^= (inSz & 0x00FF);
|
||||
}
|
||||
else if (inSz <= 0xFFFFFFFF) {
|
||||
authLenSz = 6;
|
||||
out[0] ^= 0xFF; out[1] ^= 0xFE;
|
||||
out[2] ^= ((inSz & 0xFF000000) >> 24);
|
||||
out[3] ^= ((inSz & 0x00FF0000) >> 16);
|
||||
out[4] ^= ((inSz & 0x0000FF00) >> 8);
|
||||
out[5] ^= (inSz & 0x000000FF);
|
||||
}
|
||||
/* Note, the protocol handles auth data up to 2^64, but we are
|
||||
* using 32-bit sizes right now, so the bigger data isn't handled
|
||||
* else if (inSz <= 0xFFFFFFFFFFFFFFFF) {} */
|
||||
else
|
||||
return;
|
||||
|
||||
/* start fill out the rest of the first block */
|
||||
remainder = AES_BLOCK_SIZE - authLenSz;
|
||||
if (inSz >= remainder) {
|
||||
/* plenty of bulk data to fill the remainder of this block */
|
||||
xorbuf(out + authLenSz, in, remainder);
|
||||
inSz -= remainder;
|
||||
in += remainder;
|
||||
}
|
||||
else {
|
||||
/* not enough bulk data, copy what is available, and pad zero */
|
||||
xorbuf(out + authLenSz, in, inSz);
|
||||
inSz = 0;
|
||||
}
|
||||
AesEncrypt(aes, out, out);
|
||||
|
||||
if (inSz > 0)
|
||||
roll_x(aes, in, inSz, out);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void AesCcmCtrInc(byte* B, word32 lenSz)
|
||||
{
|
||||
word32 i;
|
||||
|
||||
for (i = 0; i < lenSz; i++) {
|
||||
if (++B[AES_BLOCK_SIZE - 1 - i] != 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
byte* authTag, word32 authTagSz,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
byte A[AES_BLOCK_SIZE];
|
||||
byte B[AES_BLOCK_SIZE];
|
||||
word32 i, lenSz;
|
||||
|
||||
XMEMCPY(B+1, nonce, nonceSz);
|
||||
lenSz = AES_BLOCK_SIZE - 1 - nonceSz;
|
||||
B[0] = (authInSz > 0 ? 64 : 0)
|
||||
+ (8 * ((authTagSz - 2) / 2))
|
||||
+ (lenSz - 1);
|
||||
for (i = 0; i < lenSz; i++)
|
||||
B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF;
|
||||
|
||||
AesEncrypt(aes, B, A);
|
||||
if (authInSz > 0)
|
||||
roll_auth(aes, authIn, authInSz, A);
|
||||
if (inSz > 0)
|
||||
roll_x(aes, in, inSz, A);
|
||||
XMEMCPY(authTag, A, authTagSz);
|
||||
|
||||
B[0] = (lenSz - 1);
|
||||
for (i = 0; i < lenSz; i++)
|
||||
B[AES_BLOCK_SIZE - 1 - i] = 0;
|
||||
AesEncrypt(aes, B, A);
|
||||
xorbuf(authTag, A, authTagSz);
|
||||
|
||||
B[15] = 1;
|
||||
while (inSz >= AES_BLOCK_SIZE) {
|
||||
AesEncrypt(aes, B, A);
|
||||
xorbuf(A, in, AES_BLOCK_SIZE);
|
||||
XMEMCPY(out, A, AES_BLOCK_SIZE);
|
||||
|
||||
AesCcmCtrInc(B, lenSz);
|
||||
inSz -= AES_BLOCK_SIZE;
|
||||
in += AES_BLOCK_SIZE;
|
||||
out += AES_BLOCK_SIZE;
|
||||
}
|
||||
if (inSz > 0) {
|
||||
AesEncrypt(aes, B, A);
|
||||
xorbuf(A, in, inSz);
|
||||
XMEMCPY(out, A, inSz);
|
||||
}
|
||||
|
||||
XMEMSET(A, 0, AES_BLOCK_SIZE);
|
||||
XMEMSET(B, 0, AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
|
||||
int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
const byte* authTag, word32 authTagSz,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
byte A[AES_BLOCK_SIZE];
|
||||
byte B[AES_BLOCK_SIZE];
|
||||
byte* o;
|
||||
word32 i, lenSz, oSz, result = 0;
|
||||
|
||||
o = out;
|
||||
oSz = inSz;
|
||||
XMEMCPY(B+1, nonce, nonceSz);
|
||||
lenSz = AES_BLOCK_SIZE - 1 - nonceSz;
|
||||
|
||||
B[0] = (lenSz - 1);
|
||||
for (i = 0; i < lenSz; i++)
|
||||
B[AES_BLOCK_SIZE - 1 - i] = 0;
|
||||
B[15] = 1;
|
||||
|
||||
while (oSz >= AES_BLOCK_SIZE) {
|
||||
AesEncrypt(aes, B, A);
|
||||
xorbuf(A, in, AES_BLOCK_SIZE);
|
||||
XMEMCPY(o, A, AES_BLOCK_SIZE);
|
||||
|
||||
AesCcmCtrInc(B, lenSz);
|
||||
oSz -= AES_BLOCK_SIZE;
|
||||
in += AES_BLOCK_SIZE;
|
||||
o += AES_BLOCK_SIZE;
|
||||
}
|
||||
if (inSz > 0) {
|
||||
AesEncrypt(aes, B, A);
|
||||
xorbuf(A, in, oSz);
|
||||
XMEMCPY(o, A, oSz);
|
||||
}
|
||||
|
||||
for (i = 0; i < lenSz; i++)
|
||||
B[AES_BLOCK_SIZE - 1 - i] = 0;
|
||||
AesEncrypt(aes, B, A);
|
||||
|
||||
o = out;
|
||||
oSz = inSz;
|
||||
|
||||
B[0] = (authInSz > 0 ? 64 : 0)
|
||||
+ (8 * ((authTagSz - 2) / 2))
|
||||
+ (lenSz - 1);
|
||||
for (i = 0; i < lenSz; i++)
|
||||
B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF;
|
||||
|
||||
AesEncrypt(aes, B, A);
|
||||
if (authInSz > 0)
|
||||
roll_auth(aes, authIn, authInSz, A);
|
||||
if (inSz > 0)
|
||||
roll_x(aes, o, oSz, A);
|
||||
|
||||
B[0] = (lenSz - 1);
|
||||
for (i = 0; i < lenSz; i++)
|
||||
B[AES_BLOCK_SIZE - 1 - i] = 0;
|
||||
AesEncrypt(aes, B, B);
|
||||
xorbuf(A, B, authTagSz);
|
||||
|
||||
if (XMEMCMP(A, authTag, authTagSz) != 0) {
|
||||
/* If the authTag check fails, don't keep the decrypted data.
|
||||
* Unfortunately, you need the decrypted data to calculate the
|
||||
* check value. */
|
||||
XMEMSET(out, 0, inSz);
|
||||
result = AES_CCM_AUTH_E;
|
||||
}
|
||||
|
||||
XMEMSET(A, 0, AES_BLOCK_SIZE);
|
||||
XMEMSET(B, 0, AES_BLOCK_SIZE);
|
||||
o = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* STM32F2_CRYPTO */
|
||||
|
||||
int AesSetIV(Aes* aes, const byte* iv)
|
||||
|
||||
@@ -1815,7 +1815,7 @@ static word32 BytePrecision(word32 value)
|
||||
{
|
||||
word32 i;
|
||||
for (i = sizeof(value); i; --i)
|
||||
if (value >> (i - 1) * 8)
|
||||
if (value >> ((i - 1) * BIT_SIZE))
|
||||
break;
|
||||
|
||||
return i;
|
||||
@@ -1832,7 +1832,7 @@ static word32 SetLength(word32 length, byte* output)
|
||||
output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
|
||||
|
||||
for (j = BytePrecision(length); j; --j) {
|
||||
output[i] = (byte)(length >> (j - 1) * 8);
|
||||
output[i] = (byte)(length >> ((j - 1) * BIT_SIZE));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,7 +663,7 @@ void Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
|
||||
void Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
|
||||
{
|
||||
word32 blocks = sz / DES_BLOCK_SIZE;
|
||||
byte hold[16];
|
||||
byte hold[DES_BLOCK_SIZE];
|
||||
|
||||
while (blocks--) {
|
||||
XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
|
||||
|
||||
@@ -273,6 +273,10 @@ void CTaoCryptErrorString(int error, char* buffer)
|
||||
XSTRNCPY(buffer, "AES-GCM Authentication check fail", max);
|
||||
break;
|
||||
|
||||
case AES_CCM_AUTH_E:
|
||||
XSTRNCPY(buffer, "AES-CCM Authentication check fail", max);
|
||||
break;
|
||||
|
||||
default:
|
||||
XSTRNCPY(buffer, "unknown error number", max);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user