use dynamic memory for ssl ciphers, only use what needed

This commit is contained in:
toddouska
2012-09-05 12:30:51 -07:00
parent c47afaf84f
commit 9ddf43268d
8 changed files with 172 additions and 74 deletions

View File

@@ -216,7 +216,8 @@ enum {
DYNAMIC_TYPE_OCSP_STATUS = 27,
DYNAMIC_TYPE_OCSP_ENTRY = 28,
DYNAMIC_TYPE_ALTNAME = 29,
DYNAMIC_TYPE_SUITES = 30
DYNAMIC_TYPE_SUITES = 30,
DYNAMIC_TYPE_CIPHER = 31
};
/* stack protection */

View File

@@ -978,25 +978,29 @@ typedef struct Keys {
/* cipher for now */
typedef union {
typedef struct Ciphers {
#ifdef BUILD_ARC4
Arc4 arc4;
Arc4* arc4;
#endif
#ifdef BUILD_DES3
Des3 des3;
Des3* des3;
#endif
#ifdef BUILD_AES
Aes aes;
Aes* aes;
#endif
#ifdef HAVE_HC128
HC128 hc128;
HC128* hc128;
#endif
#ifdef BUILD_RABBIT
Rabbit rabbit;
Rabbit* rabbit;
#endif
} Ciphers;
CYASSL_LOCAL void InitCiphers(CYASSL* ssl);
CYASSL_LOCAL void FreeCiphers(CYASSL* ssl);
/* hashes type */
typedef struct Hashes {
byte md5[MD5_DIGEST_SIZE];

View File

@@ -99,6 +99,7 @@
#define BAD_DECRYPT_TYPE 65
#define BAD_FINISHED_MSG 66
#define BAD_COMPRESSION_STR 67
#define BAD_DERIVE_STR 68
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */

View File

@@ -81,5 +81,6 @@ STRINGTABLE
66, "Bad Finished Message Processing"
67, "Bad Compression Type"
68, "Bad DeriveKeys Error"
}

View File

@@ -434,7 +434,59 @@ void FreeSSL_Ctx(CYASSL_CTX* ctx)
}
}
/* Set cipher pointers to null */
void InitCiphers(CYASSL* ssl)
{
#ifdef BUILD_ARC4
ssl->encrypt.arc4 = NULL;
ssl->decrypt.arc4 = NULL;
#endif
#ifdef BUILD_DES3
ssl->encrypt.des3 = NULL;
ssl->decrypt.des3 = NULL;
#endif
#ifdef BUILD_AES
ssl->encrypt.aes = NULL;
ssl->decrypt.aes = NULL;
#endif
#ifdef HAVE_HC128
ssl->encrypt.hc128 = NULL;
ssl->decrypt.hc128 = NULL;
#endif
#ifdef BUILD_RABBIT
ssl->encrypt.rabbit = NULL;
ssl->decrypt.rabbit = NULL;
#endif
}
/* Free ciphers */
void FreeCiphers(CYASSL* ssl)
{
#ifdef BUILD_ARC4
XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef BUILD_DES3
XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef BUILD_AES
XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef HAVE_HC128
XFREE(ssl->encrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef BUILD_RABBIT
XFREE(ssl->encrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
}
void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
byte haveNTRU, byte haveECDSAsig, byte haveStaticECC, int side)
{
@@ -1002,6 +1054,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
ssl->arrays.server_hint[0] = 0;
#endif /* NO_PSK */
InitCiphers(ssl);
/* all done with init, now can return errors, call other stuff */
/* increment CTX reference count */
@@ -1047,6 +1100,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
/* In case holding SSL object in array and don't want to free actual ssl */
void SSL_ResourceFree(CYASSL* ssl)
{
FreeCiphers(ssl);
XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
@@ -2387,13 +2441,13 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
switch (ssl->specs.bulk_cipher_algorithm) {
#ifdef BUILD_ARC4
case rc4:
Arc4Process(&ssl->encrypt.arc4, out, input, sz);
Arc4Process(ssl->encrypt.arc4, out, input, sz);
break;
#endif
#ifdef BUILD_DES3
case triple_des:
Des3_CbcEncrypt(&ssl->encrypt.des3, out, input, sz);
Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz);
break;
#endif
@@ -2403,12 +2457,12 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
if ((word)input % 16) {
byte buffer[MAX_RECORD_SIZE + MAX_COMP_EXTRA+MAX_MSG_EXTRA];
XMEMCPY(buffer, input, sz);
AesCbcEncrypt(&ssl->encrypt.aes, buffer, buffer, sz);
AesCbcEncrypt(ssl->encrypt.aes, buffer, buffer, sz);
XMEMCPY(out, buffer, sz);
break;
}
#endif
AesCbcEncrypt(&ssl->encrypt.aes, out, input, sz);
AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
break;
#endif
@@ -2431,25 +2485,25 @@ static INLINE void Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
* 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,
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);
AesGcmIncExpIV(&ssl->encrypt.aes);
AesGcmIncExpIV(ssl->encrypt.aes);
}
break;
#endif
#ifdef HAVE_HC128
case hc128:
Hc128_Process(&ssl->encrypt.hc128, out, input, sz);
Hc128_Process(ssl->encrypt.hc128, out, input, sz);
break;
#endif
#ifdef BUILD_RABBIT
case rabbit:
RabbitProcess(&ssl->encrypt.rabbit, out, input, sz);
RabbitProcess(ssl->encrypt.rabbit, out, input, sz);
break;
#endif
@@ -2465,19 +2519,19 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
switch (ssl->specs.bulk_cipher_algorithm) {
#ifdef BUILD_ARC4
case rc4:
Arc4Process(&ssl->decrypt.arc4, plain, input, sz);
Arc4Process(ssl->decrypt.arc4, plain, input, sz);
break;
#endif
#ifdef BUILD_DES3
case triple_des:
Des3_CbcDecrypt(&ssl->decrypt.des3, plain, input, sz);
Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
break;
#endif
#ifdef BUILD_AES
case aes:
AesCbcDecrypt(&ssl->decrypt.aes, plain, input, sz);
AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
break;
#endif
@@ -2486,7 +2540,7 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
{
byte additional[AES_BLOCK_SIZE];
AesGcmSetExpIV(&ssl->decrypt.aes, input);
AesGcmSetExpIV(ssl->decrypt.aes, input);
XMEMSET(additional, 0, AES_BLOCK_SIZE);
/* sequence number field is 64-bits, we only use 32-bits */
@@ -2498,7 +2552,7 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
additional + AEAD_LEN_OFFSET);
if (AesGcmDecrypt(&ssl->decrypt.aes,
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,
@@ -2513,13 +2567,13 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
#ifdef HAVE_HC128
case hc128:
Hc128_Process(&ssl->decrypt.hc128, plain, input, sz);
Hc128_Process(ssl->decrypt.hc128, plain, input, sz);
break;
#endif
#ifdef BUILD_RABBIT
case rabbit:
RabbitProcess(&ssl->decrypt.rabbit, plain, input, sz);
RabbitProcess(ssl->decrypt.rabbit, plain, input, sz);
break;
#endif
@@ -3227,7 +3281,7 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
if (ssl->specs.cipher_type == aead) {
ivSz = AES_GCM_EXP_IV_SZ;
sz += (ivSz + 16 - digestSz);
AesGcmGetExpIV(&ssl->encrypt.aes, iv);
AesGcmGetExpIV(ssl->encrypt.aes, iv);
}
#endif
size = (word16)(sz - headerSz); /* include mac and digest */

View File

@@ -918,34 +918,46 @@ static int SetPrefix(byte* sha_input, int idx)
static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
byte side)
byte side, void* heap, RNG* rng)
{
#ifdef BUILD_ARC4
word32 sz = specs->key_size;
if (specs->bulk_cipher_algorithm == rc4) {
enc->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER);
if (enc->arc4 == NULL)
return MEMORY_E;
dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER);
if (dec->arc4 == NULL)
return MEMORY_E;
if (side == CLIENT_END) {
Arc4SetKey(&enc->arc4, keys->client_write_key, sz);
Arc4SetKey(&dec->arc4, keys->server_write_key, sz);
Arc4SetKey(enc->arc4, keys->client_write_key, sz);
Arc4SetKey(dec->arc4, keys->server_write_key, sz);
}
else {
Arc4SetKey(&enc->arc4, keys->server_write_key, sz);
Arc4SetKey(&dec->arc4, keys->client_write_key, sz);
Arc4SetKey(enc->arc4, keys->server_write_key, sz);
Arc4SetKey(dec->arc4, keys->client_write_key, sz);
}
}
#endif
#ifdef HAVE_HC128
if (specs->bulk_cipher_algorithm == hc128) {
enc->hc128 = (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER);
if (enc->hc128 == NULL)
return MEMORY_E;
dec->hc128 = (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER);
if (dec->hc128 == NULL)
return MEMORY_E;
if (side == CLIENT_END) {
Hc128_SetKey(&enc->hc128, keys->client_write_key,
Hc128_SetKey(enc->hc128, keys->client_write_key,
keys->client_write_IV);
Hc128_SetKey(&dec->hc128, keys->server_write_key,
Hc128_SetKey(dec->hc128, keys->server_write_key,
keys->server_write_IV);
}
else {
Hc128_SetKey(&enc->hc128, keys->server_write_key,
Hc128_SetKey(enc->hc128, keys->server_write_key,
keys->server_write_IV);
Hc128_SetKey(&dec->hc128, keys->client_write_key,
Hc128_SetKey(dec->hc128, keys->client_write_key,
keys->client_write_IV);
}
}
@@ -953,16 +965,22 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
#ifdef BUILD_RABBIT
if (specs->bulk_cipher_algorithm == rabbit) {
enc->rabbit = (Rabbit*)XMALLOC(sizeof(Rabbit),heap,DYNAMIC_TYPE_CIPHER);
if (enc->rabbit == NULL)
return MEMORY_E;
dec->rabbit = (Rabbit*)XMALLOC(sizeof(Rabbit),heap,DYNAMIC_TYPE_CIPHER);
if (dec->rabbit == NULL)
return MEMORY_E;
if (side == CLIENT_END) {
RabbitSetKey(&enc->rabbit, keys->client_write_key,
RabbitSetKey(enc->rabbit, keys->client_write_key,
keys->client_write_IV);
RabbitSetKey(&dec->rabbit, keys->server_write_key,
RabbitSetKey(dec->rabbit, keys->server_write_key,
keys->server_write_IV);
}
else {
RabbitSetKey(&enc->rabbit, keys->server_write_key,
RabbitSetKey(enc->rabbit, keys->server_write_key,
keys->server_write_IV);
RabbitSetKey(&dec->rabbit, keys->client_write_key,
RabbitSetKey(dec->rabbit, keys->client_write_key,
keys->client_write_IV);
}
}
@@ -970,16 +988,22 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
#ifdef BUILD_DES3
if (specs->bulk_cipher_algorithm == triple_des) {
enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER);
if (enc->des3 == NULL)
return MEMORY_E;
dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER);
if (dec->des3 == NULL)
return MEMORY_E;
if (side == CLIENT_END) {
Des3_SetKey(&enc->des3, keys->client_write_key,
Des3_SetKey(enc->des3, keys->client_write_key,
keys->client_write_IV, DES_ENCRYPTION);
Des3_SetKey(&dec->des3, keys->server_write_key,
Des3_SetKey(dec->des3, keys->server_write_key,
keys->server_write_IV, DES_DECRYPTION);
}
else {
Des3_SetKey(&enc->des3, keys->server_write_key,
Des3_SetKey(enc->des3, keys->server_write_key,
keys->server_write_IV, DES_ENCRYPTION);
Des3_SetKey(&dec->des3, keys->client_write_key,
Des3_SetKey(dec->des3, keys->client_write_key,
keys->client_write_IV, DES_DECRYPTION);
}
}
@@ -987,19 +1011,25 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
#ifdef BUILD_AES
if (specs->bulk_cipher_algorithm == aes) {
enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
if (enc->aes == NULL)
return MEMORY_E;
dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
if (dec->aes == NULL)
return MEMORY_E;
if (side == CLIENT_END) {
AesSetKey(&enc->aes, keys->client_write_key,
AesSetKey(enc->aes, keys->client_write_key,
specs->key_size, keys->client_write_IV,
AES_ENCRYPTION);
AesSetKey(&dec->aes, keys->server_write_key,
AesSetKey(dec->aes, keys->server_write_key,
specs->key_size, keys->server_write_IV,
AES_DECRYPTION);
}
else {
AesSetKey(&enc->aes, keys->server_write_key,
AesSetKey(enc->aes, keys->server_write_key,
specs->key_size, keys->server_write_IV,
AES_ENCRYPTION);
AesSetKey(&dec->aes, keys->client_write_key,
AesSetKey(dec->aes, keys->client_write_key,
specs->key_size, keys->client_write_IV,
AES_DECRYPTION);
}
@@ -1008,16 +1038,28 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
#ifdef BUILD_AESGCM
if (specs->bulk_cipher_algorithm == aes_gcm) {
byte iv[AES_GCM_EXP_IV_SZ];
enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
if (enc->aes == NULL)
return MEMORY_E;
dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
if (dec->aes == NULL)
return MEMORY_E;
/* Initialize the AES-GCM explicit IV to a random number. */
RNG_GenerateBlock(rng, iv, sizeof(iv));
AesGcmSetExpIV(enc->aes, iv);
if (side == CLIENT_END) {
AesGcmSetKey(&enc->aes, keys->client_write_key, specs->key_size,
AesGcmSetKey(enc->aes, keys->client_write_key, specs->key_size,
keys->client_write_IV);
AesGcmSetKey(&dec->aes, keys->server_write_key, specs->key_size,
AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size,
keys->server_write_IV);
}
else {
AesGcmSetKey(&enc->aes, keys->server_write_key, specs->key_size,
AesGcmSetKey(enc->aes, keys->server_write_key, specs->key_size,
keys->server_write_IV);
AesGcmSetKey(&dec->aes, keys->client_write_key, specs->key_size,
AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size,
keys->client_write_IV);
}
}
@@ -1026,6 +1068,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
keys->sequence_number = 0;
keys->peer_sequence_number = 0;
keys->encryptionOn = 0;
(void)rng;
return 0;
}
@@ -1043,16 +1086,6 @@ int StoreKeys(CYASSL* ssl, const byte* keyData)
XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
i += sz;
}
#ifdef BUILD_AESGCM
else if (ssl->specs.bulk_cipher_algorithm == aes_gcm) {
byte iv[AES_GCM_EXP_IV_SZ];
/* Initialize the AES-GCM explicit IV to a random number. */
RNG_GenerateBlock(&ssl->rng, iv, sizeof(iv));
AesGcmSetExpIV(&ssl->encrypt.aes, iv);
}
#endif
sz = ssl->specs.key_size;
XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz);
i += sz;
@@ -1065,7 +1098,7 @@ int StoreKeys(CYASSL* ssl, const byte* keyData)
XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz);
return SetKeys(&ssl->encrypt, &ssl->decrypt, &ssl->keys, &ssl->specs,
ssl->options.side);
ssl->options.side, ssl->heap, &ssl->rng);
}

View File

@@ -217,7 +217,8 @@ static const char* const msgTable[] =
/* 66 */
"Bad Finished Message Processing",
"Bad Compression Type"
"Bad Compression Type",
"Bad DeriveKeys Error"
};
@@ -1205,6 +1206,7 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
}
if (doResume ) {
int ret = 0;
SSL_SESSION* resume = GetSession(session->sslServer,
session->sslServer->arrays.masterSecret);
if (resume == NULL) {
@@ -1228,12 +1230,16 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
}
if (session->sslServer->options.tls) {
DeriveTlsKeys(session->sslServer);
DeriveTlsKeys(session->sslClient);
ret = DeriveTlsKeys(session->sslServer);
ret += DeriveTlsKeys(session->sslClient);
}
else {
DeriveKeys(session->sslServer);
DeriveKeys(session->sslClient);
ret = DeriveKeys(session->sslServer);
ret += DeriveKeys(session->sslClient);
}
if (ret != 0) {
SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
}
#ifdef SHOW_SECRETS
@@ -1517,31 +1523,31 @@ static void Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
switch (ssl->specs.bulk_cipher_algorithm) {
#ifdef BUILD_ARC4
case rc4:
Arc4Process(&ssl->decrypt.arc4, output, input, sz);
Arc4Process(ssl->decrypt.arc4, output, input, sz);
break;
#endif
#ifdef BUILD_DES3
case triple_des:
Des3_CbcDecrypt(&ssl->decrypt.des3, output, input, sz);
Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
break;
#endif
#ifdef BUILD_AES
case aes:
AesCbcDecrypt(&ssl->decrypt.aes, output, input, sz);
AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
break;
#endif
#ifdef HAVE_HC128
case hc128:
Hc128_Process(&ssl->decrypt.hc128, output, input, sz);
Hc128_Process(ssl->decrypt.hc128, output, input, sz);
break;
#endif
#ifdef BUILD_RABBIT
case rabbit:
RabbitProcess(&ssl->decrypt.rabbit, output, input, sz);
RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
break;
#endif

View File

@@ -121,8 +121,7 @@ static void p_hash(byte* result, word32 resLen, const byte* secret,
/* compute TLSv1 PRF (pseudo random function using HMAC) */
static void doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen,
const byte* label, word32 labLen, const byte* seed, word32 seedLen,
int hash_type)
const byte* label, word32 labLen, const byte* seed, word32 seedLen)
{
word32 half = (secLen + 1) / 2;
@@ -176,8 +175,7 @@ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
hash_type);
}
else
doPRF(digest, digLen, secret, secLen, label, labLen, seed, seedLen,
hash_type);
doPRF(digest, digLen, secret, secLen, label, labLen, seed, seedLen);
}