Merge branch 'master' of github.com:cyassl/cyassl

This commit is contained in:
toddouska 2012-07-27 12:32:42 -07:00
commit e2eb1b78cc
13 changed files with 1615 additions and 262 deletions

View File

@ -296,9 +296,27 @@ AC_ARG_ENABLE(aesgcm,
[ ENABLED_AESGCM=no ]
)
if test "$ENABLED_AESGCM" = "word32"
then
AM_CFLAGS="$AM_CFLAGS -DGCM_WORD32"
ENABLED_AESGCM=yes
fi
if test "$ENABLED_AESGCM" = "small"
then
AM_CFLAGS="$AM_CFLAGS -DGCM_SMALL"
ENABLED_AESGCM=yes
fi
if test "$ENABLED_AESGCM" = "table"
then
AM_CFLAGS="$AM_CFLAGS -DGCM_TABLE"
ENABLED_AESGCM=yes
fi
if test "$ENABLED_AESGCM" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM"
AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM -DCYASSL_SHA384 -DCYASSL_SHA512"
fi
AM_CONDITIONAL([BUILD_AESGCM], [test "x$ENABLED_AESGCM" = "xyes"])
@ -355,6 +373,11 @@ then
ENABLED_SHA512="yes"
fi
if test "$ENABLED_AESGCM" = "yes"
then
ENABLED_SHA512="yes"
fi
AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"])

View File

@ -54,6 +54,7 @@ void bench_arc4();
void bench_hc128();
void bench_rabbit();
void bench_aes(int);
void bench_aesgcm();
void bench_md5();
void bench_sha();
@ -78,6 +79,9 @@ int main(int argc, char** argv)
#ifndef NO_AES
bench_aes(0);
bench_aes(1);
#endif
#ifdef HAVE_AESGCM
bench_aesgcm();
#endif
bench_arc4();
#ifdef HAVE_HC128
@ -171,6 +175,34 @@ void bench_aes(int show)
#endif
byte additional[13];
byte tag[16];
#ifdef HAVE_AESGCM
void bench_aesgcm()
{
Aes enc;
double start, total, persec;
int i;
AesGcmSetKey(&enc, key, 16);
AesSetIV(&enc, iv);
start = current_time();
for(i = 0; i < megs; i++)
AesGcmEncrypt(&enc, cipher, plain, sizeof(plain),
tag, 16, additional, 13);
total = current_time() - start;
persec = 1 / total * megs;
printf("AES-GCM %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total,
persec);
}
#endif
#ifndef NO_DES3
void bench_des()
{

View File

@ -1428,29 +1428,92 @@ static INLINE void IncrementGcmCounter(byte* inOutCtr)
}
static void RIGHTSHIFT(byte* x)
#if defined(GCM_SMALL) || defined(GCM_TABLE)
static INLINE void FlattenSzInBits(byte* buf, word32 sz)
{
/* Multiply the sz by 8 */
word32 szHi = (sz >> (8*sizeof(sz) - 3));
sz <<= 3;
/* copy over the words of the sz into the destination buffer */
buf[0] = (szHi >> 24) & 0xff;
buf[1] = (szHi >> 16) & 0xff;
buf[2] = (szHi >> 8) & 0xff;
buf[3] = szHi & 0xff;
buf[4] = (sz >> 24) & 0xff;
buf[5] = (sz >> 16) & 0xff;
buf[6] = (sz >> 8) & 0xff;
buf[7] = sz & 0xff;
}
static INLINE void RIGHTSHIFTX(byte* x)
{
int i;
int carryOut = 0;
int carryIn = 0;
int borrow = x[15] & 0x01;
for (i = 0; i < AES_BLOCK_SIZE; i++) {
carryOut = x[i] & 0x01;
x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0);
carryIn = carryOut;
}
if (borrow) x[0] ^= 0xE1;
}
#endif /* defined(GCM_SMALL) || defined(GCM_TABLE) */
#ifdef GCM_TABLE
static void GenerateM0(Aes* aes)
{
int i, j;
byte (*m)[AES_BLOCK_SIZE] = aes->M0;
XMEMCPY(m[128], aes->H, AES_BLOCK_SIZE);
for (i = 64; i > 0; i /= 2) {
XMEMCPY(m[i], m[i*2], AES_BLOCK_SIZE);
RIGHTSHIFTX(m[i]);
}
for (i = 2; i < 256; i *= 2) {
for (j = 1; j < i; j++) {
XMEMCPY(m[i+j], m[i], AES_BLOCK_SIZE);
xorbuf(m[i+j], m[j], AES_BLOCK_SIZE);
}
}
XMEMSET(m[0], 0, AES_BLOCK_SIZE);
}
#endif /* GCM_TABLE */
void AesGcmSetKey(Aes* aes, const byte* key, word32 len)
{
byte iv[AES_BLOCK_SIZE];
XMEMSET(iv, 0, AES_BLOCK_SIZE);
AesSetKey(aes, key, len, iv, AES_ENCRYPTION);
AesEncrypt(aes, iv, aes->H);
#ifdef GCM_TABLE
GenerateM0(aes);
#endif /* GCM_TABLE */
}
#if defined(GCM_SMALL)
static void GMULT(byte* X, byte* Y)
{
byte R[AES_BLOCK_SIZE];
byte Z[AES_BLOCK_SIZE];
byte V[AES_BLOCK_SIZE];
int i, j;
XMEMSET(R, 0, AES_BLOCK_SIZE);
R[0] = 0xE1;
XMEMSET(Z, 0, AES_BLOCK_SIZE);
XMEMCPY(V, X, AES_BLOCK_SIZE);
for (i = 0; i < AES_BLOCK_SIZE; i++)
@ -1462,12 +1525,7 @@ static void GMULT(byte* X, byte* Y)
xorbuf(Z, V, AES_BLOCK_SIZE);
}
if (V[15] & 0x01) {
RIGHTSHIFT(V);
xorbuf(V, R, AES_BLOCK_SIZE);
} else {
RIGHTSHIFT(V);
}
RIGHTSHIFTX(V);
y = y << 1;
}
}
@ -1475,11 +1533,13 @@ static void GMULT(byte* X, byte* Y)
}
static void GHASH(byte* h, const byte* a, word32 aSz,
static void GHASH(Aes* aes, const byte* a, word32 aSz,
const byte* c, word32 cSz, byte* s, word32 sSz)
{
byte x[AES_BLOCK_SIZE];
byte scratch[AES_BLOCK_SIZE];
word32 blocks, partial;
byte* h = aes->H;
XMEMSET(x, 0, AES_BLOCK_SIZE);
@ -1493,7 +1553,6 @@ static void GHASH(byte* h, const byte* a, word32 aSz,
a += AES_BLOCK_SIZE;
}
if (partial != 0) {
byte scratch[AES_BLOCK_SIZE];
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
XMEMCPY(scratch, a, partial);
xorbuf(x, scratch, AES_BLOCK_SIZE);
@ -1511,7 +1570,6 @@ static void GHASH(byte* h, const byte* a, word32 aSz,
c += AES_BLOCK_SIZE;
}
if (partial != 0) {
byte scratch[AES_BLOCK_SIZE];
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
XMEMCPY(scratch, c, partial);
xorbuf(x, scratch, AES_BLOCK_SIZE);
@ -1519,27 +1577,433 @@ static void GHASH(byte* h, const byte* a, word32 aSz,
}
}
/* Hash in the lengths in bits of A and C */
{
byte len[AES_BLOCK_SIZE];
XMEMSET(len, 0, AES_BLOCK_SIZE);
len[3] = aSz >> 29;
len[4] = aSz >> 21;
len[5] = aSz >> 13;
len[6] = aSz >> 5;
len[7] = aSz << 3;
/* Hash in the lengths of A and C in bits */
FlattenSzInBits(&scratch[0], aSz);
FlattenSzInBits(&scratch[8], cSz);
xorbuf(x, scratch, AES_BLOCK_SIZE);
GMULT(x, h);
len[11] = cSz >> 29;
len[12] = cSz >> 21;
len[13] = cSz >> 13;
len[14] = cSz >> 5;
len[15] = cSz << 3;
xorbuf(x, len, AES_BLOCK_SIZE);
GMULT(x, h);
}
/* Copy the result into s. */
XMEMCPY(s, x, sSz);
}
/* end GCM_SMALL */
#elif defined(GCM_TABLE)
static const byte R[256][2] = {
{0x00, 0x00}, {0x01, 0xc2}, {0x03, 0x84}, {0x02, 0x46},
{0x07, 0x08}, {0x06, 0xca}, {0x04, 0x8c}, {0x05, 0x4e},
{0x0e, 0x10}, {0x0f, 0xd2}, {0x0d, 0x94}, {0x0c, 0x56},
{0x09, 0x18}, {0x08, 0xda}, {0x0a, 0x9c}, {0x0b, 0x5e},
{0x1c, 0x20}, {0x1d, 0xe2}, {0x1f, 0xa4}, {0x1e, 0x66},
{0x1b, 0x28}, {0x1a, 0xea}, {0x18, 0xac}, {0x19, 0x6e},
{0x12, 0x30}, {0x13, 0xf2}, {0x11, 0xb4}, {0x10, 0x76},
{0x15, 0x38}, {0x14, 0xfa}, {0x16, 0xbc}, {0x17, 0x7e},
{0x38, 0x40}, {0x39, 0x82}, {0x3b, 0xc4}, {0x3a, 0x06},
{0x3f, 0x48}, {0x3e, 0x8a}, {0x3c, 0xcc}, {0x3d, 0x0e},
{0x36, 0x50}, {0x37, 0x92}, {0x35, 0xd4}, {0x34, 0x16},
{0x31, 0x58}, {0x30, 0x9a}, {0x32, 0xdc}, {0x33, 0x1e},
{0x24, 0x60}, {0x25, 0xa2}, {0x27, 0xe4}, {0x26, 0x26},
{0x23, 0x68}, {0x22, 0xaa}, {0x20, 0xec}, {0x21, 0x2e},
{0x2a, 0x70}, {0x2b, 0xb2}, {0x29, 0xf4}, {0x28, 0x36},
{0x2d, 0x78}, {0x2c, 0xba}, {0x2e, 0xfc}, {0x2f, 0x3e},
{0x70, 0x80}, {0x71, 0x42}, {0x73, 0x04}, {0x72, 0xc6},
{0x77, 0x88}, {0x76, 0x4a}, {0x74, 0x0c}, {0x75, 0xce},
{0x7e, 0x90}, {0x7f, 0x52}, {0x7d, 0x14}, {0x7c, 0xd6},
{0x79, 0x98}, {0x78, 0x5a}, {0x7a, 0x1c}, {0x7b, 0xde},
{0x6c, 0xa0}, {0x6d, 0x62}, {0x6f, 0x24}, {0x6e, 0xe6},
{0x6b, 0xa8}, {0x6a, 0x6a}, {0x68, 0x2c}, {0x69, 0xee},
{0x62, 0xb0}, {0x63, 0x72}, {0x61, 0x34}, {0x60, 0xf6},
{0x65, 0xb8}, {0x64, 0x7a}, {0x66, 0x3c}, {0x67, 0xfe},
{0x48, 0xc0}, {0x49, 0x02}, {0x4b, 0x44}, {0x4a, 0x86},
{0x4f, 0xc8}, {0x4e, 0x0a}, {0x4c, 0x4c}, {0x4d, 0x8e},
{0x46, 0xd0}, {0x47, 0x12}, {0x45, 0x54}, {0x44, 0x96},
{0x41, 0xd8}, {0x40, 0x1a}, {0x42, 0x5c}, {0x43, 0x9e},
{0x54, 0xe0}, {0x55, 0x22}, {0x57, 0x64}, {0x56, 0xa6},
{0x53, 0xe8}, {0x52, 0x2a}, {0x50, 0x6c}, {0x51, 0xae},
{0x5a, 0xf0}, {0x5b, 0x32}, {0x59, 0x74}, {0x58, 0xb6},
{0x5d, 0xf8}, {0x5c, 0x3a}, {0x5e, 0x7c}, {0x5f, 0xbe},
{0xe1, 0x00}, {0xe0, 0xc2}, {0xe2, 0x84}, {0xe3, 0x46},
{0xe6, 0x08}, {0xe7, 0xca}, {0xe5, 0x8c}, {0xe4, 0x4e},
{0xef, 0x10}, {0xee, 0xd2}, {0xec, 0x94}, {0xed, 0x56},
{0xe8, 0x18}, {0xe9, 0xda}, {0xeb, 0x9c}, {0xea, 0x5e},
{0xfd, 0x20}, {0xfc, 0xe2}, {0xfe, 0xa4}, {0xff, 0x66},
{0xfa, 0x28}, {0xfb, 0xea}, {0xf9, 0xac}, {0xf8, 0x6e},
{0xf3, 0x30}, {0xf2, 0xf2}, {0xf0, 0xb4}, {0xf1, 0x76},
{0xf4, 0x38}, {0xf5, 0xfa}, {0xf7, 0xbc}, {0xf6, 0x7e},
{0xd9, 0x40}, {0xd8, 0x82}, {0xda, 0xc4}, {0xdb, 0x06},
{0xde, 0x48}, {0xdf, 0x8a}, {0xdd, 0xcc}, {0xdc, 0x0e},
{0xd7, 0x50}, {0xd6, 0x92}, {0xd4, 0xd4}, {0xd5, 0x16},
{0xd0, 0x58}, {0xd1, 0x9a}, {0xd3, 0xdc}, {0xd2, 0x1e},
{0xc5, 0x60}, {0xc4, 0xa2}, {0xc6, 0xe4}, {0xc7, 0x26},
{0xc2, 0x68}, {0xc3, 0xaa}, {0xc1, 0xec}, {0xc0, 0x2e},
{0xcb, 0x70}, {0xca, 0xb2}, {0xc8, 0xf4}, {0xc9, 0x36},
{0xcc, 0x78}, {0xcd, 0xba}, {0xcf, 0xfc}, {0xce, 0x3e},
{0x91, 0x80}, {0x90, 0x42}, {0x92, 0x04}, {0x93, 0xc6},
{0x96, 0x88}, {0x97, 0x4a}, {0x95, 0x0c}, {0x94, 0xce},
{0x9f, 0x90}, {0x9e, 0x52}, {0x9c, 0x14}, {0x9d, 0xd6},
{0x98, 0x98}, {0x99, 0x5a}, {0x9b, 0x1c}, {0x9a, 0xde},
{0x8d, 0xa0}, {0x8c, 0x62}, {0x8e, 0x24}, {0x8f, 0xe6},
{0x8a, 0xa8}, {0x8b, 0x6a}, {0x89, 0x2c}, {0x88, 0xee},
{0x83, 0xb0}, {0x82, 0x72}, {0x80, 0x34}, {0x81, 0xf6},
{0x84, 0xb8}, {0x85, 0x7a}, {0x87, 0x3c}, {0x86, 0xfe},
{0xa9, 0xc0}, {0xa8, 0x02}, {0xaa, 0x44}, {0xab, 0x86},
{0xae, 0xc8}, {0xaf, 0x0a}, {0xad, 0x4c}, {0xac, 0x8e},
{0xa7, 0xd0}, {0xa6, 0x12}, {0xa4, 0x54}, {0xa5, 0x96},
{0xa0, 0xd8}, {0xa1, 0x1a}, {0xa3, 0x5c}, {0xa2, 0x9e},
{0xb5, 0xe0}, {0xb4, 0x22}, {0xb6, 0x64}, {0xb7, 0xa6},
{0xb2, 0xe8}, {0xb3, 0x2a}, {0xb1, 0x6c}, {0xb0, 0xae},
{0xbb, 0xf0}, {0xba, 0x32}, {0xb8, 0x74}, {0xb9, 0xb6},
{0xbc, 0xf8}, {0xbd, 0x3a}, {0xbf, 0x7c}, {0xbe, 0xbe} };
static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE])
{
int i, j;
byte Z[AES_BLOCK_SIZE];
byte a;
XMEMSET(Z, 0, sizeof(Z));
for (i = 15; i > 0; i--) {
xorbuf(Z, m[x[i]], AES_BLOCK_SIZE);
a = Z[15];
for (j = 15; j > 0; j--) {
Z[j] = Z[j-1];
}
Z[0] = R[a][0];
Z[1] ^= R[a][1];
}
xorbuf(Z, m[x[0]], AES_BLOCK_SIZE);
XMEMCPY(x, Z, AES_BLOCK_SIZE);
}
static void GHASH(Aes* aes, const byte* a, word32 aSz,
const byte* c, word32 cSz, byte* s, word32 sSz)
{
byte x[AES_BLOCK_SIZE];
byte scratch[AES_BLOCK_SIZE];
word32 blocks, partial;
XMEMSET(x, 0, AES_BLOCK_SIZE);
/* Hash in A, the Additional Authentication Data */
if (aSz != 0 && a != NULL) {
blocks = aSz / AES_BLOCK_SIZE;
partial = aSz % AES_BLOCK_SIZE;
while (blocks--) {
xorbuf(x, a, AES_BLOCK_SIZE);
GMULT(x, aes->M0);
a += AES_BLOCK_SIZE;
}
if (partial != 0) {
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
XMEMCPY(scratch, a, partial);
xorbuf(x, scratch, AES_BLOCK_SIZE);
GMULT(x, aes->M0);
}
}
/* Hash in C, the Ciphertext */
if (cSz != 0 && c != NULL) {
blocks = cSz / AES_BLOCK_SIZE;
partial = cSz % AES_BLOCK_SIZE;
while (blocks--) {
xorbuf(x, c, AES_BLOCK_SIZE);
GMULT(x, aes->M0);
c += AES_BLOCK_SIZE;
}
if (partial != 0) {
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
XMEMCPY(scratch, c, partial);
xorbuf(x, scratch, AES_BLOCK_SIZE);
GMULT(x, aes->M0);
}
}
/* Hash in the lengths of A and C in bits */
FlattenSzInBits(&scratch[0], aSz);
FlattenSzInBits(&scratch[8], cSz);
xorbuf(x, scratch, AES_BLOCK_SIZE);
GMULT(x, aes->M0);
/* Copy the result into s. */
XMEMCPY(s, x, sSz);
}
/* end GCM_TABLE */
#elif defined(WORD64_AVAILABLE) && !defined(GCM_WORD32)
static void GMULT(word64* X, word64* Y)
{
word64 Z[2] = {0,0};
word64 V[2] = {X[0], X[1]};
int i, j;
for (i = 0; i < 2; i++)
{
word64 y = Y[i];
for (j = 0; j < 64; j++)
{
if (y & 0x8000000000000000) {
Z[0] ^= V[0];
Z[1] ^= V[1];
}
if (V[1] & 0x0000000000000001) {
V[1] >>= 1;
V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000 : 0);
V[0] >>= 1;
V[0] ^= 0xE100000000000000;
}
else {
V[1] >>= 1;
V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000 : 0);
V[0] >>= 1;
}
y <<= 1;
}
}
X[0] = Z[0];
X[1] = Z[1];
}
static void GHASH(Aes* aes, const byte* a, word32 aSz,
const byte* c, word32 cSz, byte* s, word32 sSz)
{
word64 x[2] = {0,0};
word32 blocks, partial;
word64 bigH[2];
XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(bigH, bigH, AES_BLOCK_SIZE);
#endif
/* Hash in A, the Additional Authentication Data */
if (aSz != 0 && a != NULL) {
word64 bigA[2];
blocks = aSz / AES_BLOCK_SIZE;
partial = aSz % AES_BLOCK_SIZE;
while (blocks--) {
XMEMCPY(bigA, a, AES_BLOCK_SIZE);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE);
#endif
x[0] ^= bigA[0];
x[1] ^= bigA[1];
GMULT(x, bigH);
a += AES_BLOCK_SIZE;
}
if (partial != 0) {
XMEMSET(bigA, 0, AES_BLOCK_SIZE);
XMEMCPY(bigA, a, partial);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE);
#endif
x[0] ^= bigA[0];
x[1] ^= bigA[1];
GMULT(x, bigH);
}
}
/* Hash in C, the Ciphertext */
if (cSz != 0 && c != NULL) {
word64 bigC[2];
blocks = cSz / AES_BLOCK_SIZE;
partial = cSz % AES_BLOCK_SIZE;
while (blocks--) {
XMEMCPY(bigC, c, AES_BLOCK_SIZE);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE);
#endif
x[0] ^= bigC[0];
x[1] ^= bigC[1];
GMULT(x, bigH);
c += AES_BLOCK_SIZE;
}
if (partial != 0) {
XMEMSET(bigC, 0, AES_BLOCK_SIZE);
XMEMCPY(bigC, c, partial);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE);
#endif
x[0] ^= bigC[0];
x[1] ^= bigC[1];
GMULT(x, bigH);
}
}
/* Hash in the lengths in bits of A and C */
{
word64 len[2] = {aSz, cSz};
/* Lengths are in bytes. Convert to bits. */
len[0] *= 8;
len[1] *= 8;
x[0] ^= len[0];
x[1] ^= len[1];
GMULT(x, bigH);
}
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(x, x, AES_BLOCK_SIZE);
#endif
XMEMCPY(s, x, sSz);
}
/* end defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) */
#else /* GCM_WORD32 */
static void GMULT(word32* X, word32* Y)
{
word32 Z[4] = {0,0,0,0};
word32 V[4] = {X[0], X[1], X[2], X[3]};
int i, j;
for (i = 0; i < 4; i++)
{
word32 y = Y[i];
for (j = 0; j < 32; j++)
{
if (y & 0x80000000) {
Z[0] ^= V[0];
Z[1] ^= V[1];
Z[2] ^= V[2];
Z[3] ^= V[3];
}
if (V[3] & 0x00000001) {
V[3] >>= 1;
V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0);
V[2] >>= 1;
V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0);
V[1] >>= 1;
V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0);
V[0] >>= 1;
V[0] ^= 0xE1000000;
} else {
V[3] >>= 1;
V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0);
V[2] >>= 1;
V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0);
V[1] >>= 1;
V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0);
V[0] >>= 1;
}
y <<= 1;
}
}
X[0] = Z[0];
X[1] = Z[1];
X[2] = Z[2];
X[3] = Z[3];
}
static void GHASH(Aes* aes, const byte* a, word32 aSz,
const byte* c, word32 cSz, byte* s, word32 sSz)
{
word32 x[4] = {0,0,0,0};
word32 blocks, partial;
word32 bigH[4];
XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords(bigH, bigH, AES_BLOCK_SIZE);
#endif
/* Hash in A, the Additional Authentication Data */
if (aSz != 0 && a != NULL) {
word32 bigA[4];
blocks = aSz / AES_BLOCK_SIZE;
partial = aSz % AES_BLOCK_SIZE;
while (blocks--) {
XMEMCPY(bigA, a, AES_BLOCK_SIZE);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE);
#endif
x[0] ^= bigA[0];
x[1] ^= bigA[1];
x[2] ^= bigA[2];
x[3] ^= bigA[3];
GMULT(x, bigH);
a += AES_BLOCK_SIZE;
}
if (partial != 0) {
XMEMSET(bigA, 0, AES_BLOCK_SIZE);
XMEMCPY(bigA, a, partial);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE);
#endif
x[0] ^= bigA[0];
x[1] ^= bigA[1];
x[2] ^= bigA[2];
x[3] ^= bigA[3];
GMULT(x, bigH);
}
}
/* Hash in C, the Ciphertext */
if (cSz != 0 && c != NULL) {
word32 bigC[4];
blocks = cSz / AES_BLOCK_SIZE;
partial = cSz % AES_BLOCK_SIZE;
while (blocks--) {
XMEMCPY(bigC, c, AES_BLOCK_SIZE);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE);
#endif
x[0] ^= bigC[0];
x[1] ^= bigC[1];
x[2] ^= bigC[2];
x[3] ^= bigC[3];
GMULT(x, bigH);
c += AES_BLOCK_SIZE;
}
if (partial != 0) {
XMEMSET(bigC, 0, AES_BLOCK_SIZE);
XMEMCPY(bigC, c, partial);
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE);
#endif
x[0] ^= bigC[0];
x[1] ^= bigC[1];
x[2] ^= bigC[2];
x[3] ^= bigC[3];
GMULT(x, bigH);
}
}
/* Hash in the lengths in bits of A and C */
{
word32 len[4];
/* Lengths are in bytes. Convert to bits. */
len[0] = (aSz >> (8*sizeof(aSz) - 3));
len[1] = aSz << 3;
len[2] = (cSz >> (8*sizeof(cSz) - 3));
len[3] = cSz << 3;
x[0] ^= len[0];
x[1] ^= len[1];
x[2] ^= len[2];
x[3] ^= len[3];
GMULT(x, bigH);
}
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords(x, x, AES_BLOCK_SIZE);
#endif
XMEMCPY(s, x, sSz);
}
#endif /* end GCM_WORD32 */
void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
byte* authTag, word32 authTagSz,
@ -1549,40 +2013,35 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
word32 partial = sz % AES_BLOCK_SIZE;
const byte* p = in;
byte* c = out;
byte h[AES_BLOCK_SIZE];
byte ctr[AES_BLOCK_SIZE];
byte scratch[AES_BLOCK_SIZE];
CYASSL_ENTER("AesGcmEncrypt");
/* Set up the H block by encrypting an array of zeroes with the key. */
XMEMSET(ctr, 0, AES_BLOCK_SIZE);
AesEncrypt(aes, ctr, h);
/* Initialize the counter with the MS 96 bits of IV, and the counter
* portion set to "1". */
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE - 4);
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE);
InitGcmCounter(ctr);
while (blocks--) {
IncrementGcmCounter(ctr);
AesEncrypt(aes, ctr, c);
xorbuf(c, p, AES_BLOCK_SIZE);
AesEncrypt(aes, ctr, scratch);
xorbuf(scratch, p, AES_BLOCK_SIZE);
XMEMCPY(c, scratch, AES_BLOCK_SIZE);
p += AES_BLOCK_SIZE;
c += AES_BLOCK_SIZE;
}
if (partial != 0) {
byte cPartial[AES_BLOCK_SIZE];
IncrementGcmCounter(ctr);
AesEncrypt(aes, ctr, cPartial);
XMEMCPY(c, cPartial, partial);
xorbuf(c, p, partial);
AesEncrypt(aes, ctr, scratch);
xorbuf(scratch, p, partial);
XMEMCPY(c, scratch, partial);
}
GHASH(h, authIn, authInSz, out, sz, authTag, authTagSz);
GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
InitGcmCounter(ctr);
AesEncrypt(aes, ctr, h);
xorbuf(authTag, h, authTagSz);
AesEncrypt(aes, ctr, scratch);
xorbuf(authTag, scratch, authTagSz);
}
@ -1594,18 +2053,14 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
word32 partial = sz % AES_BLOCK_SIZE;
const byte* c = in;
byte* p = out;
byte h[AES_BLOCK_SIZE];
byte ctr[AES_BLOCK_SIZE];
byte scratch[AES_BLOCK_SIZE];
CYASSL_ENTER("AesGcmDecrypt");
/* Set up the H block by encrypting an array of zeroes with the key. */
XMEMSET(ctr, 0, AES_BLOCK_SIZE);
AesEncrypt(aes, ctr, h);
/* Initialize the counter with the MS 96 bits of IV, and the counter
* portion set to "1". */
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE - 4);
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE);
InitGcmCounter(ctr);
/* Calculate the authTag again using the received auth data and the
@ -1614,7 +2069,7 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
byte Tprime[AES_BLOCK_SIZE];
byte EKY0[AES_BLOCK_SIZE];
GHASH(h, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
AesEncrypt(aes, ctr, EKY0);
xorbuf(Tprime, EKY0, sizeof(Tprime));
if (XMEMCMP(authTag, Tprime, authTagSz) != 0) {
@ -1624,19 +2079,18 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
while (blocks--) {
IncrementGcmCounter(ctr);
AesEncrypt(aes, ctr, p);
xorbuf(p, c, AES_BLOCK_SIZE);
AesEncrypt(aes, ctr, scratch);
xorbuf(scratch, c, AES_BLOCK_SIZE);
XMEMCPY(p, scratch, AES_BLOCK_SIZE);
p += AES_BLOCK_SIZE;
c += AES_BLOCK_SIZE;
}
if (partial != 0) {
byte pPartial[AES_BLOCK_SIZE];
IncrementGcmCounter(ctr);
AesEncrypt(aes, ctr, pPartial);
XMEMCPY(p, pPartial, partial);
xorbuf(p, c, partial);
AesEncrypt(aes, ctr, scratch);
xorbuf(scratch, c, partial);
XMEMCPY(p, scratch, partial);
}
return 0;

View File

@ -34,7 +34,7 @@ static int InitHmac(Hmac* hmac, int type)
hmac->innerHashKeyed = 0;
hmac->macType = (byte)type;
if (!(type == MD5 || type == SHA || type == SHA256))
if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384))
return BAD_FUNC_ARG;
if (type == MD5)
@ -45,6 +45,10 @@ static int InitHmac(Hmac* hmac, int type)
else if (type == SHA256)
InitSha256(&hmac->hash.sha256);
#endif
#ifdef CYASSL_SHA384
else if (type == SHA384)
InitSha384(&hmac->hash.sha384);
#endif
return 0;
}
@ -54,34 +58,60 @@ void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
{
byte* ip = (byte*) hmac->ipad;
byte* op = (byte*) hmac->opad;
word32 i;
word32 i, hmac_block_size = MD5_BLOCK_SIZE;
InitHmac(hmac, type);
if (length <= HMAC_BLOCK_SIZE)
XMEMCPY(ip, key, length);
else {
if (hmac->macType == MD5) {
if (hmac->macType == MD5) {
if (length <= MD5_BLOCK_SIZE) {
XMEMCPY(ip, key, length);
}
else {
Md5Update(&hmac->hash.md5, key, length);
Md5Final(&hmac->hash.md5, ip);
length = MD5_DIGEST_SIZE;
}
else if (hmac->macType == SHA) {
}
else if (hmac->macType == SHA) {
hmac_block_size = SHA_BLOCK_SIZE;
if (length <= SHA_BLOCK_SIZE) {
XMEMCPY(ip, key, length);
}
else {
ShaUpdate(&hmac->hash.sha, key, length);
ShaFinal(&hmac->hash.sha, ip);
length = SHA_DIGEST_SIZE;
}
}
#ifndef NO_SHA256
else if (hmac->macType == SHA256) {
else if (hmac->macType == SHA256) {
hmac_block_size = SHA256_BLOCK_SIZE;
if (length <= SHA256_BLOCK_SIZE) {
XMEMCPY(ip, key, length);
}
else {
Sha256Update(&hmac->hash.sha256, key, length);
Sha256Final(&hmac->hash.sha256, ip);
length = SHA256_DIGEST_SIZE;
}
#endif
}
XMEMSET(ip + length, 0, HMAC_BLOCK_SIZE - length);
#endif
#ifdef CYASSL_SHA384
else if (hmac->macType == SHA384) {
hmac_block_size = SHA384_BLOCK_SIZE;
if (length <= SHA384_BLOCK_SIZE) {
XMEMCPY(ip, key, length);
}
else {
Sha384Update(&hmac->hash.sha384, key, length);
Sha384Final(&hmac->hash.sha384, ip);
length = SHA384_DIGEST_SIZE;
}
}
#endif
XMEMSET(ip + length, 0, hmac_block_size - length);
for(i = 0; i < HMAC_BLOCK_SIZE; i++) {
for(i = 0; i < hmac_block_size; i++) {
op[i] = ip[i] ^ OPAD;
ip[i] ^= IPAD;
}
@ -91,12 +121,16 @@ void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
static void HmacKeyInnerHash(Hmac* hmac)
{
if (hmac->macType == MD5)
Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE);
else if (hmac->macType == SHA)
ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE);
#ifndef NO_SHA256
else if (hmac->macType == SHA256)
Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, SHA256_BLOCK_SIZE);
#endif
#ifdef CYASSL_SHA384
else if (hmac->macType == SHA384)
Sha384Update(&hmac->hash.sha384, (byte*) hmac->ipad, SHA384_BLOCK_SIZE);
#endif
hmac->innerHashKeyed = 1;
@ -116,6 +150,10 @@ void HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
else if (hmac->macType == SHA256)
Sha256Update(&hmac->hash.sha256, msg, length);
#endif
#ifdef CYASSL_SHA384
else if (hmac->macType == SHA384)
Sha384Update(&hmac->hash.sha384, msg, length);
#endif
}
@ -128,30 +166,41 @@ void HmacFinal(Hmac* hmac, byte* hash)
if (hmac->macType == MD5) {
Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash);
Md5Update(&hmac->hash.md5, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE);
Md5Update(&hmac->hash.md5, (byte*) hmac->innerHash, MD5_DIGEST_SIZE);
Md5Final(&hmac->hash.md5, hash);
}
else if (hmac->macType ==SHA) {
else if (hmac->macType == SHA) {
ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash);
ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE);
ShaUpdate(&hmac->hash.sha, (byte*) hmac->innerHash, SHA_DIGEST_SIZE);
ShaFinal(&hmac->hash.sha, hash);
}
#ifndef NO_SHA256
else if (hmac->macType ==SHA256) {
else if (hmac->macType == SHA256) {
Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash);
Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, SHA256_BLOCK_SIZE);
Sha256Update(&hmac->hash.sha256, (byte*) hmac->innerHash,
SHA256_DIGEST_SIZE);
Sha256Final(&hmac->hash.sha256, hash);
}
#endif
#ifdef CYASSL_SHA384
else if (hmac->macType == SHA384) {
Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash);
Sha384Update(&hmac->hash.sha384, (byte*) hmac->opad, SHA384_BLOCK_SIZE);
Sha384Update(&hmac->hash.sha384, (byte*) hmac->innerHash,
SHA384_DIGEST_SIZE);
Sha384Final(&hmac->hash.sha384, hash);
}
#endif
hmac->innerHashKeyed = 0;
}

View File

@ -99,6 +99,7 @@ int rabbit_test();
int des_test();
int des3_test();
int aes_test();
int aesgcm_test();
int rsa_test();
int dh_test();
int dsa_test();
@ -233,6 +234,13 @@ void ctaocrypt_test(void* args)
err_sys("AES test failed!\n", ret);
else
printf( "AES test passed!\n");
#ifdef HAVE_AESGCM
if ( (ret = aesgcm_test()) )
err_sys("AES-GCM test failed!\n", ret);
else
printf( "AES-GCM test passed!\n");
#endif
#endif
if ( (ret = random_test()) )
@ -1144,93 +1152,101 @@ int aes_test()
}
#endif /* CYASSL_AES_COUNTER */
return 0;
}
#ifdef HAVE_AESGCM
int aesgcm_test()
{
Aes enc;
/*
* This is Test Case 16 from the document Galois/
* Counter Mode of Operation (GCM) by McGrew and
* Viega.
*/
const byte k[] =
{
/*
* This is Test Case 16 from the document Galois/
* Counter Mode of Operation (GCM) by McGrew and
* Viega.
*/
const byte k[] =
{
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
};
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
};
const byte iv[] =
{
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x00, 0x00
};
const byte p[] =
{
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
};
const byte a[] =
{
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xab, 0xad, 0xda, 0xd2
};
const byte c[] =
{
0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
0xbc, 0xc9, 0xf6, 0x62
};
const byte iv[] =
{
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x00, 0x00
};
const byte p[] =
{
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
};
const byte a[] =
{
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xab, 0xad, 0xda, 0xd2
};
const byte c[] =
{
0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
0xbc, 0xc9, 0xf6, 0x62
};
const byte t[] =
{
0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b
};
const byte t[] =
{
0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b
};
byte t2[16];
byte p2[60];
byte c2[60];
byte t2[16];
byte p2[60];
byte c2[60];
int result;
int result;
memset(t2, 0, 16);
memset(c2, 0, 60);
memset(p2, 0, 60);
memset(t2, 0, 16);
memset(c2, 0, 60);
memset(p2, 0, 60);
AesSetKey(&enc, k, sizeof(k), iv, AES_ENCRYPTION);
/* AES-GCM encrypt and decrypt both use AES encrypt internally */
AesGcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a));
if (memcmp(c, c2, sizeof(c2)))
return -68;
if (memcmp(t, t2, sizeof(t2)))
return -69;
AesGcmSetKey(&enc, k, sizeof(k));
AesSetIV(&enc, iv);
/* AES-GCM encrypt and decrypt both use AES encrypt internally */
AesGcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a));
if (memcmp(c, c2, sizeof(c2)))
return -68;
if (memcmp(t, t2, sizeof(t2)))
return -69;
result = AesGcmDecrypt(&enc,
p2, c2, sizeof(p2), t2, sizeof(t2), a, sizeof(a));
if (result != 0)
return -70;
if (memcmp(p, p2, sizeof(p2)))
return -71;
}
#endif /* HAVE_AESGCM */
result = AesGcmDecrypt(&enc,
p2, c2, sizeof(p2), t2, sizeof(t2), a, sizeof(a));
if (result != 0)
return -70;
if (memcmp(p, p2, sizeof(p2)))
return -71;
return 0;
}
#endif /* HAVE_AESGCM */
#endif /* NO_AES */

View File

@ -68,6 +68,14 @@ typedef struct Aes {
ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */
#ifdef HAVE_AESGCM
ALIGN16 byte H[AES_BLOCK_SIZE];
#ifdef GCM_TABLE
/* key-based fast multiplication table. */
ALIGN16 byte M0[256][AES_BLOCK_SIZE];
#endif /* GCM_TABLE */
#endif /* HAVE_AESGCM */
} Aes;
@ -81,6 +89,7 @@ CYASSL_API void AesEncryptDirect(Aes* aes, byte* out, const byte* in);
CYASSL_API void AesDecryptDirect(Aes* aes, byte* out, const byte* in);
#ifdef HAVE_AESGCM
CYASSL_API void AesGcmSetKey(Aes* aes, const byte* key, word32 len);
CYASSL_API void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz);

View File

@ -32,6 +32,10 @@
#include <cyassl/ctaocrypt/sha256.h>
#endif
#ifdef CYASSL_SHA384
#include <cyassl/ctaocrypt/sha512.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -40,13 +44,19 @@
enum {
IPAD = 0x36,
OPAD = 0x5C,
#ifndef NO_SHA256
#if defined(CYASSL_SHA384)
INNER_HASH_SIZE = SHA384_DIGEST_SIZE,
HMAC_BLOCK_SIZE = SHA384_BLOCK_SIZE
#elif !defined(NO_SHA256)
INNER_HASH_SIZE = SHA256_DIGEST_SIZE,
HMAC_BLOCK_SIZE = SHA256_BLOCK_SIZE,
SHA384 = 5
#else
INNER_HASH_SIZE = SHA_DIGEST_SIZE,
HMAC_BLOCK_SIZE = SHA_BLOCK_SIZE,
SHA256 = 2, /* hash type unique */
SHA384 = 5
#endif
HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE
};
@ -57,6 +67,9 @@ typedef union {
#ifndef NO_SHA256
Sha256 sha256;
#endif
#ifdef CYASSL_SHA384
Sha384 sha384;
#endif
} Hash;
/* Hmac digest */

View File

@ -44,6 +44,9 @@
#ifdef HAVE_OCSP
#include <cyassl/ocsp.h>
#endif
#ifdef CYASSL_SHA512
#include <cyassl/ctaocrypt/sha512.h>
#endif
#ifdef CYASSL_CALLBACKS
#include <cyassl/openssl/cyassl_callbacks.h>
@ -147,6 +150,10 @@ void c32to24(word32 in, word24 out);
#define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
#define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
#endif
#if defined (HAVE_AESGCM)
#define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
#define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
#endif
#endif
#if !defined(NO_HC128) && !defined(NO_TLS)
@ -164,6 +171,10 @@ void c32to24(word32 in, word24 out);
#if !defined (NO_SHA256)
#define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
#define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
#if defined (HAVE_AESGCM)
#define BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
#define BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
#endif
#endif
#endif
@ -178,6 +189,18 @@ void c32to24(word32 in, word24 out);
#define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
#define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
#define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
#if defined (HAVE_AESGCM)
#define BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
#define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
#define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
#define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
#define BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
#define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
#define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
#define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
#endif
#endif
#if !defined(NO_RC4)
#define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
@ -210,6 +233,11 @@ void c32to24(word32 in, word24 out);
#define BUILD_AES
#endif
#if defined(BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) || \
defined(BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
#define BUILD_AESGCM
#endif
#if defined(BUILD_TLS_RSA_WITH_HC_128_CBC_SHA) || \
defined(BUILD_TLS_RSA_WITH_HC_128_CBC_MD5)
#define BUILD_HC128
@ -275,7 +303,23 @@ enum {
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67,
TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x3d,
TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x3c
TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x3c,
/* AES-GCM */
TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x9c,
TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x9d,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x9e,
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x9f,
/* ECC AES-GCM, first byte is 0xC0 (ECC_BYTE) */
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0x2b,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0x2c,
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0x2d,
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0x2e,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0x2f,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0x30,
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0x31,
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0x32
};
@ -297,6 +341,7 @@ enum Misc {
TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */
NO_COMPRESSION = 0,
ZLIB_COMPRESSION = 221, /* CyaSSL zlib compression */
HELLO_EXT_SIG_ALGO = 13, /* ID for the sig_algo hello extension */
SECRET_LEN = 48, /* pre RSA and all master */
ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */
SIZEOF_SENDER = 4, /* clnt or srvr */
@ -338,6 +383,10 @@ enum Misc {
CERT_HEADER_SZ = 3, /* always 3 bytes */
REQ_HEADER_SZ = 2, /* cert request header sz */
HINT_LEN_SZ = 2, /* length of hint size field */
HELLO_EXT_SZ = 14, /* total length of the lazy hello extensions */
HELLO_EXT_LEN = 12, /* length of the lazy hello extensions */
HELLO_EXT_SIGALGO_SZ = 8, /* length of signature algo extension */
HELLO_EXT_SIGALGO_LEN = 6, /* number of items in the signature algo list */
DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */
@ -361,8 +410,19 @@ enum Misc {
AES_256_KEY_SIZE = 32, /* for 256 bit */
AES_192_KEY_SIZE = 24, /* for 192 bit */
AES_IV_SIZE = 16, /* always block size */
AES_GCM_IMP_IV_SZ = 4, /* Implicit part of IV */
AES_GCM_EXP_IV_SZ = 8, /* Explicit part of IV */
AES_GCM_CTR_IV_SZ = 4, /* Counter part of IV */
AES_128_KEY_SIZE = 16, /* for 128 bit */
AEAD_SEQ_OFFSET = 4, /* Auth Data: Sequence number */
AEAD_TYPE_OFFSET = 8, /* Auth Data: Type */
AEAD_VMAJ_OFFSET = 9, /* Auth Data: Major Version */
AEAD_VMIN_OFFSET = 10, /* Auth Data: Minor Version */
AEAD_LEN_OFFSET = 11, /* Auth Data: Length */
AEAD_AUTH_TAG_SZ = 16, /* Size of the authentication tag */
AEAD_AUTH_DATA_SZ = 13, /* Size of the data to authenticate */
HC_128_KEY_SIZE = 16, /* 128 bits */
HC_128_IV_SIZE = 16, /* also 128 bits */
@ -765,7 +825,7 @@ int AlreadySigner(CYASSL_CERT_MANAGER* cm, byte* hash);
/* All cipher suite related info */
typedef struct CipherSpecs {
byte bulk_cipher_algorithm;
byte cipher_type; /* block or stream */
byte cipher_type; /* block, stream, or aead */
byte mac_algorithm;
byte kea; /* key exchange algo */
byte sig_algo;
@ -789,6 +849,7 @@ enum BulkCipherAlgorithm {
des40,
idea,
aes,
aes_gcm,
hc128, /* CyaSSL extensions */
rabbit
};
@ -859,7 +920,7 @@ enum ClientCertificateType {
};
enum CipherType { stream, block };
enum CipherType { stream, block, aead };
/* keys and secrets */
@ -1129,6 +1190,9 @@ struct CYASSL {
Sha hashSha; /* sha hash of handshake msgs */
#ifndef NO_SHA256
Sha256 hashSha256; /* sha256 hash of handshake msgs */
#endif
#ifdef CYASSL_SHA384
Sha384 hashSha384; /* sha384 hash of handshake msgs */
#endif
Hashes verifyHashes;
Hashes certHashes; /* for cert verify */

View File

@ -69,7 +69,7 @@ void echoclient_test(void* args)
#if defined(CYASSL_DTLS)
method = DTLSv1_client_method();
#elif !defined(NO_TLS)
method = TLSv1_client_method();
method = CyaSSLv23_client_method();
#else
method = SSLv3_client_method();
#endif
@ -105,7 +105,7 @@ void echoclient_test(void* args)
while (fgets(send, sizeof(send), fin)) {
sendSz = (int)strlen(send) + 1;
sendSz = (int)strlen(send);
if (SSL_write(ssl, send, sendSz) != sendSz)
err_sys("SSL_write failed");
@ -115,7 +115,7 @@ void echoclient_test(void* args)
break;
}
if (strncmp(send, "break", 4) == 0) {
if (strncmp(send, "break", 5) == 0) {
fputs("sending server session close: break!\n", fout);
break;
}
@ -123,6 +123,7 @@ void echoclient_test(void* args)
while (sendSz) {
int got;
if ( (got = SSL_read(ssl, reply, sizeof(reply))) > 0) {
reply[got] = 0;
fputs(reply, fout);
sendSz -= got;
}
@ -165,6 +166,9 @@ void echoclient_test(void* args)
args.argv = argv;
CyaSSL_Init();
#ifdef DEBUG_CYASSL
CyaSSL_Debugging_ON();
#endif
if (CurrentDir("echoclient") || CurrentDir("build"))
ChangeDirBack(2);
echoclient_test(&args);

View File

@ -55,7 +55,7 @@
#ifndef NO_CYASSL_CLIENT
static int DoHelloVerifyRequest(CYASSL* ssl, const byte* input, word32*);
static int DoServerHello(CYASSL* ssl, const byte* input, word32*);
static int DoServerHello(CYASSL* ssl, const byte* input, word32*, word32);
static int DoCertificateRequest(CYASSL* ssl, const byte* input, word32*);
static int DoServerKeyExchange(CYASSL* ssl, const byte* input, word32*);
#endif
@ -239,7 +239,8 @@ static INLINE void ato32(const byte* c, word32* u32)
ssl->c_stream.zfree = (free_func)myFree;
ssl->c_stream.opaque = (voidpf)ssl->heap;
if (deflateInit(&ssl->c_stream, 8) != Z_OK) return ZLIB_INIT_ERROR;
if (deflateInit(&ssl->c_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
return ZLIB_INIT_ERROR;
ssl->didStreamInit = 1;
@ -268,11 +269,6 @@ static INLINE void ato32(const byte* c, word32* u32)
int err;
int currTotal = ssl->c_stream.total_out;
/* put size in front of compression */
c16toa((word16)inSz, out);
out += 2;
outSz -= 2;
ssl->c_stream.next_in = in;
ssl->c_stream.avail_in = inSz;
ssl->c_stream.next_out = out;
@ -281,7 +277,7 @@ static INLINE void ato32(const byte* c, word32* u32)
err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
return ssl->c_stream.total_out - currTotal + sizeof(word16);
return ssl->c_stream.total_out - currTotal;
}
@ -290,12 +286,6 @@ static INLINE void ato32(const byte* c, word32* u32)
{
int err;
int currTotal = ssl->d_stream.total_out;
word16 len;
/* find size in front of compression */
ato16(in, &len);
in += 2;
inSz -= 2;
ssl->d_stream.next_in = in;
ssl->d_stream.avail_in = inSz;
@ -498,6 +488,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveECDSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
if (tls && haveECDSA) {
suites->suites[idx++] = ECC_BYTE;
@ -505,6 +502,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveECDSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
if (tls && haveECDSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
@ -512,6 +516,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveECDSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
if (tls && haveECDSA) {
suites->suites[idx++] = ECC_BYTE;
@ -519,6 +530,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveECDSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
if (tls && haveECDSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
@ -554,6 +572,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
@ -561,6 +586,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveRSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
@ -568,6 +600,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE;
@ -575,6 +614,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveRSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
@ -610,6 +656,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0;
@ -617,6 +670,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0;
@ -638,6 +698,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0;
@ -645,6 +712,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0;
@ -793,6 +867,9 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
InitSha(&ssl->hashSha);
#ifndef NO_SHA256
InitSha256(&ssl->hashSha256);
#endif
#ifdef CYASSL_SHA384
InitSha384(&ssl->hashSha384);
#endif
InitRsaKey(&ssl->peerRsaKey, ctx->heap);
@ -1096,10 +1173,14 @@ static void HashOutput(CYASSL* ssl, const byte* output, int sz, int ivSz)
Md5Update(&ssl->hashMd5, adj, sz);
ShaUpdate(&ssl->hashSha, adj, sz);
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
Sha256Update(&ssl->hashSha256, adj, sz);
#endif
#ifdef CYASSL_SHA384
Sha384Update(&ssl->hashSha384, adj, sz);
#endif
}
}
@ -1118,10 +1199,14 @@ static void HashInput(CYASSL* ssl, const byte* input, int sz)
Md5Update(&ssl->hashMd5, adj, sz);
ShaUpdate(&ssl->hashSha, adj, sz);
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
Sha256Update(&ssl->hashSha256, adj, sz);
#endif
#ifdef CYASSL_SHA384
Sha384Update(&ssl->hashSha384, adj, sz);
#endif
}
}
@ -1539,10 +1624,21 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
Sha sha = ssl->hashSha;
#ifndef NO_SHA256
Sha256 sha256;
#endif
#ifdef CYASSL_SHA384
Sha384 sha384;
#endif
#ifndef NO_SHA256
InitSha256(&sha256);
if (IsAtLeastTLSv1_2(ssl))
sha256 = ssl->hashSha256;
#endif
#ifdef CYASSL_SHA384
InitSha384(&sha384);
if (IsAtLeastTLSv1_2(ssl))
sha384 = ssl->hashSha384;
#endif
if (ssl->options.tls)
BuildTlsFinished(ssl, hashes, sender);
@ -1554,10 +1650,14 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
/* restore */
ssl->hashMd5 = md5;
ssl->hashSha = sha;
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
ssl->hashSha256 = sha256;
#endif
#ifdef CYASSL_SHA384
ssl->hashSha384 = sha384;
#endif
}
}
@ -1936,23 +2036,28 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
}
}
ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz,
handshake, 1);
idx += finishedSz;
if (ssl->specs.cipher_type != aead) {
ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz,
handshake, 1);
idx += finishedSz;
/* read mac and fill */
mac = input + idx;
idx += ssl->specs.hash_size;
/* read mac and fill */
mac = input + idx;
idx += ssl->specs.hash_size;
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
padSz -= ssl->specs.block_size;
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
padSz -= ssl->specs.block_size;
idx += padSz;
idx += padSz;
/* verify mac */
if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size)) {
CYASSL_MSG("Verify finished error on mac");
return VERIFY_MAC_ERROR;
/* verify mac */
if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size)) {
CYASSL_MSG("Verify finished error on mac");
return VERIFY_MAC_ERROR;
}
}
else {
idx += (finishedSz + AEAD_AUTH_TAG_SZ);
}
if (ssl->options.side == CLIENT_END) {
@ -2012,7 +2117,7 @@ static int DoHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx,
case server_hello:
CYASSL_MSG("processing server hello");
ret = DoServerHello(ssl, input, inOutIdx);
ret = DoServerHello(ssl, input, inOutIdx, size);
break;
case certificate_request:
@ -2075,6 +2180,15 @@ static int DoHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx,
}
static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
{
if (verify)
return ssl->keys.peer_sequence_number++;
else
return ssl->keys.sequence_number++;
}
static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
{
switch (ssl->specs.bulk_cipher_algorithm) {
@ -2105,6 +2219,50 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
break;
#endif
#ifdef BUILD_AESGCM
case aes_gcm:
{
byte additional[AES_BLOCK_SIZE];
byte nonce[AES_BLOCK_SIZE];
/* use this side's IV */
if (ssl->options.side == SERVER_END) {
XMEMCPY(nonce, ssl->keys.server_write_IV,
AES_GCM_IMP_IV_SZ);
}
else {
XMEMCPY(nonce, ssl->keys.client_write_IV,
AES_GCM_IMP_IV_SZ);
}
XMEMCPY(nonce + AES_GCM_IMP_IV_SZ,
input, AES_GCM_EXP_IV_SZ);
XMEMSET(nonce + AES_GCM_IMP_IV_SZ + AES_GCM_EXP_IV_SZ,
0, AES_GCM_CTR_IV_SZ);
AesSetIV(&ssl->encrypt.aes, nonce);
XMEMSET(additional, 0, AES_BLOCK_SIZE);
/* sequence number field is 64-bits, we only use 32-bits */
c32toa(GetSEQIncrement(ssl, 0),
additional + AEAD_SEQ_OFFSET);
/* Store the type, version. Unfortunately, they are in
* the input buffer ahead of the plaintext. */
XMEMCPY(additional + AEAD_TYPE_OFFSET, input - 5, 3);
/* Store the length of the plain text minus the explicit
* IV length minus the authentication tag size. */
c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
additional + AEAD_LEN_OFFSET);
AesGcmEncrypt(&ssl->encrypt.aes,
out + AES_GCM_EXP_IV_SZ, input + AES_GCM_EXP_IV_SZ,
sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
out + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ,
additional, AEAD_AUTH_DATA_SZ);
}
break;
#endif
#ifdef HAVE_HC128
case hc128:
Hc128_Process(&ssl->encrypt.hc128, out, input, sz);
@ -2123,7 +2281,7 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
}
static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input,
static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
word32 sz)
{
switch (ssl->specs.bulk_cipher_algorithm) {
@ -2145,6 +2303,51 @@ static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input,
break;
#endif
#ifdef BUILD_AESGCM
case aes_gcm:
{
byte additional[AES_BLOCK_SIZE];
byte nonce[AES_BLOCK_SIZE];
/* use the other side's IV */
if (ssl->options.side == SERVER_END) {
XMEMCPY(nonce, ssl->keys.client_write_IV,
AES_GCM_IMP_IV_SZ);
}
else {
XMEMCPY(nonce, ssl->keys.server_write_IV,
AES_GCM_IMP_IV_SZ);
}
XMEMCPY(nonce + AES_GCM_IMP_IV_SZ,
input, AES_GCM_EXP_IV_SZ);
XMEMSET(nonce + AES_GCM_IMP_IV_SZ + AES_GCM_EXP_IV_SZ,
0, AES_GCM_CTR_IV_SZ);
AesSetIV(&ssl->decrypt.aes, nonce);
XMEMSET(additional, 0, AES_BLOCK_SIZE);
/* sequence number field is 64-bits, we only use 32-bits */
c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET);
additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
additional[AEAD_VMAJ_OFFSET] = ssl->curRL.version.major;
additional[AEAD_VMIN_OFFSET] = ssl->curRL.version.minor;
c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
additional + AEAD_LEN_OFFSET);
if (AesGcmDecrypt(&ssl->decrypt.aes,
plain + AES_GCM_EXP_IV_SZ,
input + AES_GCM_EXP_IV_SZ,
sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
input + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ,
additional, AEAD_AUTH_DATA_SZ) < 0) {
SendAlert(ssl, alert_fatal, bad_record_mac);
return VERIFY_MAC_ERROR;
}
break;
}
#endif
#ifdef HAVE_HC128
case hc128:
Hc128_Process(&ssl->decrypt.hc128, plain, input, sz);
@ -2160,27 +2363,25 @@ static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input,
default:
CYASSL_MSG("CyaSSL Decrypt programming error");
}
return 0;
}
/* decrypt input message in place */
static int DecryptMessage(CYASSL* ssl, byte* input, word32 sz, word32* idx)
{
Decrypt(ssl, input, input, sz);
ssl->keys.encryptSz = sz;
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
*idx += ssl->specs.block_size; /* go past TLSv1.1 IV */
int decryptResult = Decrypt(ssl, input, input, sz);
return 0;
}
if (decryptResult == 0)
{
ssl->keys.encryptSz = sz;
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
*idx += ssl->specs.block_size; /* go past TLSv1.1 IV */
if (ssl->specs.cipher_type == aead)
*idx += AES_GCM_EXP_IV_SZ;
}
static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
{
if (verify)
return ssl->keys.peer_sequence_number++;
else
return ssl->keys.sequence_number++;
return decryptResult;
}
@ -2207,6 +2408,10 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
pad = *(input + idx + msgSz - ivExtra - 1);
padByte = 1;
}
if (ssl->specs.cipher_type == aead) {
ivExtra = AES_GCM_EXP_IV_SZ;
digestSz = AEAD_AUTH_TAG_SZ;
}
dataSz = msgSz - ivExtra - digestSz - pad - padByte;
if (dataSz < 0) {
@ -2218,7 +2423,8 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
if (dataSz) {
int rawSz = dataSz; /* keep raw size for hmac */
ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1);
if (ssl->specs.cipher_type != aead)
ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1);
#ifdef HAVE_LIBZ
if (ssl->options.usingCompression) {
@ -2244,14 +2450,9 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
if (padByte)
idx++;
#ifdef HAVE_LIBZ
if (ssl->options.usingCompression)
XMEMMOVE(rawData, decomp, dataSz);
#endif
/* verify */
if (dataSz) {
if (XMEMCMP(mac, verify, digestSz)) {
if (ssl->specs.cipher_type != aead && XMEMCMP(mac, verify, digestSz)) {
CYASSL_MSG("App data verify mac error");
return VERIFY_MAC_ERROR;
}
@ -2259,6 +2460,12 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
else
GetSEQIncrement(ssl, 1); /* even though no data, increment verify */
#ifdef HAVE_LIBZ
/* decompress could be bigger, overwrite after verify */
if (ssl->options.usingCompression)
XMEMMOVE(rawData, decomp, dataSz);
#endif
*inOutIdx = idx;
return 0;
}
@ -2288,21 +2495,26 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type)
CYASSL_ERROR(*type);
if (ssl->keys.encryptionOn) {
int aSz = ALERT_SIZE;
const byte* mac;
byte verify[SHA256_DIGEST_SIZE];
int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size;
ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1);
if (ssl->specs.cipher_type != aead) {
int aSz = ALERT_SIZE;
const byte* mac;
byte verify[SHA256_DIGEST_SIZE];
int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size;
/* read mac and fill */
mac = input + *inOutIdx;
*inOutIdx += (ssl->specs.hash_size + padSz);
/* verify */
if (XMEMCMP(mac, verify, ssl->specs.hash_size)) {
CYASSL_MSG(" alert verify mac error");
return VERIFY_MAC_ERROR;
ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1);
/* read mac and fill */
mac = input + *inOutIdx;
*inOutIdx += (ssl->specs.hash_size + padSz);
/* verify */
if (XMEMCMP(mac, verify, ssl->specs.hash_size)) {
CYASSL_MSG(" alert verify mac error");
return VERIFY_MAC_ERROR;
}
}
else {
*inOutIdx += AEAD_AUTH_TAG_SZ;
}
}
@ -2820,6 +3032,11 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
sz += pad;
}
if (ssl->specs.cipher_type == aead) {
ivSz = AES_GCM_EXP_IV_SZ;
sz += (ivSz + 16 - digestSz);
RNG_GenerateBlock(&ssl->rng, iv, ivSz);
}
size = (word16)(sz - headerSz); /* include mac and digest */
AddRecordHeader(output, size, (byte)type, ssl);
@ -2833,8 +3050,10 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
if (type == handshake)
HashOutput(ssl, output, headerSz + inSz, ivSz);
ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0);
idx += digestSz;
if (ssl->specs.cipher_type != aead) {
ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0);
idx += digestSz;
}
if (ssl->specs.cipher_type == block)
for (i = 0; i <= pad; i++)
@ -3715,7 +3934,55 @@ const char* const cipher_names[] =
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
"ECDH-ECDSA-DES-CBC3-SHA"
"ECDH-ECDSA-DES-CBC3-SHA",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
"AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
"AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
"DHE-RSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
"DHE-RSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
"ECDHE-RSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
"ECDHE-RSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
"ECDHE-ECDSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
"ECDHE-ECDSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
"ECDH-RSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
"ECDH-RSA-AES256-GCM-SHA384",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
"ECDH-ECDSA-AES128-GCM-SHA256",
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
"ECDH-ECDSA-AES256-GCM-SHA384"
#endif
};
@ -3867,7 +4134,55 @@ int cipher_name_idx[] =
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
#endif
};
@ -4089,7 +4404,10 @@ int SetCipherList(Suites* s, const char* list)
length = sizeof(ProtocolVersion) + RAN_LEN
+ idSz + ENUM_LEN
+ ssl->suites.suiteSz + SUITE_LEN
+ COMP_LEN + ENUM_LEN;
+ COMP_LEN + ENUM_LEN;
if (IsAtLeastTLSv1_2(ssl))
length += HELLO_EXT_SZ;
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
@ -4155,7 +4473,29 @@ int SetCipherList(Suites* s, const char* list)
output[idx++] = ZLIB_COMPRESSION;
else
output[idx++] = NO_COMPRESSION;
if (IsAtLeastTLSv1_2(ssl))
{
/* add in the extensions length */
c16toa(HELLO_EXT_LEN, output + idx);
idx += 2;
c16toa(HELLO_EXT_SIG_ALGO, output + idx);
idx += 2;
c16toa(HELLO_EXT_SIGALGO_SZ, output + idx);
idx += 2;
/* This is a lazy list setup. Eventually, we'll need to support
* using other hash types or even other extensions. */
c16toa(HELLO_EXT_SIGALGO_LEN, output + idx);
idx += 2;
output[idx++] = sha_mac;
output[idx++] = rsa_sa_algo;
output[idx++] = sha_mac;
output[idx++] = dsa_sa_algo;
output[idx++] = sha_mac;
output[idx++] = ecc_dsa_sa_algo;
}
HashOutput(ssl, output, sendSz, 0);
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
@ -4197,12 +4537,14 @@ int SetCipherList(Suites* s, const char* list)
}
static int DoServerHello(CYASSL* ssl, const byte* input, word32* inOutIdx)
static int DoServerHello(CYASSL* ssl, const byte* input, word32* inOutIdx,
word32 helloSz)
{
byte b;
byte compression;
ProtocolVersion pv;
word32 i = *inOutIdx;
word32 begin = i;
#ifdef CYASSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
@ -4254,7 +4596,11 @@ int SetCipherList(Suites* s, const char* list)
CYASSL_MSG("Server refused compression, turning off");
ssl->options.usingCompression = 0; /* turn off if server refused */
}
*inOutIdx = i;
if ( (i - begin) < helloSz)
*inOutIdx = begin + helloSz; /* skip extensions */
ssl->options.serverState = SERVER_HELLO_COMPLETE;
*inOutIdx = i;
@ -5563,6 +5909,46 @@ int SetCipherList(Suites* s, const char* list)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
if (requirement == ecc_dsa_sa_algo)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
if (requirement == ecc_dsa_sa_algo)
return 1;
break;
case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
if (requirement == ecc_static_diffie_hellman_kea)
return 1;
break;
case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
if (requirement == ecc_static_diffie_hellman_kea)
return 1;
break;
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
if (requirement == rsa_kea)
return 1;
break;
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == rsa_kea)
return 1;
break;
case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
if (requirement == ecc_static_diffie_hellman_kea)
return 1;
break;
case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == ecc_static_diffie_hellman_kea)
return 1;
break;
default:
CYASSL_MSG("Unsupported cipher suite, CipherRequires ECC");
return 0;
@ -5679,6 +6065,20 @@ int SetCipherList(Suites* s, const char* list)
return 1;
break;
case TLS_RSA_WITH_AES_128_GCM_SHA256 :
case TLS_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == rsa_kea)
return 1;
break;
case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
if (requirement == rsa_kea)
return 1;
if (requirement == diffie_hellman_kea)
return 1;
break;
default:
CYASSL_MSG("Unsupported cipher suite, CipherRequires");
return 0;

View File

@ -311,6 +311,142 @@ int SetCipherSpecs(CYASSL* ssl)
break;
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha384_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA384_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha384_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA384_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha384_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA384_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha384_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA384_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 1;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
default:
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC");
return UNSUPPORTED_SUITE;
@ -646,6 +782,74 @@ int SetCipherSpecs(CYASSL* ssl)
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
case TLS_RSA_WITH_AES_128_GCM_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
case TLS_RSA_WITH_AES_256_GCM_SHA384 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha384_mac;
ssl->specs.kea = rsa_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA384_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_128_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
ssl->specs.bulk_cipher_algorithm = aes_gcm;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha384_mac;
ssl->specs.kea = diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA384_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = AES_256_KEY_SIZE;
ssl->specs.block_size = AES_BLOCK_SIZE;
ssl->specs.iv_size = AES_GCM_IMP_IV_SZ;
break;
#endif
default:
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs");
return UNSUPPORTED_SUITE;
@ -802,6 +1006,19 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
}
#endif
#ifdef BUILD_AESGCM
if (specs->bulk_cipher_algorithm == aes_gcm) {
if (side == CLIENT_END) {
AesGcmSetKey(&enc->aes, keys->client_write_key, specs->key_size);
AesGcmSetKey(&dec->aes, keys->server_write_key, specs->key_size);
}
else {
AesGcmSetKey(&enc->aes, keys->server_write_key, specs->key_size);
AesGcmSetKey(&dec->aes, keys->client_write_key, specs->key_size);
}
}
#endif
keys->sequence_number = 0;
keys->peer_sequence_number = 0;
keys->encryptionOn = 0;
@ -813,12 +1030,15 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
/* TLS can call too */
int StoreKeys(CYASSL* ssl, const byte* keyData)
{
int sz = ssl->specs.hash_size, i;
int sz, i = 0;
XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz);
i = sz;
XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
i += sz;
if (ssl->specs.cipher_type != aead) {
sz = ssl->specs.hash_size;
XMEMCPY(ssl->keys.client_write_MAC_secret,&keyData[i], sz);
i += sz;
XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
i += sz;
}
sz = ssl->specs.key_size;
XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz);

View File

@ -5018,6 +5018,23 @@ int CyaSSL_set_compression(CYASSL* ssl)
case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
default:
return "NONE";
}
@ -5066,6 +5083,14 @@ int CyaSSL_set_compression(CYASSL* ssl)
return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA";
case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA";
case TLS_RSA_WITH_AES_128_GCM_SHA256 :
return "TLS_RSA_WITH_AES_128_GCM_SHA256";
case TLS_RSA_WITH_AES_256_GCM_SHA384 :
return "TLS_RSA_WITH_AES_256_GCM_SHA384";
case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
default:
return "NONE";
} /* switch */

View File

@ -53,28 +53,51 @@ static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
}
#ifdef CYASSL_SHA384
#define PHASH_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE
#else
#define PHASH_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
#endif
/* compute p_hash for MD5, SHA-1, or SHA-256 for TLSv1 PRF */
/* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */
static void p_hash(byte* result, word32 resLen, const byte* secret,
word32 secLen, const byte* seed, word32 seedLen, int hash)
{
word32 len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ?
SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE;
word32 times = resLen / len;
word32 lastLen = resLen % len;
word32 len = MD5_DIGEST_SIZE;
word32 times;
word32 lastLen;
word32 lastTime;
word32 i;
word32 idx = 0;
byte previous[SHA256_DIGEST_SIZE]; /* max size */
byte current[SHA256_DIGEST_SIZE]; /* max size */
byte previous[PHASH_MAX_DIGEST_SIZE]; /* max size */
byte current[PHASH_MAX_DIGEST_SIZE]; /* max size */
Hmac hmac;
if (hash == md5_mac) {
hash = MD5;
}
else if (hash == sha_mac) {
len = SHA_DIGEST_SIZE;
hash = SHA;
} else if (hash == sha256_mac) {
len = SHA256_DIGEST_SIZE;
hash = SHA256;
}
#ifdef CYASSL_SHA384
else if (hash == sha384_mac)
{
len = SHA384_DIGEST_SIZE;
hash = SHA384;
}
#endif
times = resLen / len;
lastLen = resLen % len;
if (lastLen) times += 1;
lastTime = times - 1;
HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256,
secret, secLen);
HmacSetKey(&hmac, hash, secret, secLen);
HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */
HmacFinal(&hmac, previous); /* A1 */
@ -99,7 +122,7 @@ static void p_hash(byte* result, word32 resLen, const byte* secret,
/* compute TLSv1 PRF (pseudo random function using HMAC) */
static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
const byte* label, word32 labLen, const byte* seed, word32 seedLen,
int useSha256)
int useAtLeastSha256, int hash_type)
{
word32 half = (secLen + 1) / 2;
@ -122,9 +145,13 @@ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
XMEMCPY(labelSeed, label, labLen);
XMEMCPY(labelSeed + labLen, seed, seedLen);
if (useSha256) {
if (useAtLeastSha256) {
/* If a cipher suite wants an algorithm better than sha256, it
* should use better. */
if (hash_type < sha256_mac)
hash_type = sha256_mac;
p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen,
sha256_mac);
hash_type);
return;
}
@ -136,20 +163,35 @@ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
}
#ifdef CYASSL_SHA384
#define HSHASH_SZ SHA384_DIGEST_SIZE
#else
#define HSHASH_SZ FINISHED_SZ
#endif
void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
{
const byte* side;
byte handshake_hash[FINISHED_SZ];
byte handshake_hash[HSHASH_SZ];
word32 hashSz = FINISHED_SZ;
Md5Final(&ssl->hashMd5, handshake_hash);
ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl)) {
Sha256Final(&ssl->hashSha256, handshake_hash);
hashSz = SHA256_DIGEST_SIZE;
}
#ifndef NO_SHA256
if (ssl->specs.mac_algorithm <= sha256_mac) {
Sha256Final(&ssl->hashSha256, handshake_hash);
hashSz = SHA256_DIGEST_SIZE;
}
#endif
#ifdef CYASSL_SHA384
if (ssl->specs.mac_algorithm == sha384_mac) {
Sha384Final(&ssl->hashSha384, handshake_hash);
hashSz = SHA384_DIGEST_SIZE;
}
#endif
}
if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
side = tls_client;
@ -157,7 +199,8 @@ void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
side = tls_server;
PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN,
side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl));
side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl),
ssl->specs.mac_algorithm);
}
@ -207,7 +250,8 @@ int DeriveTlsKeys(CYASSL* ssl)
XMEMCPY(&seed[RAN_LEN], ssl->arrays.clientRandom, RAN_LEN);
PRF(key_data, length, ssl->arrays.masterSecret, SECRET_LEN, key_label,
KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl),
ssl->specs.mac_algorithm);
return StoreKeys(ssl, key_data);
}
@ -223,7 +267,7 @@ int MakeTlsMasterSecret(CYASSL* ssl)
PRF(ssl->arrays.masterSecret, SECRET_LEN,
ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz,
master_label, MASTER_LABEL_SZ,
seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm);
#ifdef SHOW_SECRETS
{