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

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

View File

@@ -296,9 +296,27 @@ AC_ARG_ENABLE(aesgcm,
[ ENABLED_AESGCM=no ] [ 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" if test "$ENABLED_AESGCM" = "yes"
then then
AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM" AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM -DCYASSL_SHA384 -DCYASSL_SHA512"
fi fi
AM_CONDITIONAL([BUILD_AESGCM], [test "x$ENABLED_AESGCM" = "xyes"]) AM_CONDITIONAL([BUILD_AESGCM], [test "x$ENABLED_AESGCM" = "xyes"])
@@ -355,6 +373,11 @@ then
ENABLED_SHA512="yes" ENABLED_SHA512="yes"
fi fi
if test "$ENABLED_AESGCM" = "yes"
then
ENABLED_SHA512="yes"
fi
AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"]) AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"])

View File

@@ -54,6 +54,7 @@ void bench_arc4();
void bench_hc128(); void bench_hc128();
void bench_rabbit(); void bench_rabbit();
void bench_aes(int); void bench_aes(int);
void bench_aesgcm();
void bench_md5(); void bench_md5();
void bench_sha(); void bench_sha();
@@ -78,6 +79,9 @@ int main(int argc, char** argv)
#ifndef NO_AES #ifndef NO_AES
bench_aes(0); bench_aes(0);
bench_aes(1); bench_aes(1);
#endif
#ifdef HAVE_AESGCM
bench_aesgcm();
#endif #endif
bench_arc4(); bench_arc4();
#ifdef HAVE_HC128 #ifdef HAVE_HC128
@@ -171,6 +175,34 @@ void bench_aes(int show)
#endif #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 #ifndef NO_DES3
void bench_des() 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 i;
int carryOut = 0; int carryOut = 0;
int carryIn = 0; int carryIn = 0;
int borrow = x[15] & 0x01;
for (i = 0; i < AES_BLOCK_SIZE; i++) { for (i = 0; i < AES_BLOCK_SIZE; i++) {
carryOut = x[i] & 0x01; carryOut = x[i] & 0x01;
x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0); x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0);
carryIn = carryOut; 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) static void GMULT(byte* X, byte* Y)
{ {
byte R[AES_BLOCK_SIZE];
byte Z[AES_BLOCK_SIZE]; byte Z[AES_BLOCK_SIZE];
byte V[AES_BLOCK_SIZE]; byte V[AES_BLOCK_SIZE];
int i, j; int i, j;
XMEMSET(R, 0, AES_BLOCK_SIZE);
R[0] = 0xE1;
XMEMSET(Z, 0, AES_BLOCK_SIZE); XMEMSET(Z, 0, AES_BLOCK_SIZE);
XMEMCPY(V, X, AES_BLOCK_SIZE); XMEMCPY(V, X, AES_BLOCK_SIZE);
for (i = 0; i < AES_BLOCK_SIZE; i++) 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); xorbuf(Z, V, AES_BLOCK_SIZE);
} }
if (V[15] & 0x01) { RIGHTSHIFTX(V);
RIGHTSHIFT(V);
xorbuf(V, R, AES_BLOCK_SIZE);
} else {
RIGHTSHIFT(V);
}
y = y << 1; 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) const byte* c, word32 cSz, byte* s, word32 sSz)
{ {
byte x[AES_BLOCK_SIZE]; byte x[AES_BLOCK_SIZE];
byte scratch[AES_BLOCK_SIZE];
word32 blocks, partial; word32 blocks, partial;
byte* h = aes->H;
XMEMSET(x, 0, AES_BLOCK_SIZE); XMEMSET(x, 0, AES_BLOCK_SIZE);
@@ -1493,7 +1553,6 @@ static void GHASH(byte* h, const byte* a, word32 aSz,
a += AES_BLOCK_SIZE; a += AES_BLOCK_SIZE;
} }
if (partial != 0) { if (partial != 0) {
byte scratch[AES_BLOCK_SIZE];
XMEMSET(scratch, 0, AES_BLOCK_SIZE); XMEMSET(scratch, 0, AES_BLOCK_SIZE);
XMEMCPY(scratch, a, partial); XMEMCPY(scratch, a, partial);
xorbuf(x, scratch, AES_BLOCK_SIZE); xorbuf(x, scratch, AES_BLOCK_SIZE);
@@ -1511,7 +1570,6 @@ static void GHASH(byte* h, const byte* a, word32 aSz,
c += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE;
} }
if (partial != 0) { if (partial != 0) {
byte scratch[AES_BLOCK_SIZE];
XMEMSET(scratch, 0, AES_BLOCK_SIZE); XMEMSET(scratch, 0, AES_BLOCK_SIZE);
XMEMCPY(scratch, c, partial); XMEMCPY(scratch, c, partial);
xorbuf(x, scratch, AES_BLOCK_SIZE); 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 */ /* Hash in the lengths of A and C in bits */
{ FlattenSzInBits(&scratch[0], aSz);
byte len[AES_BLOCK_SIZE]; FlattenSzInBits(&scratch[8], cSz);
XMEMSET(len, 0, AES_BLOCK_SIZE); xorbuf(x, scratch, AES_BLOCK_SIZE);
len[3] = aSz >> 29;
len[4] = aSz >> 21;
len[5] = aSz >> 13;
len[6] = aSz >> 5;
len[7] = aSz << 3;
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); GMULT(x, h);
}
/* Copy the result into s. */
XMEMCPY(s, x, sSz); 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, void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
byte* authTag, word32 authTagSz, 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; word32 partial = sz % AES_BLOCK_SIZE;
const byte* p = in; const byte* p = in;
byte* c = out; byte* c = out;
byte h[AES_BLOCK_SIZE];
byte ctr[AES_BLOCK_SIZE]; byte ctr[AES_BLOCK_SIZE];
byte scratch[AES_BLOCK_SIZE];
CYASSL_ENTER("AesGcmEncrypt"); 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 /* Initialize the counter with the MS 96 bits of IV, and the counter
* portion set to "1". */ * portion set to "1". */
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE - 4); XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE);
InitGcmCounter(ctr); InitGcmCounter(ctr);
while (blocks--) { while (blocks--) {
IncrementGcmCounter(ctr); IncrementGcmCounter(ctr);
AesEncrypt(aes, ctr, c); AesEncrypt(aes, ctr, scratch);
xorbuf(c, p, AES_BLOCK_SIZE); xorbuf(scratch, p, AES_BLOCK_SIZE);
XMEMCPY(c, scratch, AES_BLOCK_SIZE);
p += AES_BLOCK_SIZE; p += AES_BLOCK_SIZE;
c += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE;
} }
if (partial != 0) { if (partial != 0) {
byte cPartial[AES_BLOCK_SIZE];
IncrementGcmCounter(ctr); IncrementGcmCounter(ctr);
AesEncrypt(aes, ctr, cPartial); AesEncrypt(aes, ctr, scratch);
XMEMCPY(c, cPartial, partial); xorbuf(scratch, p, partial);
xorbuf(c, p, partial); XMEMCPY(c, scratch, partial);
} }
GHASH(h, authIn, authInSz, out, sz, authTag, authTagSz); GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
InitGcmCounter(ctr); InitGcmCounter(ctr);
AesEncrypt(aes, ctr, h); AesEncrypt(aes, ctr, scratch);
xorbuf(authTag, h, authTagSz); 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; word32 partial = sz % AES_BLOCK_SIZE;
const byte* c = in; const byte* c = in;
byte* p = out; byte* p = out;
byte h[AES_BLOCK_SIZE];
byte ctr[AES_BLOCK_SIZE]; byte ctr[AES_BLOCK_SIZE];
byte scratch[AES_BLOCK_SIZE];
CYASSL_ENTER("AesGcmDecrypt"); 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 /* Initialize the counter with the MS 96 bits of IV, and the counter
* portion set to "1". */ * portion set to "1". */
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE - 4); XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE);
InitGcmCounter(ctr); InitGcmCounter(ctr);
/* Calculate the authTag again using the received auth data and the /* 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 Tprime[AES_BLOCK_SIZE];
byte EKY0[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); AesEncrypt(aes, ctr, EKY0);
xorbuf(Tprime, EKY0, sizeof(Tprime)); xorbuf(Tprime, EKY0, sizeof(Tprime));
if (XMEMCMP(authTag, Tprime, authTagSz) != 0) { if (XMEMCMP(authTag, Tprime, authTagSz) != 0) {
@@ -1624,19 +2079,18 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
while (blocks--) { while (blocks--) {
IncrementGcmCounter(ctr); IncrementGcmCounter(ctr);
AesEncrypt(aes, ctr, p); AesEncrypt(aes, ctr, scratch);
xorbuf(p, c, AES_BLOCK_SIZE); xorbuf(scratch, c, AES_BLOCK_SIZE);
XMEMCPY(p, scratch, AES_BLOCK_SIZE);
p += AES_BLOCK_SIZE; p += AES_BLOCK_SIZE;
c += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE;
} }
if (partial != 0) { if (partial != 0) {
byte pPartial[AES_BLOCK_SIZE];
IncrementGcmCounter(ctr); IncrementGcmCounter(ctr);
AesEncrypt(aes, ctr, pPartial); AesEncrypt(aes, ctr, scratch);
XMEMCPY(p, pPartial, partial); xorbuf(scratch, c, partial);
xorbuf(p, c, partial); XMEMCPY(p, scratch, partial);
} }
return 0; return 0;

View File

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

View File

@@ -99,6 +99,7 @@ int rabbit_test();
int des_test(); int des_test();
int des3_test(); int des3_test();
int aes_test(); int aes_test();
int aesgcm_test();
int rsa_test(); int rsa_test();
int dh_test(); int dh_test();
int dsa_test(); int dsa_test();
@@ -233,6 +234,13 @@ void ctaocrypt_test(void* args)
err_sys("AES test failed!\n", ret); err_sys("AES test failed!\n", ret);
else else
printf( "AES test passed!\n"); 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 #endif
if ( (ret = random_test()) ) if ( (ret = random_test()) )
@@ -1144,8 +1152,14 @@ int aes_test()
} }
#endif /* CYASSL_AES_COUNTER */ #endif /* CYASSL_AES_COUNTER */
return 0;
}
#ifdef HAVE_AESGCM #ifdef HAVE_AESGCM
int aesgcm_test()
{ {
Aes enc;
/* /*
* This is Test Case 16 from the document Galois/ * This is Test Case 16 from the document Galois/
* Counter Mode of Operation (GCM) by McGrew and * Counter Mode of Operation (GCM) by McGrew and
@@ -1212,7 +1226,8 @@ int aes_test()
memset(c2, 0, 60); memset(c2, 0, 60);
memset(p2, 0, 60); memset(p2, 0, 60);
AesSetKey(&enc, k, sizeof(k), iv, AES_ENCRYPTION); AesGcmSetKey(&enc, k, sizeof(k));
AesSetIV(&enc, iv);
/* AES-GCM encrypt and decrypt both use AES encrypt internally */ /* AES-GCM encrypt and decrypt both use AES encrypt internally */
AesGcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a)); AesGcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a));
if (memcmp(c, c2, sizeof(c2))) if (memcmp(c, c2, sizeof(c2)))
@@ -1226,11 +1241,12 @@ int aes_test()
return -70; return -70;
if (memcmp(p, p2, sizeof(p2))) if (memcmp(p, p2, sizeof(p2)))
return -71; return -71;
}
#endif /* HAVE_AESGCM */
return 0; return 0;
} }
#endif /* HAVE_AESGCM */
#endif /* NO_AES */ #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 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ 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; } 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); CYASSL_API void AesDecryptDirect(Aes* aes, byte* out, const byte* in);
#ifdef HAVE_AESGCM #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, CYASSL_API void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
byte* authTag, word32 authTagSz, byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz); const byte* authIn, word32 authInSz);

View File

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

View File

@@ -44,6 +44,9 @@
#ifdef HAVE_OCSP #ifdef HAVE_OCSP
#include <cyassl/ocsp.h> #include <cyassl/ocsp.h>
#endif #endif
#ifdef CYASSL_SHA512
#include <cyassl/ctaocrypt/sha512.h>
#endif
#ifdef CYASSL_CALLBACKS #ifdef CYASSL_CALLBACKS
#include <cyassl/openssl/cyassl_callbacks.h> #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_128_CBC_SHA256
#define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
#endif #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 #endif
#if !defined(NO_HC128) && !defined(NO_TLS) #if !defined(NO_HC128) && !defined(NO_TLS)
@@ -164,6 +171,10 @@ void c32to24(word32 in, word24 out);
#if !defined (NO_SHA256) #if !defined (NO_SHA256)
#define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
#define BUILD_TLS_DHE_RSA_WITH_AES_256_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
#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_RSA_WITH_AES_256_CBC_SHA
#define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
#define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_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 #endif
#if !defined(NO_RC4) #if !defined(NO_RC4)
#define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
@@ -210,6 +233,11 @@ void c32to24(word32 in, word24 out);
#define BUILD_AES #define BUILD_AES
#endif #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) || \ #if defined(BUILD_TLS_RSA_WITH_HC_128_CBC_SHA) || \
defined(BUILD_TLS_RSA_WITH_HC_128_CBC_MD5) defined(BUILD_TLS_RSA_WITH_HC_128_CBC_MD5)
#define BUILD_HC128 #define BUILD_HC128
@@ -275,7 +303,23 @@ enum {
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67,
TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x3d, 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 */ TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */
NO_COMPRESSION = 0, NO_COMPRESSION = 0,
ZLIB_COMPRESSION = 221, /* CyaSSL zlib compression */ 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 */ SECRET_LEN = 48, /* pre RSA and all master */
ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */ ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */
SIZEOF_SENDER = 4, /* clnt or srvr */ SIZEOF_SENDER = 4, /* clnt or srvr */
@@ -338,6 +383,10 @@ enum Misc {
CERT_HEADER_SZ = 3, /* always 3 bytes */ CERT_HEADER_SZ = 3, /* always 3 bytes */
REQ_HEADER_SZ = 2, /* cert request header sz */ REQ_HEADER_SZ = 2, /* cert request header sz */
HINT_LEN_SZ = 2, /* length of hint size field */ 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_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */ 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_256_KEY_SIZE = 32, /* for 256 bit */
AES_192_KEY_SIZE = 24, /* for 192 bit */ AES_192_KEY_SIZE = 24, /* for 192 bit */
AES_IV_SIZE = 16, /* always block size */ 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 */ 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_KEY_SIZE = 16, /* 128 bits */
HC_128_IV_SIZE = 16, /* also 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 */ /* All cipher suite related info */
typedef struct CipherSpecs { typedef struct CipherSpecs {
byte bulk_cipher_algorithm; byte bulk_cipher_algorithm;
byte cipher_type; /* block or stream */ byte cipher_type; /* block, stream, or aead */
byte mac_algorithm; byte mac_algorithm;
byte kea; /* key exchange algo */ byte kea; /* key exchange algo */
byte sig_algo; byte sig_algo;
@@ -789,6 +849,7 @@ enum BulkCipherAlgorithm {
des40, des40,
idea, idea,
aes, aes,
aes_gcm,
hc128, /* CyaSSL extensions */ hc128, /* CyaSSL extensions */
rabbit rabbit
}; };
@@ -859,7 +920,7 @@ enum ClientCertificateType {
}; };
enum CipherType { stream, block }; enum CipherType { stream, block, aead };
/* keys and secrets */ /* keys and secrets */
@@ -1129,6 +1190,9 @@ struct CYASSL {
Sha hashSha; /* sha hash of handshake msgs */ Sha hashSha; /* sha hash of handshake msgs */
#ifndef NO_SHA256 #ifndef NO_SHA256
Sha256 hashSha256; /* sha256 hash of handshake msgs */ Sha256 hashSha256; /* sha256 hash of handshake msgs */
#endif
#ifdef CYASSL_SHA384
Sha384 hashSha384; /* sha384 hash of handshake msgs */
#endif #endif
Hashes verifyHashes; Hashes verifyHashes;
Hashes certHashes; /* for cert verify */ Hashes certHashes; /* for cert verify */

View File

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

View File

@@ -55,7 +55,7 @@
#ifndef NO_CYASSL_CLIENT #ifndef NO_CYASSL_CLIENT
static int DoHelloVerifyRequest(CYASSL* ssl, const byte* input, word32*); 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 DoCertificateRequest(CYASSL* ssl, const byte* input, word32*);
static int DoServerKeyExchange(CYASSL* ssl, const byte* input, word32*); static int DoServerKeyExchange(CYASSL* ssl, const byte* input, word32*);
#endif #endif
@@ -239,7 +239,8 @@ static INLINE void ato32(const byte* c, word32* u32)
ssl->c_stream.zfree = (free_func)myFree; ssl->c_stream.zfree = (free_func)myFree;
ssl->c_stream.opaque = (voidpf)ssl->heap; 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; ssl->didStreamInit = 1;
@@ -268,11 +269,6 @@ static INLINE void ato32(const byte* c, word32* u32)
int err; int err;
int currTotal = ssl->c_stream.total_out; 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.next_in = in;
ssl->c_stream.avail_in = inSz; ssl->c_stream.avail_in = inSz;
ssl->c_stream.next_out = out; 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); err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR; 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 err;
int currTotal = ssl->d_stream.total_out; 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.next_in = in;
ssl->d_stream.avail_in = inSz; ssl->d_stream.avail_in = inSz;
@@ -498,6 +488,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
if (tls && haveECDSA) { if (tls && haveECDSA) {
suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = ECC_BYTE;
@@ -505,6 +502,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
if (tls && haveECDSA && haveStaticECC) { if (tls && haveECDSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = ECC_BYTE;
@@ -512,6 +516,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
if (tls && haveECDSA) { if (tls && haveECDSA) {
suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = ECC_BYTE;
@@ -519,6 +530,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
if (tls && haveECDSA && haveStaticECC) { if (tls && haveECDSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = ECC_BYTE;
@@ -554,6 +572,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA) { if (tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = ECC_BYTE;
@@ -561,6 +586,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
if (tls && haveRSA && haveStaticECC) { if (tls && haveRSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = ECC_BYTE;
@@ -568,6 +600,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA) { if (tls && haveRSA) {
suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = ECC_BYTE;
@@ -575,6 +614,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
if (tls && haveRSA && haveStaticECC) { if (tls && haveRSA && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = ECC_BYTE;
@@ -610,6 +656,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
if (tls1_2 && haveDH && haveRSA) { if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0; suites->suites[idx++] = 0;
@@ -617,6 +670,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveDH && haveRSA) { if (tls1_2 && haveDH && haveRSA) {
suites->suites[idx++] = 0; suites->suites[idx++] = 0;
@@ -638,6 +698,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
if (tls1_2 && haveRSA) { if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0; suites->suites[idx++] = 0;
@@ -645,6 +712,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
} }
#endif #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 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
if (tls1_2 && haveRSA) { if (tls1_2 && haveRSA) {
suites->suites[idx++] = 0; suites->suites[idx++] = 0;
@@ -793,6 +867,9 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
InitSha(&ssl->hashSha); InitSha(&ssl->hashSha);
#ifndef NO_SHA256 #ifndef NO_SHA256
InitSha256(&ssl->hashSha256); InitSha256(&ssl->hashSha256);
#endif
#ifdef CYASSL_SHA384
InitSha384(&ssl->hashSha384);
#endif #endif
InitRsaKey(&ssl->peerRsaKey, ctx->heap); 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); Md5Update(&ssl->hashMd5, adj, sz);
ShaUpdate(&ssl->hashSha, adj, sz); ShaUpdate(&ssl->hashSha, adj, sz);
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256 #ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
Sha256Update(&ssl->hashSha256, adj, sz); Sha256Update(&ssl->hashSha256, adj, sz);
#endif #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); Md5Update(&ssl->hashMd5, adj, sz);
ShaUpdate(&ssl->hashSha, adj, sz); ShaUpdate(&ssl->hashSha, adj, sz);
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256 #ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
Sha256Update(&ssl->hashSha256, adj, sz); Sha256Update(&ssl->hashSha256, adj, sz);
#endif #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; Sha sha = ssl->hashSha;
#ifndef NO_SHA256 #ifndef NO_SHA256
Sha256 sha256; Sha256 sha256;
#endif
#ifdef CYASSL_SHA384
Sha384 sha384;
#endif
#ifndef NO_SHA256
InitSha256(&sha256); InitSha256(&sha256);
if (IsAtLeastTLSv1_2(ssl)) if (IsAtLeastTLSv1_2(ssl))
sha256 = ssl->hashSha256; sha256 = ssl->hashSha256;
#endif #endif
#ifdef CYASSL_SHA384
InitSha384(&sha384);
if (IsAtLeastTLSv1_2(ssl))
sha384 = ssl->hashSha384;
#endif
if (ssl->options.tls) if (ssl->options.tls)
BuildTlsFinished(ssl, hashes, sender); BuildTlsFinished(ssl, hashes, sender);
@@ -1554,10 +1650,14 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
/* restore */ /* restore */
ssl->hashMd5 = md5; ssl->hashMd5 = md5;
ssl->hashSha = sha; ssl->hashSha = sha;
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256 #ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
ssl->hashSha256 = sha256; ssl->hashSha256 = sha256;
#endif #endif
#ifdef CYASSL_SHA384
ssl->hashSha384 = sha384;
#endif
}
} }
@@ -1936,6 +2036,7 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
} }
} }
if (ssl->specs.cipher_type != aead) {
ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz, ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz,
handshake, 1); handshake, 1);
idx += finishedSz; idx += finishedSz;
@@ -1954,6 +2055,10 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
CYASSL_MSG("Verify finished error on mac"); CYASSL_MSG("Verify finished error on mac");
return VERIFY_MAC_ERROR; return VERIFY_MAC_ERROR;
} }
}
else {
idx += (finishedSz + AEAD_AUTH_TAG_SZ);
}
if (ssl->options.side == CLIENT_END) { if (ssl->options.side == CLIENT_END) {
ssl->options.serverState = SERVER_FINISHED_COMPLETE; ssl->options.serverState = SERVER_FINISHED_COMPLETE;
@@ -2012,7 +2117,7 @@ static int DoHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx,
case server_hello: case server_hello:
CYASSL_MSG("processing server hello"); CYASSL_MSG("processing server hello");
ret = DoServerHello(ssl, input, inOutIdx); ret = DoServerHello(ssl, input, inOutIdx, size);
break; break;
case certificate_request: 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) static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
{ {
switch (ssl->specs.bulk_cipher_algorithm) { switch (ssl->specs.bulk_cipher_algorithm) {
@@ -2105,6 +2219,50 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
break; break;
#endif #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 #ifdef HAVE_HC128
case hc128: case hc128:
Hc128_Process(&ssl->encrypt.hc128, out, input, sz); 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) word32 sz)
{ {
switch (ssl->specs.bulk_cipher_algorithm) { switch (ssl->specs.bulk_cipher_algorithm) {
@@ -2145,6 +2303,51 @@ static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input,
break; break;
#endif #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 #ifdef HAVE_HC128
case hc128: case hc128:
Hc128_Process(&ssl->decrypt.hc128, plain, input, sz); Hc128_Process(&ssl->decrypt.hc128, plain, input, sz);
@@ -2160,27 +2363,25 @@ static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input,
default: default:
CYASSL_MSG("CyaSSL Decrypt programming error"); CYASSL_MSG("CyaSSL Decrypt programming error");
} }
return 0;
} }
/* decrypt input message in place */ /* decrypt input message in place */
static int DecryptMessage(CYASSL* ssl, byte* input, word32 sz, word32* idx) static int DecryptMessage(CYASSL* ssl, byte* input, word32 sz, word32* idx)
{ {
Decrypt(ssl, input, input, sz); int decryptResult = Decrypt(ssl, input, input, sz);
if (decryptResult == 0)
{
ssl->keys.encryptSz = sz; ssl->keys.encryptSz = sz;
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
*idx += ssl->specs.block_size; /* go past TLSv1.1 IV */ *idx += ssl->specs.block_size; /* go past TLSv1.1 IV */
if (ssl->specs.cipher_type == aead)
return 0; *idx += AES_GCM_EXP_IV_SZ;
} }
return decryptResult;
static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
{
if (verify)
return ssl->keys.peer_sequence_number++;
else
return ssl->keys.sequence_number++;
} }
@@ -2207,6 +2408,10 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
pad = *(input + idx + msgSz - ivExtra - 1); pad = *(input + idx + msgSz - ivExtra - 1);
padByte = 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; dataSz = msgSz - ivExtra - digestSz - pad - padByte;
if (dataSz < 0) { if (dataSz < 0) {
@@ -2218,6 +2423,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
if (dataSz) { if (dataSz) {
int rawSz = dataSz; /* keep raw size for hmac */ int rawSz = dataSz; /* keep raw size for hmac */
if (ssl->specs.cipher_type != aead)
ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1); ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1);
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
@@ -2244,14 +2450,9 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
if (padByte) if (padByte)
idx++; idx++;
#ifdef HAVE_LIBZ
if (ssl->options.usingCompression)
XMEMMOVE(rawData, decomp, dataSz);
#endif
/* verify */ /* verify */
if (dataSz) { if (dataSz) {
if (XMEMCMP(mac, verify, digestSz)) { if (ssl->specs.cipher_type != aead && XMEMCMP(mac, verify, digestSz)) {
CYASSL_MSG("App data verify mac error"); CYASSL_MSG("App data verify mac error");
return VERIFY_MAC_ERROR; return VERIFY_MAC_ERROR;
} }
@@ -2259,6 +2460,12 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
else else
GetSEQIncrement(ssl, 1); /* even though no data, increment verify */ 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; *inOutIdx = idx;
return 0; return 0;
} }
@@ -2288,6 +2495,7 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type)
CYASSL_ERROR(*type); CYASSL_ERROR(*type);
if (ssl->keys.encryptionOn) { if (ssl->keys.encryptionOn) {
if (ssl->specs.cipher_type != aead) {
int aSz = ALERT_SIZE; int aSz = ALERT_SIZE;
const byte* mac; const byte* mac;
byte verify[SHA256_DIGEST_SIZE]; byte verify[SHA256_DIGEST_SIZE];
@@ -2305,6 +2513,10 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type)
return VERIFY_MAC_ERROR; return VERIFY_MAC_ERROR;
} }
} }
else {
*inOutIdx += AEAD_AUTH_TAG_SZ;
}
}
return level; return level;
} }
@@ -2820,6 +3032,11 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
sz += pad; 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 */ size = (word16)(sz - headerSz); /* include mac and digest */
AddRecordHeader(output, size, (byte)type, ssl); 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) if (type == handshake)
HashOutput(ssl, output, headerSz + inSz, ivSz); HashOutput(ssl, output, headerSz + inSz, ivSz);
if (ssl->specs.cipher_type != aead) {
ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0); ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0);
idx += digestSz; idx += digestSz;
}
if (ssl->specs.cipher_type == block) if (ssl->specs.cipher_type == block)
for (i = 0; i <= pad; i++) for (i = 0; i <= pad; i++)
@@ -3715,7 +3934,55 @@ const char* const cipher_names[] =
#endif #endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA #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 #endif
}; };
@@ -3867,7 +4134,55 @@ int cipher_name_idx[] =
#endif #endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA #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 #endif
}; };
@@ -4091,6 +4406,9 @@ int SetCipherList(Suites* s, const char* list)
+ ssl->suites.suiteSz + SUITE_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; sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
#ifdef CYASSL_DTLS #ifdef CYASSL_DTLS
@@ -4156,6 +4474,28 @@ int SetCipherList(Suites* s, const char* list)
else else
output[idx++] = NO_COMPRESSION; 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); HashOutput(ssl, output, sendSz, 0);
ssl->options.clientState = CLIENT_HELLO_COMPLETE; 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 b;
byte compression; byte compression;
ProtocolVersion pv; ProtocolVersion pv;
word32 i = *inOutIdx; word32 i = *inOutIdx;
word32 begin = i;
#ifdef CYASSL_CALLBACKS #ifdef CYASSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
@@ -4255,6 +4597,10 @@ int SetCipherList(Suites* s, const char* list)
ssl->options.usingCompression = 0; /* turn off if server refused */ 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; ssl->options.serverState = SERVER_HELLO_COMPLETE;
*inOutIdx = i; *inOutIdx = i;
@@ -5563,6 +5909,46 @@ int SetCipherList(Suites* s, const char* list)
return 1; return 1;
break; 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: default:
CYASSL_MSG("Unsupported cipher suite, CipherRequires ECC"); CYASSL_MSG("Unsupported cipher suite, CipherRequires ECC");
return 0; return 0;
@@ -5679,6 +6065,20 @@ int SetCipherList(Suites* s, const char* list)
return 1; return 1;
break; 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: default:
CYASSL_MSG("Unsupported cipher suite, CipherRequires"); CYASSL_MSG("Unsupported cipher suite, CipherRequires");
return 0; return 0;

View File

@@ -311,6 +311,142 @@ int SetCipherSpecs(CYASSL* ssl)
break; break;
#endif #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: default:
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC"); CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC");
return UNSUPPORTED_SUITE; return UNSUPPORTED_SUITE;
@@ -646,6 +782,74 @@ int SetCipherSpecs(CYASSL* ssl)
break; break;
#endif #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: default:
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs"); CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs");
return UNSUPPORTED_SUITE; return UNSUPPORTED_SUITE;
@@ -802,6 +1006,19 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
} }
#endif #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->sequence_number = 0;
keys->peer_sequence_number = 0; keys->peer_sequence_number = 0;
keys->encryptionOn = 0; keys->encryptionOn = 0;
@@ -813,12 +1030,15 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
/* TLS can call too */ /* TLS can call too */
int StoreKeys(CYASSL* ssl, const byte* keyData) 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); if (ssl->specs.cipher_type != aead) {
i = sz; 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); XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
i += sz; i += sz;
}
sz = ssl->specs.key_size; sz = ssl->specs.key_size;
XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz); 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 : case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
return "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: default:
return "NONE"; return "NONE";
} }
@@ -5066,6 +5083,14 @@ int CyaSSL_set_compression(CYASSL* ssl)
return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA"; return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA";
case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
return "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: default:
return "NONE"; return "NONE";
} /* switch */ } /* 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, static void p_hash(byte* result, word32 resLen, const byte* secret,
word32 secLen, const byte* seed, word32 seedLen, int hash) word32 secLen, const byte* seed, word32 seedLen, int hash)
{ {
word32 len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ? word32 len = MD5_DIGEST_SIZE;
SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE; word32 times;
word32 times = resLen / len; word32 lastLen;
word32 lastLen = resLen % len;
word32 lastTime; word32 lastTime;
word32 i; word32 i;
word32 idx = 0; word32 idx = 0;
byte previous[SHA256_DIGEST_SIZE]; /* max size */ byte previous[PHASH_MAX_DIGEST_SIZE]; /* max size */
byte current[SHA256_DIGEST_SIZE]; /* max size */ byte current[PHASH_MAX_DIGEST_SIZE]; /* max size */
Hmac hmac; 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; if (lastLen) times += 1;
lastTime = times - 1; lastTime = times - 1;
HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256, HmacSetKey(&hmac, hash, secret, secLen);
secret, secLen);
HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */ HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */
HmacFinal(&hmac, previous); /* A1 */ 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) */ /* compute TLSv1 PRF (pseudo random function using HMAC) */
static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
const byte* label, word32 labLen, const byte* seed, word32 seedLen, const byte* label, word32 labLen, const byte* seed, word32 seedLen,
int useSha256) int useAtLeastSha256, int hash_type)
{ {
word32 half = (secLen + 1) / 2; 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, label, labLen);
XMEMCPY(labelSeed + labLen, seed, seedLen); 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, p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen,
sha256_mac); hash_type);
return; 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) void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
{ {
const byte* side; const byte* side;
byte handshake_hash[FINISHED_SZ]; byte handshake_hash[HSHASH_SZ];
word32 hashSz = FINISHED_SZ; word32 hashSz = FINISHED_SZ;
Md5Final(&ssl->hashMd5, handshake_hash); Md5Final(&ssl->hashMd5, handshake_hash);
ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]); ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl)) { if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256
if (ssl->specs.mac_algorithm <= sha256_mac) {
Sha256Final(&ssl->hashSha256, handshake_hash); Sha256Final(&ssl->hashSha256, handshake_hash);
hashSz = SHA256_DIGEST_SIZE; hashSz = SHA256_DIGEST_SIZE;
} }
#endif #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) if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
side = tls_client; side = tls_client;
@@ -157,7 +199,8 @@ void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
side = tls_server; side = tls_server;
PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN, 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); XMEMCPY(&seed[RAN_LEN], ssl->arrays.clientRandom, RAN_LEN);
PRF(key_data, length, ssl->arrays.masterSecret, SECRET_LEN, key_label, 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); return StoreKeys(ssl, key_data);
} }
@@ -223,7 +267,7 @@ int MakeTlsMasterSecret(CYASSL* ssl)
PRF(ssl->arrays.masterSecret, SECRET_LEN, PRF(ssl->arrays.masterSecret, SECRET_LEN,
ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz, ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz,
master_label, MASTER_LABEL_SZ, master_label, MASTER_LABEL_SZ,
seed, SEED_LEN, IsAtLeastTLSv1_2(ssl)); seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm);
#ifdef SHOW_SECRETS #ifdef SHOW_SECRETS
{ {