Added AES-CCM encrypt/decrypt, test fuction, benchmark function.

This commit is contained in:
John Safranek 2013-01-10 16:38:52 -08:00
parent e85caee845
commit 05165bc09e
6 changed files with 229 additions and 42 deletions

View File

@ -55,6 +55,7 @@ void bench_hc128(void);
void bench_rabbit(void);
void bench_aes(int);
void bench_aesgcm(void);
void bench_aesccm(void);
void bench_md5(void);
void bench_sha(void);
@ -85,6 +86,9 @@ int main(int argc, char** argv)
#ifdef HAVE_AESGCM
bench_aesgcm();
#endif
#ifdef HAVE_AESCCM
bench_aesccm();
#endif
#ifndef NO_RC4
bench_arc4();
#endif
@ -211,6 +215,29 @@ void bench_aesgcm(void)
#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
void bench_des(void)
{

View File

@ -2546,64 +2546,220 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz,
const byte* implicitIV, word32 ivSz)
{
(void)aes;
(void)key;
(void)keySz;
(void)implicitIV;
(void)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));
}
void AesCcmSetExpIV(Aes* aes, const byte* iv, word32 ivSz)
static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out)
{
(void)aes;
(void)iv;
(void)ivSz;
/* 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);
}
}
void AesCcmGetExpIV(Aes* aes, byte* iv, word32 ivSz)
static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out)
{
(void)aes;
(void)iv;
(void)ivSz;
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);
}
void AesCcmIncExpIV(Aes* aes)
static INLINE void AesCcmCtrInc(byte* B, word32 lenSz)
{
(void)aes;
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 sz,
void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
(void)aes;
(void)out;
(void)in;
(void)sz;
(void)authTag;
(void)authTagSz;
(void)authIn;
(void)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 sz,
int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
(void)aes;
(void)out;
(void)in;
(void)sz;
(void)authTag;
(void)authTagSz;
(void)authIn;
(void)authInSz;
return 0;
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

View File

@ -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);

View File

@ -1615,13 +1615,12 @@ int aesccm_test(void)
{
0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0
0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84
};
const byte t[] =
{
0x3a, 0x2e, 0x46, 0xc8, 0xec, 0x33, 0xa5, 0x48
0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0
};
byte t2[sizeof(t)];

View File

@ -76,6 +76,9 @@ typedef struct Aes {
ALIGN16 byte M0[256][AES_BLOCK_SIZE];
#endif /* GCM_TABLE */
#endif /* HAVE_AESGCM */
#ifdef HAVE_AESCCM
word32 lenSz;
#endif
#ifdef CYASSL_AESNI
byte use_aesni;
#endif /* CYASSL_AESNI */
@ -108,13 +111,10 @@ CYASSL_API int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
#ifdef HAVE_AESCCM
CYASSL_API void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz,
const byte* implicitIV, word32 ivSz);
CYASSL_API void AesCcmSetExpIV(Aes* aes, const byte* iv, word32 ivSz);
CYASSL_API void AesCcmGetExpIV(Aes* aes, byte* iv, word32 ivSz);
CYASSL_API void AesCcmIncExpIV(Aes* aes);
CYASSL_API void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
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 sz,
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 */

View File

@ -99,6 +99,7 @@ enum {
ALT_NAME_E = -177, /* alt name size problem, too big */
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 */
};