Initial draft of AES GCM cipher suites. Missing SHA-384 support.
This commit is contained in:
parent
737cd127e8
commit
3a9a195683
@ -233,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
|
||||
@ -398,6 +403,8 @@ 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_IMPLICIT_IV_SIZE = 4, /* Implicit half of IV */
|
||||
AES_GCM_EXPLICIT_IV_SIZE = 8, /* Explicit half of IV */
|
||||
AES_128_KEY_SIZE = 16, /* for 128 bit */
|
||||
|
||||
HC_128_KEY_SIZE = 16, /* 128 bits */
|
||||
@ -1167,6 +1174,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 */
|
||||
|
144
src/internal.c
144
src/internal.c
@ -886,6 +886,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);
|
||||
|
||||
@ -1177,10 +1180,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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1199,10 +1206,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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1624,6 +1635,12 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
|
||||
if (IsAtLeastTLSv1_2(ssl))
|
||||
sha256 = ssl->hashSha256;
|
||||
#endif
|
||||
#if CYASSL_SHA384
|
||||
Sha384 sha384;
|
||||
InitSha384(&sha384);
|
||||
if (IsAtLeastTLSv1_2(ssl))
|
||||
sha384 = ssl->hashSha384;
|
||||
#endif
|
||||
|
||||
if (ssl->options.tls)
|
||||
BuildTlsFinished(ssl, hashes, sender);
|
||||
@ -1639,6 +1656,10 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
|
||||
if (IsAtLeastTLSv1_2(ssl))
|
||||
ssl->hashSha256 = sha256;
|
||||
#endif
|
||||
#ifdef CYASSL_SHA384
|
||||
if (IsAtLeastTLSv1_2(ssl))
|
||||
ssl->hashSha384 = sha384;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -2017,6 +2038,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,
|
||||
handshake, 1);
|
||||
idx += finishedSz;
|
||||
@ -2035,6 +2057,11 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
|
||||
CYASSL_MSG("Verify finished error on mac");
|
||||
return VERIFY_MAC_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
idx = idx + finishedSz + 16;
|
||||
/* XXX the 16 should be from specs */
|
||||
}
|
||||
|
||||
if (ssl->options.side == CLIENT_END) {
|
||||
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
|
||||
@ -2156,6 +2183,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) {
|
||||
@ -2186,6 +2222,35 @@ 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];
|
||||
|
||||
if (ssl->options.side == SERVER_END) {
|
||||
XMEMCPY(nonce, ssl->keys.server_write_IV,
|
||||
AES_GCM_IMPLICIT_IV_SIZE);
|
||||
}
|
||||
else {
|
||||
XMEMCPY(nonce, ssl->keys.client_write_IV,
|
||||
AES_GCM_IMPLICIT_IV_SIZE);
|
||||
}
|
||||
XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE,
|
||||
input, AES_GCM_EXPLICIT_IV_SIZE);
|
||||
XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE +
|
||||
AES_GCM_EXPLICIT_IV_SIZE, 0, 4);
|
||||
AesSetIV(&ssl->encrypt.aes, nonce);
|
||||
|
||||
XMEMSET(additional, 0, 16);
|
||||
c32toa(GetSEQIncrement(ssl, 0), additional + 4);
|
||||
XMEMCPY(additional+8, input - 5, 5);
|
||||
AesGcmEncrypt(&ssl->encrypt.aes, out+8, input+8, sz-24,
|
||||
out + 8 + (sz - 24), 16, additional, 13);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HC128
|
||||
case hc128:
|
||||
Hc128_Process(&ssl->encrypt.hc128, out, input, sz);
|
||||
@ -2204,7 +2269,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) {
|
||||
@ -2226,6 +2291,41 @@ static INLINE void Decrypt(CYASSL* ssl, byte* plain, const byte* input,
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_AESGCM
|
||||
case aes_gcm:
|
||||
{
|
||||
byte additional[16];
|
||||
byte nonce[16];
|
||||
|
||||
/* use the other side's IV */
|
||||
if (ssl->options.side == SERVER_END) {
|
||||
XMEMCPY(nonce, ssl->keys.client_write_IV,
|
||||
AES_GCM_IMPLICIT_IV_SIZE);
|
||||
}
|
||||
else {
|
||||
XMEMCPY(nonce, ssl->keys.server_write_IV,
|
||||
AES_GCM_IMPLICIT_IV_SIZE);
|
||||
}
|
||||
XMEMCPY(nonce + AES_GCM_IMPLICIT_IV_SIZE,
|
||||
input, AES_GCM_EXPLICIT_IV_SIZE);
|
||||
XMEMSET(nonce + AES_GCM_IMPLICIT_IV_SIZE +
|
||||
AES_GCM_EXPLICIT_IV_SIZE, 0, 4);
|
||||
AesSetIV(&ssl->decrypt.aes, nonce);
|
||||
XMEMSET(additional, 0, 4);
|
||||
c32toa(GetSEQIncrement(ssl, 1), additional + 4);
|
||||
additional[8] = ssl->curRL.type;
|
||||
additional[9] = ssl->curRL.version.major;
|
||||
additional[10] = ssl->curRL.version.minor;
|
||||
c16toa(sz, additional + 11);
|
||||
if (AesGcmDecrypt(&ssl->decrypt.aes, plain+8, input+8, sz-24,
|
||||
input + 8 + (sz - 24), 16, additional, 13) < 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);
|
||||
@ -2241,27 +2341,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);
|
||||
int decryptResult = Decrypt(ssl, input, input, sz);
|
||||
|
||||
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 */
|
||||
|
||||
return 0;
|
||||
if (ssl->specs.cipher_type == aead)
|
||||
*idx += AES_GCM_EXPLICIT_IV_SIZE;
|
||||
}
|
||||
|
||||
|
||||
static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
|
||||
{
|
||||
if (verify)
|
||||
return ssl->keys.peer_sequence_number++;
|
||||
else
|
||||
return ssl->keys.sequence_number++;
|
||||
return decryptResult;
|
||||
}
|
||||
|
||||
|
||||
@ -2288,6 +2386,10 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
||||
pad = *(input + idx + msgSz - ivExtra - 1);
|
||||
padByte = 1;
|
||||
}
|
||||
if (ssl->specs.cipher_type == aead) {
|
||||
ivExtra = 8;
|
||||
digestSz = 16;
|
||||
}
|
||||
|
||||
dataSz = msgSz - ivExtra - digestSz - pad - padByte;
|
||||
if (dataSz < 0) {
|
||||
@ -2299,6 +2401,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
||||
if (dataSz) {
|
||||
int rawSz = dataSz; /* keep raw size for hmac */
|
||||
|
||||
if (ssl->specs.cipher_type != aead)
|
||||
ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1);
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
@ -2332,7 +2435,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@ -2369,6 +2472,7 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type)
|
||||
CYASSL_ERROR(*type);
|
||||
|
||||
if (ssl->keys.encryptionOn) {
|
||||
if (ssl->specs.cipher_type != aead) {
|
||||
int aSz = ALERT_SIZE;
|
||||
const byte* mac;
|
||||
byte verify[SHA256_DIGEST_SIZE];
|
||||
@ -2386,6 +2490,11 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type)
|
||||
return VERIFY_MAC_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*inOutIdx += 16;
|
||||
/* XXX this should be a value out of the cipher specs */
|
||||
}
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
@ -2901,6 +3010,11 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
|
||||
sz += pad;
|
||||
}
|
||||
|
||||
if (ssl->specs.cipher_type == aead) {
|
||||
ivSz = AES_GCM_EXPLICIT_IV_SIZE;
|
||||
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);
|
||||
|
||||
@ -2914,8 +3028,10 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
|
||||
|
||||
if (type == handshake)
|
||||
HashOutput(ssl, output, headerSz + inSz, ivSz);
|
||||
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++)
|
||||
|
46
src/keys.c
46
src/keys.c
@ -323,7 +323,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -340,7 +340,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -357,7 +357,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -374,7 +374,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -391,7 +391,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -408,7 +408,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -425,7 +425,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -442,7 +442,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -793,7 +793,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -809,7 +809,7 @@ int SetCipherSpecs(CYASSL* ssl)
|
||||
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_IV_SIZE;
|
||||
ssl->specs.iv_size = AES_GCM_IMPLICIT_IV_SIZE;
|
||||
|
||||
break;
|
||||
#endif
|
||||
@ -970,6 +970,27 @@ 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) {
|
||||
AesSetKey(&enc->aes, keys->client_write_key,
|
||||
specs->key_size, keys->client_write_IV,
|
||||
AES_ENCRYPTION);
|
||||
AesSetKey(&dec->aes, keys->server_write_key,
|
||||
specs->key_size, keys->server_write_IV,
|
||||
AES_ENCRYPTION);
|
||||
}
|
||||
else {
|
||||
AesSetKey(&enc->aes, keys->server_write_key,
|
||||
specs->key_size, keys->server_write_IV,
|
||||
AES_ENCRYPTION);
|
||||
AesSetKey(&dec->aes, keys->client_write_key,
|
||||
specs->key_size, keys->client_write_IV,
|
||||
AES_ENCRYPTION);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
keys->sequence_number = 0;
|
||||
keys->peer_sequence_number = 0;
|
||||
keys->encryptionOn = 0;
|
||||
@ -983,10 +1004,15 @@ int StoreKeys(CYASSL* ssl, const byte* keyData)
|
||||
{
|
||||
int sz = ssl->specs.hash_size, i;
|
||||
|
||||
if (ssl->specs.cipher_type != aead) {
|
||||
XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz);
|
||||
i = sz;
|
||||
XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
|
||||
i += sz;
|
||||
}
|
||||
else {
|
||||
sz = 0;
|
||||
}
|
||||
|
||||
sz = ssl->specs.key_size;
|
||||
XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz);
|
||||
|
Loading…
Reference in New Issue
Block a user