forked from wolfSSL/wolfssl
Merge branch 'ccm'
This commit is contained in:
@ -55,6 +55,7 @@ void bench_hc128(void);
|
|||||||
void bench_rabbit(void);
|
void bench_rabbit(void);
|
||||||
void bench_aes(int);
|
void bench_aes(int);
|
||||||
void bench_aesgcm(void);
|
void bench_aesgcm(void);
|
||||||
|
void bench_aesccm(void);
|
||||||
|
|
||||||
void bench_md5(void);
|
void bench_md5(void);
|
||||||
void bench_sha(void);
|
void bench_sha(void);
|
||||||
@ -85,6 +86,9 @@ int main(int argc, char** argv)
|
|||||||
#ifdef HAVE_AESGCM
|
#ifdef HAVE_AESGCM
|
||||||
bench_aesgcm();
|
bench_aesgcm();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_AESCCM
|
||||||
|
bench_aesccm();
|
||||||
|
#endif
|
||||||
#ifndef NO_RC4
|
#ifndef NO_RC4
|
||||||
bench_arc4();
|
bench_arc4();
|
||||||
#endif
|
#endif
|
||||||
@ -211,6 +215,29 @@ void bench_aesgcm(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_AESCCM
|
||||||
|
void bench_aesccm(void)
|
||||||
|
{
|
||||||
|
Aes enc;
|
||||||
|
double start, total, persec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
AesCcmSetKey(&enc, key, 16, iv, 12);
|
||||||
|
start = current_time();
|
||||||
|
|
||||||
|
for(i = 0; i < megs; i++)
|
||||||
|
AesCcmEncrypt(&enc, cipher, plain, sizeof(plain),
|
||||||
|
tag, 16, additional, 13);
|
||||||
|
|
||||||
|
total = current_time() - start;
|
||||||
|
|
||||||
|
persec = 1 / total * megs;
|
||||||
|
printf("AES-CCM %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total,
|
||||||
|
persec);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_DES3
|
#ifndef NO_DES3
|
||||||
void bench_des(void)
|
void bench_des(void)
|
||||||
{
|
{
|
||||||
|
@ -2541,6 +2541,229 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
|
|
||||||
#endif /* HAVE_AESGCM */
|
#endif /* HAVE_AESGCM */
|
||||||
|
|
||||||
|
#ifdef HAVE_AESCCM
|
||||||
|
|
||||||
|
void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz,
|
||||||
|
const byte* implicitIV, word32 ivSz)
|
||||||
|
{
|
||||||
|
byte fullIV[AES_BLOCK_SIZE];
|
||||||
|
|
||||||
|
if (!((keySz == 16) || (keySz == 24) || (keySz == 32)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ivSz > AES_BLOCK_SIZE - 2) {
|
||||||
|
CYASSL_MSG("AES-CCM IV is too long");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMSET(fullIV, 0, sizeof(fullIV));
|
||||||
|
XMEMCPY(fullIV + 1, implicitIV, ivSz);
|
||||||
|
|
||||||
|
AesSetKeyLocal(aes, key, keySz, fullIV, AES_ENCRYPTION);
|
||||||
|
aes->lenSz = AES_BLOCK_SIZE - 1 - ivSz;
|
||||||
|
|
||||||
|
XMEMSET(fullIV, 0, sizeof(fullIV));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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,
|
||||||
|
byte* authTag, word32 authTagSz,
|
||||||
|
const byte* authIn, word32 authInSz)
|
||||||
|
{
|
||||||
|
byte A[AES_BLOCK_SIZE];
|
||||||
|
byte B[AES_BLOCK_SIZE];
|
||||||
|
word32 i;
|
||||||
|
|
||||||
|
XMEMCPY(B, aes->reg, AES_BLOCK_SIZE);
|
||||||
|
B[0] = (authInSz > 0 ? 64 : 0)
|
||||||
|
+ (8 * ((authTagSz - 2) / 2))
|
||||||
|
+ (aes->lenSz - 1);
|
||||||
|
for (i = 0; i < aes->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] = (aes->lenSz - 1);
|
||||||
|
for (i = 0; i < aes->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, aes->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* authTag, word32 authTagSz,
|
||||||
|
const byte* authIn, word32 authInSz)
|
||||||
|
{
|
||||||
|
byte A[AES_BLOCK_SIZE];
|
||||||
|
byte B[AES_BLOCK_SIZE];
|
||||||
|
byte* o;
|
||||||
|
word32 i, oSz, result = 0;
|
||||||
|
|
||||||
|
o = out;
|
||||||
|
oSz = inSz;
|
||||||
|
XMEMCPY(B, aes->reg, AES_BLOCK_SIZE);
|
||||||
|
B[0] = (aes->lenSz - 1);
|
||||||
|
for (i = 0; i < aes->lenSz - 1; 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, aes->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 < aes->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))
|
||||||
|
+ (aes->lenSz - 1);
|
||||||
|
for (i = 0; i < aes->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] = (aes->lenSz - 1);
|
||||||
|
for (i = 0; i < aes->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 */
|
#endif /* STM32F2_CRYPTO */
|
||||||
|
|
||||||
int AesSetIV(Aes* aes, const byte* iv)
|
int AesSetIV(Aes* aes, const byte* iv)
|
||||||
|
@ -273,6 +273,10 @@ void CTaoCryptErrorString(int error, char* buffer)
|
|||||||
XSTRNCPY(buffer, "AES-GCM Authentication check fail", max);
|
XSTRNCPY(buffer, "AES-GCM Authentication check fail", max);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AES_CCM_AUTH_E:
|
||||||
|
XSTRNCPY(buffer, "AES-CCM Authentication check fail", max);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
XSTRNCPY(buffer, "unknown error number", max);
|
XSTRNCPY(buffer, "unknown error number", max);
|
||||||
|
|
||||||
|
@ -112,6 +112,7 @@ int des_test(void);
|
|||||||
int des3_test(void);
|
int des3_test(void);
|
||||||
int aes_test(void);
|
int aes_test(void);
|
||||||
int aesgcm_test(void);
|
int aesgcm_test(void);
|
||||||
|
int aesccm_test(void);
|
||||||
int rsa_test(void);
|
int rsa_test(void);
|
||||||
int dh_test(void);
|
int dh_test(void);
|
||||||
int dsa_test(void);
|
int dsa_test(void);
|
||||||
@ -292,6 +293,13 @@ void ctaocrypt_test(void* args)
|
|||||||
else
|
else
|
||||||
printf( "AES-GCM test passed!\n");
|
printf( "AES-GCM test passed!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_AESCCM
|
||||||
|
if ( (ret = aesccm_test()) )
|
||||||
|
err_sys("AES-CCM test failed!\n", ret);
|
||||||
|
else
|
||||||
|
printf( "AES-CCM test passed!\n");
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( (ret = random_test()) )
|
if ( (ret = random_test()) )
|
||||||
@ -1580,6 +1588,79 @@ int aesgcm_test(void)
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_AESGCM */
|
#endif /* HAVE_AESGCM */
|
||||||
|
|
||||||
|
#ifdef HAVE_AESCCM
|
||||||
|
int aesccm_test(void)
|
||||||
|
{
|
||||||
|
Aes enc;
|
||||||
|
|
||||||
|
/* key */
|
||||||
|
const byte k[] =
|
||||||
|
{
|
||||||
|
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||||
|
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
|
||||||
|
};
|
||||||
|
|
||||||
|
/* nonce */
|
||||||
|
const byte iv[] =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0,
|
||||||
|
0xa1, 0xa2, 0xa3, 0xa4, 0xa5
|
||||||
|
};
|
||||||
|
|
||||||
|
/* plaintext */
|
||||||
|
const byte p[] =
|
||||||
|
{
|
||||||
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||||
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
|
||||||
|
};
|
||||||
|
|
||||||
|
const byte a[] =
|
||||||
|
{
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
|
||||||
|
};
|
||||||
|
|
||||||
|
const byte c[] =
|
||||||
|
{
|
||||||
|
0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
|
||||||
|
0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
|
||||||
|
0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84
|
||||||
|
};
|
||||||
|
|
||||||
|
const byte t[] =
|
||||||
|
{
|
||||||
|
0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0
|
||||||
|
};
|
||||||
|
|
||||||
|
byte t2[sizeof(t)];
|
||||||
|
byte p2[sizeof(p)];
|
||||||
|
byte c2[sizeof(c)];
|
||||||
|
|
||||||
|
int result;
|
||||||
|
|
||||||
|
memset(t2, 0, sizeof(t2));
|
||||||
|
memset(c2, 0, sizeof(c2));
|
||||||
|
memset(p2, 0, sizeof(p2));
|
||||||
|
|
||||||
|
AesCcmSetKey(&enc, k, sizeof(k), iv, sizeof(iv));
|
||||||
|
/* AES-CCM encrypt and decrypt both use AES encrypt internally */
|
||||||
|
AesCcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a));
|
||||||
|
if (memcmp(c, c2, sizeof(c2)))
|
||||||
|
return -107;
|
||||||
|
if (memcmp(t, t2, sizeof(t2)))
|
||||||
|
return -108;
|
||||||
|
|
||||||
|
result = AesCcmDecrypt(&enc,
|
||||||
|
p2, c2, sizeof(p2), t2, sizeof(t2), a, sizeof(a));
|
||||||
|
if (result != 0)
|
||||||
|
return -109;
|
||||||
|
if (memcmp(p, p2, sizeof(p2)))
|
||||||
|
return -110;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_AESCCM */
|
||||||
|
|
||||||
|
|
||||||
#endif /* NO_AES */
|
#endif /* NO_AES */
|
||||||
|
|
||||||
|
@ -76,6 +76,9 @@ typedef struct Aes {
|
|||||||
ALIGN16 byte M0[256][AES_BLOCK_SIZE];
|
ALIGN16 byte M0[256][AES_BLOCK_SIZE];
|
||||||
#endif /* GCM_TABLE */
|
#endif /* GCM_TABLE */
|
||||||
#endif /* HAVE_AESGCM */
|
#endif /* HAVE_AESGCM */
|
||||||
|
#ifdef HAVE_AESCCM
|
||||||
|
word32 lenSz;
|
||||||
|
#endif
|
||||||
#ifdef CYASSL_AESNI
|
#ifdef CYASSL_AESNI
|
||||||
byte use_aesni;
|
byte use_aesni;
|
||||||
#endif /* CYASSL_AESNI */
|
#endif /* CYASSL_AESNI */
|
||||||
@ -105,6 +108,16 @@ CYASSL_API int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||||||
const byte* authTag, word32 authTagSz,
|
const byte* authTag, word32 authTagSz,
|
||||||
const byte* authIn, word32 authInSz);
|
const byte* authIn, word32 authInSz);
|
||||||
#endif /* HAVE_AESGCM */
|
#endif /* HAVE_AESGCM */
|
||||||
|
#ifdef HAVE_AESCCM
|
||||||
|
CYASSL_API void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz,
|
||||||
|
const byte* implicitIV, word32 ivSz);
|
||||||
|
CYASSL_API void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||||
|
byte* authTag, word32 authTagSz,
|
||||||
|
const byte* authIn, word32 authInSz);
|
||||||
|
CYASSL_API int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||||
|
const byte* authTag, word32 authTagSz,
|
||||||
|
const byte* authIn, word32 authInSz);
|
||||||
|
#endif /* HAVE_AESCCM */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -99,6 +99,7 @@ enum {
|
|||||||
ALT_NAME_E = -177, /* alt name size problem, too big */
|
ALT_NAME_E = -177, /* alt name size problem, too big */
|
||||||
|
|
||||||
AES_GCM_AUTH_E = -180, /* AES-GCM Authentication check failure */
|
AES_GCM_AUTH_E = -180, /* AES-GCM Authentication check failure */
|
||||||
|
AES_CCM_AUTH_E = -181, /* AES-CCM Authentication check failure */
|
||||||
|
|
||||||
MIN_CODE_E = -200 /* errors -101 - -199 */
|
MIN_CODE_E = -200 /* errors -101 - -199 */
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user