diff options
-rw-r--r-- | doc/TODO | 4 | ||||
-rw-r--r-- | lib/auth_anon.c | 2 | ||||
-rw-r--r-- | lib/auth_rsa.c | 6 | ||||
-rw-r--r-- | lib/gnutls_constate.c | 61 | ||||
-rw-r--r-- | lib/gnutls_datum.c | 4 | ||||
-rw-r--r-- | lib/gnutls_datum.h | 2 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 1 | ||||
-rw-r--r-- | lib/gnutls_errors_int.h | 1 | ||||
-rw-r--r-- | lib/gnutls_global.c | 2 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 93 | ||||
-rw-r--r-- | lib/gnutls_hash_int.c | 45 | ||||
-rw-r--r-- | lib/gnutls_hash_int.h | 2 | ||||
-rw-r--r-- | lib/gnutls_int.h | 21 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 34 | ||||
-rw-r--r-- | lib/gnutls_mem.c | 42 | ||||
-rw-r--r-- | lib/gnutls_mem.h | 20 | ||||
-rw-r--r-- | lib/gnutls_record.c | 57 |
17 files changed, 233 insertions, 164 deletions
@@ -5,12 +5,12 @@ in order to avoid having people working on the same thing. Current list: + Trace memory leaks in libgcrypt + Audit the code +* Add support for certificates with DSS parameters +* OpenPGP certificate support * Add callbacks to get SRP parameters (instead of a reading password file) * Minimize footprint. -* Add support for certificates with DSS parameters * Add more TLS extensions * Add support for PKCS8 encrypted private keys -* OpenPGP certificate support - Add Kerberos support (+) Means high priority diff --git a/lib/auth_anon.c b/lib/auth_anon.c index aece0378a2..712da0fbff 100644 --- a/lib/auth_anon.c +++ b/lib/auth_anon.c @@ -57,7 +57,7 @@ MOD_AUTH_STRUCT anon_auth_struct = { */ int _gnutls_generate_key(GNUTLS_KEY key) { _gnutls_mpi_print( NULL, &key->key.size, key->KEY); - key->key.data = secure_malloc( key->key.size); + key->key.data = gnutls_secure_malloc( key->key.size); if ( key->key.data==NULL) { return GNUTLS_E_MEMORY_ERROR; } diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index f34b96a4fa..57ca961672 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -109,11 +109,11 @@ return ret; #ifdef DEBUG _gnutls_log( "Possible PKCS-1 format attack\n"); #endif - RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc); + RANDOMIZE_KEY(state->gnutls_key->key, gnutls_secure_malloc); } else { ret = 0; if (plaintext.size != TLS_MASTER_SIZE) { /* WOW */ - RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc); + RANDOMIZE_KEY(state->gnutls_key->key, gnutls_secure_malloc); } else { if (_gnutls_get_adv_version_major( state) != plaintext.data[0] || _gnutls_get_adv_version_minor( state) != plaintext.data[1]) { @@ -157,7 +157,7 @@ int gen_rsa_client_kx(GNUTLS_STATE state, opaque ** data) gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; } - RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc); + RANDOMIZE_KEY(state->gnutls_key->key, gnutls_secure_malloc); ver = _gnutls_version_max(state); diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c index e118420e08..d09d6da863 100644 --- a/lib/gnutls_constate.c +++ b/lib/gnutls_constate.c @@ -36,7 +36,7 @@ int _gnutls_set_keys(GNUTLS_STATE state, int hash_size, int IV_size, int key_siz opaque *key_block; char keyexp[] = "key expansion"; char random[2*TLS_RANDOM_SIZE]; - int pos; + int pos, ret; int block_size; if (state->cipher_specs.generated_keys!=0) { @@ -49,57 +49,78 @@ int _gnutls_set_keys(GNUTLS_STATE state, int hash_size, int IV_size, int key_siz block_size = 2 * hash_size + 2 * key_size + 2 * IV_size; - + key_block = gnutls_secure_malloc( block_size); + if (key_block==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy(random, state->security_parameters.server_random, TLS_RANDOM_SIZE); memcpy(&random[TLS_RANDOM_SIZE], state->security_parameters.client_random, TLS_RANDOM_SIZE); if ( state->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ - key_block = gnutls_ssl3_generate_random( state->security_parameters.master_secret, TLS_MASTER_SIZE, random, 2*TLS_RANDOM_SIZE, - block_size); + ret = gnutls_ssl3_generate_random( state->security_parameters.master_secret, TLS_MASTER_SIZE, random, 2*TLS_RANDOM_SIZE, + block_size, key_block); } else { /* TLS 1.0 */ - key_block = + ret = gnutls_PRF( state->security_parameters.master_secret, TLS_MASTER_SIZE, keyexp, strlen(keyexp), random, 2*TLS_RANDOM_SIZE, - block_size); + block_size, key_block); + } + + if (ret<0) { + gnutls_assert(); + gnutls_secure_free(key_block); + return ret; } - if (key_block==NULL) return GNUTLS_E_MEMORY_ERROR; - #ifdef HARD_DEBUG _gnutls_log( "KEY BLOCK[%d]: %s\n",block_size, _gnutls_bin2hex(key_block, block_size)); #endif pos = 0; if (hash_size > 0) { - if (gnutls_sset_datum( &state->cipher_specs.client_write_mac_secret, &key_block[pos], hash_size) < 0 ) + if (gnutls_sset_datum( &state->cipher_specs.client_write_mac_secret, &key_block[pos], hash_size) < 0 ) { + gnutls_secure_free(key_block); return GNUTLS_E_MEMORY_ERROR; + } pos+=hash_size; - if (gnutls_sset_datum( &state->cipher_specs.server_write_mac_secret, &key_block[pos], hash_size) < 0 ) + if (gnutls_sset_datum( &state->cipher_specs.server_write_mac_secret, &key_block[pos], hash_size) < 0 ) { + gnutls_secure_free(key_block); return GNUTLS_E_MEMORY_ERROR; + } pos+=hash_size; } if (key_size > 0) { - if (gnutls_sset_datum( &state->cipher_specs.client_write_key, &key_block[pos], key_size) < 0 ) + if (gnutls_sset_datum( &state->cipher_specs.client_write_key, &key_block[pos], key_size) < 0 ) { + gnutls_secure_free(key_block); return GNUTLS_E_MEMORY_ERROR; + } pos+=key_size; - if (gnutls_sset_datum( &state->cipher_specs.server_write_key, &key_block[pos], key_size) < 0 ) + if (gnutls_sset_datum( &state->cipher_specs.server_write_key, &key_block[pos], key_size) < 0 ) { + gnutls_secure_free(key_block); return GNUTLS_E_MEMORY_ERROR; + } pos+=key_size; } if (IV_size > 0) { - if (gnutls_sset_datum( &state->cipher_specs.client_write_IV, &key_block[pos], IV_size) < 0 ) + if (gnutls_sset_datum( &state->cipher_specs.client_write_IV, &key_block[pos], IV_size) < 0 ) { + gnutls_secure_free(key_block); return GNUTLS_E_MEMORY_ERROR; + } pos+=IV_size; - if (gnutls_sset_datum( &state->cipher_specs.server_write_IV, &key_block[pos], IV_size) < 0 ) + if (gnutls_sset_datum( &state->cipher_specs.server_write_IV, &key_block[pos], IV_size) < 0 ) { + gnutls_secure_free(key_block); return GNUTLS_E_MEMORY_ERROR; + } pos+=IV_size; } - secure_free(key_block); + gnutls_secure_free(key_block); state->cipher_specs.generated_keys = 1; @@ -236,8 +257,10 @@ int rc; } - _gnutls_set_read_keys(state); - + rc = _gnutls_set_read_keys(state); + if (rc < 0) + return rc; + #ifdef HANDSHAKE_DEBUG _gnutls_log( "Cipher Suite: %s\n", _gnutls_cipher_suite_get_name(state-> @@ -381,7 +404,9 @@ int rc; _gnutls_cpy_write_security_parameters( &state->security_parameters, &state->gnutls_internals.resumed_security_parameters); } - _gnutls_set_write_keys(state); + rc = _gnutls_set_write_keys(state); + if (rc < 0) + return rc; #ifdef HANDSHAKE_DEBUG _gnutls_log( "Cipher Suite: %s\n", diff --git a/lib/gnutls_datum.c b/lib/gnutls_datum.c index c94144bc96..d39ef33fd1 100644 --- a/lib/gnutls_datum.c +++ b/lib/gnutls_datum.c @@ -56,7 +56,7 @@ int gnutls_set_datum( gnutls_datum* dat, const void* data, int data_size) { } int gnutls_sset_datum( gnutls_datum* dat, const void* data, int data_size) { - dat->data = secure_malloc(data_size); + dat->data = gnutls_secure_malloc(data_size); if (dat->data==NULL) return GNUTLS_E_MEMORY_ERROR; dat->size = data_size; @@ -75,7 +75,7 @@ void gnutls_free_datum( gnutls_datum* dat) { void gnutls_sfree_datum( gnutls_datum* dat) { if (dat->data!=NULL && dat->size!=0) - secure_free( dat->data); + gnutls_secure_free( dat->data); dat->data = NULL; dat->size = 0; diff --git a/lib/gnutls_datum.h b/lib/gnutls_datum.h index 4280b191e5..15aa73ba63 100644 --- a/lib/gnutls_datum.h +++ b/lib/gnutls_datum.h @@ -3,8 +3,6 @@ void WRITEdatum24( opaque* dest, gnutls_datum dat); void WRITEdatum32( opaque* dest, gnutls_datum dat); void WRITEdatum8( opaque* dest, gnutls_datum dat); -typedef gnutls_datum gnutls_sdatum; - int gnutls_set_datum( gnutls_datum* dat, const void* data, int data_size); /* uses secure_malloc */ int gnutls_sset_datum( gnutls_sdatum* dat, const void* data, int data_size); diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index 2da20177c9..1eae48c2c9 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -47,6 +47,7 @@ static gnutls_error_entry error_algorithms[] = { GNUTLS_ERROR_ENTRY( GNUTLS_E_UNSUPPORTED_VERSION_PACKET, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_UNEXPECTED_PACKET_LENGTH, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_INVALID_SESSION, 1), + GNUTLS_ERROR_ENTRY( GNUTLS_E_INTERNAL, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_UNABLE_SEND_DATA, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_FATAL_ALERT_RECEIVED ,1), GNUTLS_ERROR_ENTRY( GNUTLS_E_RECEIVED_BAD_MESSAGE, 1), diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h index 4f3c73bf2b..fa6d9f9b74 100644 --- a/lib/gnutls_errors_int.h +++ b/lib/gnutls_errors_int.h @@ -58,5 +58,6 @@ #define GNUTLS_E_ILLEGAL_PARAMETER -55 /* GNUTLS_A_ILLEGAL_PARAMETER */ #define GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE -56 #define GNUTLS_E_PKCS1_WRONG_PAD -57 +#define GNUTLS_E_INTERNAL -58 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -250 diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c index 5273faac5d..491e4c1bbe 100644 --- a/lib/gnutls_global.c +++ b/lib/gnutls_global.c @@ -83,7 +83,7 @@ int gnutls_global_init() int result; /* for gcrypt in order to be able to allocate memory */ - gcry_set_allocation_handler(gnutls_malloc, secure_malloc, _gnutls_is_secure_memory, gnutls_realloc, gnutls_free); + gcry_set_allocation_handler(gnutls_malloc, gnutls_secure_malloc, _gnutls_is_secure_memory, gnutls_realloc, gnutls_free); /* set default recv/send functions */ diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index b812d2d50c..64e66398d2 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -113,34 +113,39 @@ void _gnutls_set_client_random(GNUTLS_STATE state, uint8 * random) /* Calculate The SSL3 Finished message */ #define SSL3_CLIENT_MSG "CLNT" #define SSL3_SERVER_MSG "SRVR" -void *_gnutls_ssl3_finished(GNUTLS_STATE state, int type, int skip) +static int _gnutls_ssl3_finished(GNUTLS_STATE state, int type, int skip, opaque* ret) { int siz; GNUTLS_MAC_HANDLE td; GNUTLS_MAC_HANDLE td2; char tmp[MAX_HASH_SIZE]; - char *concat; char *mesg, *data; - concat = gnutls_malloc(36); - if (concat==NULL) { - gnutls_assert(); - return NULL; - } - td = gnutls_mac_init_ssl3_handshake(GNUTLS_MAC_MD5, state->security_parameters. master_secret, 48); + if (td==NULL) { + gnutls_assert(); + return GNUTLS_E_HASH_FAILED; + } + td2 = gnutls_mac_init_ssl3_handshake(GNUTLS_MAC_SHA, state->security_parameters. master_secret, 48); + if (td2==NULL) { + gnutls_assert(); + gnutls_mac_deinit_ssl3_handshake(td, tmp); + return GNUTLS_E_HASH_FAILED; + } siz = gnutls_get_handshake_buffer_size(state) - skip; data = gnutls_malloc(siz); if (data==NULL) { gnutls_assert(); - return NULL; + gnutls_mac_deinit_ssl3_handshake(td2, tmp); + gnutls_mac_deinit_ssl3_handshake(td, tmp); + return GNUTLS_E_MEMORY_ERROR; } gnutls_read_handshake_buffer(state, data, siz); @@ -159,35 +164,47 @@ void *_gnutls_ssl3_finished(GNUTLS_STATE state, int type, int skip) gnutls_mac_ssl3(td2, mesg, siz); gnutls_mac_deinit_ssl3_handshake(td, tmp); - memcpy(concat, tmp, 16); + memcpy(ret, tmp, 16); gnutls_mac_deinit_ssl3_handshake(td2, tmp); - memcpy(&concat[16], tmp, 20); - return concat; + memcpy(&ret[16], tmp, 20); + return 0; } /* Hash the handshake messages as required by TLS 1.0 */ #define SERVER_MSG "server finished" #define CLIENT_MSG "client finished" -void *_gnutls_finished(GNUTLS_STATE state, int type, int skip) +int _gnutls_finished(GNUTLS_STATE state, int type, int skip, void* ret) { int siz; GNUTLS_MAC_HANDLE td; GNUTLS_MAC_HANDLE td2; char tmp[MAX_HASH_SIZE]; - char concat[36]; - char *mesg; - char *data; + opaque concat[36]; + opaque *mesg, *data; td = gnutls_hash_init(GNUTLS_MAC_MD5); + if (td==GNUTLS_HASH_FAILED) { + gnutls_assert(); + return GNUTLS_E_HASH_FAILED; + } + td2 = gnutls_hash_init(GNUTLS_MAC_SHA); + if (td2==GNUTLS_HASH_FAILED) { + gnutls_assert(); + gnutls_hash_deinit( td2, tmp); + return GNUTLS_E_HASH_FAILED; + } siz = gnutls_get_handshake_buffer_size(state) - skip; - data = gnutls_malloc(siz); + + data = gnutls_malloc( siz); if (data==NULL) { gnutls_assert(); - return NULL; + gnutls_hash_deinit( td2, tmp); + gnutls_hash_deinit( td, tmp); + return GNUTLS_E_MEMORY_ERROR; } gnutls_read_handshake_buffer(state, data, siz); @@ -209,10 +226,8 @@ void *_gnutls_finished(GNUTLS_STATE state, int type, int skip) } else { mesg = CLIENT_MSG; } - data = - gnutls_PRF(state->security_parameters.master_secret, - 48, mesg, strlen(mesg), concat, 36, 12); - return data; + return gnutls_PRF(state->security_parameters.master_secret, + 48, mesg, strlen(mesg), concat, 36, 12, ret); } /* this function will produce TLS_RANDOM_SIZE bytes of random data @@ -401,28 +416,33 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, */ int _gnutls_send_finished( GNUTLS_STATE state, int again) { - uint8 *data=NULL; + uint8 data[36]; int ret; int data_size=0; if (again==0) { if (state->security_parameters.version == GNUTLS_SSL3) { - data = + ret = _gnutls_ssl3_finished(state, state->security_parameters. - entity, 0); + entity, 0, data); data_size = 36; } else { /* TLS 1.0 */ - data = + ret = _gnutls_finished(state, - state->security_parameters.entity, 0); + state->security_parameters.entity, 0, data); data_size = 12; } } + + if (ret < 0) { + gnutls_assert(); + return ret; + } + ret = _gnutls_send_handshake( state, data, data_size, GNUTLS_FINISHED); - gnutls_free(data); return ret; } @@ -432,7 +452,7 @@ int _gnutls_send_finished( GNUTLS_STATE state, int again) */ int _gnutls_recv_finished( GNUTLS_STATE state) { - uint8 *data, *vrfy; + uint8 data[36], *vrfy; int data_size; int ret; int vrfysize; @@ -457,27 +477,32 @@ int _gnutls_recv_finished( GNUTLS_STATE state) gnutls_assert(); return GNUTLS_E_ERROR_IN_FINISHED_PACKET; } + if (state->security_parameters.version == GNUTLS_SSL3) { /* skip the bytes from the last message */ - data = + ret = _gnutls_ssl3_finished(state, (state->security_parameters. entity + 1) % 2, vrfysize + - HANDSHAKE_HEADER_SIZE); + HANDSHAKE_HEADER_SIZE, data); } else { /* TLS 1.0 */ - data = + ret = _gnutls_finished(state, (state->security_parameters.entity + 1) % 2, - vrfysize + HANDSHAKE_HEADER_SIZE); + vrfysize + HANDSHAKE_HEADER_SIZE, data); + } + + if (ret < 0) { + gnutls_assert(); + return ret; } if (memcmp(vrfy, data, data_size) != 0) { gnutls_assert(); ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET; } - gnutls_free(data); gnutls_free(vrfy); return ret; diff --git a/lib/gnutls_hash_int.c b/lib/gnutls_hash_int.c index 097fc9c469..aabb2b1ac8 100644 --- a/lib/gnutls_hash_int.c +++ b/lib/gnutls_hash_int.c @@ -19,8 +19,8 @@ */ #include <gnutls_int.h> - #include <gnutls_hash_int.h> +#include <gnutls_errors.h> /* This file handles all the internal functions that cope with hashes * and hmacs. Currently it uses the functions provided by @@ -367,7 +367,7 @@ void gnutls_mac_deinit_ssl3_handshake(GNUTLS_MAC_HANDLE handle, void* digest) return; } -static void ssl3_sha(int i, char *secret, int secret_len, char *random, +static int ssl3_sha(int i, char *secret, int secret_len, char *random, int random_len, void* digest) { int j; @@ -380,42 +380,63 @@ static void ssl3_sha(int i, char *secret, int secret_len, char *random, } td = gnutls_hash_init(GNUTLS_MAC_SHA); + if (td == NULL) { + gnutls_assert(); + return GNUTLS_E_HASH_FAILED; + } + gnutls_hash(td, text1, i + 1); gnutls_hash(td, secret, secret_len); gnutls_hash(td, random, random_len); gnutls_hash_deinit(td, digest); + return 0; } -static void ssl3_md5(int i, char *secret, int secret_len, char *random, +static int ssl3_md5(int i, char *secret, int secret_len, char *random, int random_len, void* digest) { opaque tmp[MAX_HASH_SIZE]; GNUTLS_MAC_HANDLE td; - + int ret; + td = gnutls_hash_init(GNUTLS_MAC_MD5); + if (td == NULL) { + gnutls_assert(); + return GNUTLS_E_HASH_FAILED; + } + gnutls_hash(td, secret, secret_len); - ssl3_sha(i, secret, secret_len, random, random_len, tmp); + ret = ssl3_sha(i, secret, secret_len, random, random_len, tmp); + if (ret < 0) { + gnutls_assert(); + gnutls_hash_deinit(td, digest); + return ret; + } gnutls_hash(td, tmp, gnutls_hash_get_algo_len(GNUTLS_MAC_SHA)); gnutls_hash_deinit(td, digest); - + return 0; } -svoid *gnutls_ssl3_generate_random(void *secret, int secret_len, void *random, - int random_len, int bytes) +int gnutls_ssl3_generate_random(void *secret, int secret_len, void *random, + int random_len, int bytes, opaque* ret) { int size = 0, i = 0; char digest[MAX_HASH_SIZE]; - char *ret = secure_malloc(bytes); int block = gnutls_hash_get_algo_len(GNUTLS_MAC_MD5); + int result; while (size < bytes) { - ssl3_md5(i, secret, secret_len, random, random_len, digest); - + result = ssl3_md5(i, secret, secret_len, random, random_len, digest); + if (result < 0) { + gnutls_assert(); + return result; + } + size += block; memcpy(&ret[size - block], digest, @@ -423,5 +444,5 @@ svoid *gnutls_ssl3_generate_random(void *secret, int secret_len, void *random, i++; } - return ret; + return 0; } diff --git a/lib/gnutls_hash_int.h b/lib/gnutls_hash_int.h index be1066c4d4..03f34dbc9a 100644 --- a/lib/gnutls_hash_int.h +++ b/lib/gnutls_hash_int.h @@ -60,7 +60,7 @@ int gnutls_hash_get_algo_len(MACAlgorithm algorithm); int gnutls_hash(GNUTLS_HASH_HANDLE handle, const void* text, int textlen); void gnutls_hash_deinit(GNUTLS_HASH_HANDLE handle, void* digest); -svoid *gnutls_ssl3_generate_random(void *secret, int secret_len, void *random, int random_len, int bytes); +int gnutls_ssl3_generate_random(void *secret, int secret_len, void *random, int random_len, int bytes, opaque* ret); GNUTLS_MAC_HANDLE gnutls_mac_init_ssl3_handshake(MACAlgorithm algorithm, void *key, int keylen); void gnutls_mac_deinit_ssl3_handshake(GNUTLS_MAC_HANDLE handle, void* digest); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 01dff2a60f..32a119d39e 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -30,10 +30,11 @@ #define HARD_DEBUG #define WRITE_DEBUG #define READ_DEBUG -#define RECORD_DEBUG #define HANDSHAKE_DEBUG // Prints some information on handshake -#define DEBUG +#define RECORD_DEBUG */ +#define DEBUG + /* It might be a good idea to replace int with void* * here. @@ -131,6 +132,7 @@ typedef struct { opaque * data; int size; } gnutls_datum; +typedef gnutls_datum gnutls_sdatum; typedef struct { AlertLevel level; @@ -182,7 +184,7 @@ typedef struct { struct GNUTLS_KEY_INT { /* For DH KX */ - gnutls_datum key; + gnutls_sdatum key; MPI KEY; MPI client_Y; MPI client_g; @@ -245,17 +247,10 @@ typedef enum GNUTLS_Version { GNUTLS_SSL3=1, GNUTLS_TLS1, GNUTLS_VERSION_UNKNOWN /* This structure holds parameters got from TLS extension * mechanism. (some extensions may hold parameters in AUTH_INFO - * structures instead - see SRP). + * structures also - see SRP). */ -typedef enum GNUTLS_NAME_IND { GNUTLS_DNSNAME=1 } GNUTLS_NAME_IND; - -typedef struct { - opaque dnsname[MAX_DNSNAME_SIZE]; - GNUTLS_NAME_IND type; -} name_ind; typedef struct { - name_ind name; opaque srp_username[MAX_SRP_USERNAME]; } TLSExtensions; @@ -502,9 +497,9 @@ typedef struct GNUTLS_STATE_INT *GNUTLS_STATE; /* functions */ int gnutls_send_alert( GNUTLS_STATE state, AlertLevel level, AlertDescription desc); -svoid *gnutls_PRF( opaque * secret, int secret_size, uint8 * label, +int gnutls_PRF( opaque * secret, int secret_size, uint8 * label, int label_size, opaque * seed, int seed_size, - int total_bytes); + int total_bytes, void* ret); void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version); GNUTLS_Version gnutls_protocol_get_version(GNUTLS_STATE state); void _gnutls_free_auth_info( GNUTLS_STATE state); diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index f52e3cf1b7..7b695b6e59 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -27,6 +27,7 @@ #include "debug.h" #include "gnutls_gcry.h" #include <gnutls_record.h> +#include <gnutls_datum.h> /* This file contains important thing for the TLS handshake procedure. */ @@ -40,47 +41,40 @@ int _gnutls_generate_master( GNUTLS_STATE state) { return 0; } +#define PREMASTER state->gnutls_key->key static int generate_normal_master( GNUTLS_STATE state) { -int premaster_size; -opaque* premaster, *master; int ret = 0; char random[2*TLS_RANDOM_SIZE]; memcpy(random, state->security_parameters.client_random, TLS_RANDOM_SIZE); memcpy(&random[TLS_RANDOM_SIZE], state->security_parameters.server_random, TLS_RANDOM_SIZE); - /* generate premaster */ - premaster_size = state->gnutls_key->key.size; - premaster = state->gnutls_key->key.data; - #ifdef HARD_DEBUG - _gnutls_log( "PREMASTER SECRET[%d]: %s\n", premaster_size, _gnutls_bin2hex(premaster, premaster_size)); + _gnutls_log( "PREMASTER SECRET[%d]: %s\n", PREMASTER.size, _gnutls_bin2hex(PREMASTER.data, PREMASTER.size)); _gnutls_log( "CLIENT RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.client_random,32)); _gnutls_log( "SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.server_random,32)); #endif if ( state->security_parameters.version == GNUTLS_SSL3) { - master = - gnutls_ssl3_generate_random( premaster, premaster_size, - random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE); + ret = + gnutls_ssl3_generate_random( PREMASTER.data, PREMASTER.size, + random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE, + state->security_parameters.master_secret); } else { - master = - gnutls_PRF( premaster, premaster_size, + ret = + gnutls_PRF( PREMASTER.data, PREMASTER.size, MASTER_SECRET, strlen(MASTER_SECRET), - random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE); + random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE, + state->security_parameters.master_secret); } - secure_free(premaster); - state->gnutls_key->key.size = 0; - state->gnutls_key->key.data = NULL; + gnutls_sfree_datum(&PREMASTER); - if (master==NULL) return GNUTLS_E_MEMORY_ERROR; + if (ret<0) return ret; #ifdef HARD_DEBUG - _gnutls_log( "MASTER SECRET: %s\n", _gnutls_bin2hex(master, TLS_MASTER_SIZE)); + _gnutls_log( "MASTER SECRET: %s\n", _gnutls_bin2hex(state->security_parameters.master_secret, TLS_MASTER_SIZE)); #endif - memcpy(state->security_parameters.master_secret, master, TLS_MASTER_SIZE); - secure_free(master); return ret; } diff --git a/lib/gnutls_mem.c b/lib/gnutls_mem.c index 6ed871a93f..25476482e4 100644 --- a/lib/gnutls_mem.c +++ b/lib/gnutls_mem.c @@ -36,6 +36,7 @@ int _gnutls_is_secure_memory(const void *ign) int _gnutls_is_secure_memory(const svoid * mem) { + if (mem==NULL) return 0; return *((opaque *) mem - 1); } @@ -122,21 +123,26 @@ void *gnutls_realloc_fast(void *ptr, size_t size) void gnutls_free(void *_ptr) { - opaque *ptr = _ptr; - if (_ptr == NULL) return; - ptr -= EXTRA_SIZE; + if ( _gnutls_is_secure_memory( _ptr) != 0) { + return gnutls_secure_free( _ptr); + } else { + opaque *ptr = _ptr; + + + ptr -= EXTRA_SIZE; #ifdef MALLOC_DEBUG - _gnutls_log("Freed: %x with %d bytes\n", _ptr, + _gnutls_log("Freed: %x with %d bytes\n", _ptr, _gnutls_malloc_ptr_size(_ptr)); #endif - free(ptr); + free(ptr); + } } -svoid *secure_malloc(size_t size) +svoid *gnutls_secure_malloc(size_t size) { opaque *ret; ret = gnutls_malloc(size); @@ -149,10 +155,10 @@ svoid *secure_malloc(size_t size) } -svoid *secure_calloc(size_t nmemb, size_t size) +svoid *gnutls_secure_calloc(size_t nmemb, size_t size) { svoid *ret; - ret = secure_malloc(size); + ret = gnutls_secure_malloc(size); if (ret == NULL) return ret; @@ -161,35 +167,39 @@ svoid *secure_calloc(size_t nmemb, size_t size) return ret; } -size_t _secure_ptr_size(svoid * ptr) +size_t _gnutls_secure_ptr_size(svoid * ptr) { return _gnutls_malloc_ptr_size(ptr); } -svoid *secure_realloc(svoid * ptr, size_t size) +svoid *gnutls_secure_realloc(svoid * ptr, size_t size) { svoid *ret; - if (ptr != NULL && size <= _secure_ptr_size(ptr)) { + if (ptr != NULL && size <= _gnutls_secure_ptr_size(ptr)) { /* do not do realloc. * return the previous pointer. */ return ptr; } - ret = secure_malloc(size); + ret = gnutls_secure_malloc(size); if (ret == NULL) return ret; if (ptr != NULL) { - memcpy(ret, ptr, GMIN(_secure_ptr_size(ptr), size)); - secure_free(ptr); + memcpy(ret, ptr, GMIN(_gnutls_secure_ptr_size(ptr), size)); + gnutls_secure_free(ptr); } return ret; } -void secure_free(svoid * ptr) +void gnutls_secure_free(svoid * ptr) { - memset(ptr, 0, _secure_ptr_size(ptr)); +opaque* _ptr = ptr; + + memset(ptr, 0, _gnutls_secure_ptr_size(ptr)); + *((opaque *) _ptr - 1) = 0; /* not secure mem */ + gnutls_free(ptr); } diff --git a/lib/gnutls_mem.h b/lib/gnutls_mem.h index fbe0375cc6..84f9d32610 100644 --- a/lib/gnutls_mem.h +++ b/lib/gnutls_mem.h @@ -2,7 +2,7 @@ # include <dmalloc.h> #endif -typedef void svoid; /* for functions that allocate using secure_free */ +typedef void svoid; /* for functions that allocate using gnutls_secure_free */ #ifdef USE_DMALLOC # define gnutls_malloc malloc @@ -10,20 +10,20 @@ typedef void svoid; /* for functions that allocate using secure_free */ # define gnutls_realloc_fast realloc # define gnutls_free free # define gnutls_calloc calloc -# define secure_malloc malloc -# define secure_realloc realloc -# define secure_free free -# define secure_calloc calloc +# define gnutls_secure_malloc malloc +# define gnutls_secure_realloc realloc +# define gnutls_secure_free free +# define gnutls_secure_calloc calloc # define gnutls_strdup strdup int _gnutls_is_secure_memory(const void*); #else -svoid* secure_malloc( size_t size); -svoid* secure_calloc( size_t nmemb, size_t size); -size_t _secure_ptr_size( svoid* ptr); -svoid* secure_realloc( svoid* ptr, size_t size); -void secure_free( svoid* ptr); +svoid* gnutls_secure_malloc( size_t size); +svoid* gnutls_secure_calloc( size_t nmemb, size_t size); +size_t _gnutls_secure_ptr_size( svoid* ptr); +svoid* gnutls_secure_realloc( svoid* ptr, size_t size); +void gnutls_secure_free( svoid* ptr); int _gnutls_is_secure_memory(const svoid* mem); void* gnutls_malloc( size_t size); diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index 4fb47990b5..14703b8807 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -255,30 +255,23 @@ static void _gnutls_cal_PRF_A( MACAlgorithm algorithm, void *secret, int secret_ return; } -#define MAX_SEED_SIZE 140 +#define MAX_SEED_SIZE 200 /* Produces "total_bytes" bytes using the hash algorithm specified. * (used in the PRF function) */ -static svoid *gnutls_P_hash( MACAlgorithm algorithm, opaque * secret, int secret_size, opaque * seed, int seed_size, int total_bytes) +static int gnutls_P_hash( MACAlgorithm algorithm, opaque * secret, int secret_size, opaque * seed, int seed_size, int total_bytes, opaque* ret) { GNUTLS_MAC_HANDLE td2; - opaque *ret; int i = 0, times, how, blocksize, A_size; opaque final[20], Atmp[MAX_SEED_SIZE]; if (seed_size > MAX_SEED_SIZE || total_bytes<=0) { gnutls_assert(); - return NULL; + return GNUTLS_E_INTERNAL; } - ret = secure_calloc(1, total_bytes); - if (ret==NULL) { - gnutls_assert(); - return ret; - } - blocksize = gnutls_hmac_get_algo_len(algorithm); do { i += blocksize; @@ -312,7 +305,8 @@ static svoid *gnutls_P_hash( MACAlgorithm algorithm, opaque * secret, int secret memcpy(&ret[i * blocksize], final, how); } } - return ret; + + return 0; } /* Function that xor's buffers using the maximum word size supported @@ -335,22 +329,30 @@ int modlen = _length%sizeof(unsigned long int); return ; } +#define MAX_PRF_BYTES 200 + /* The PRF function expands a given secret - * needed by the TLS specification + * needed by the TLS specification. ret must have a least total_bytes + * available. */ -svoid *gnutls_PRF( opaque * secret, int secret_size, uint8 * label, int label_size, opaque * seed, int seed_size, int total_bytes) +int gnutls_PRF( opaque * secret, int secret_size, uint8 * label, int label_size, opaque * seed, int seed_size, int total_bytes, void* ret) { int l_s, s_seed_size; - char *o1, *o2; char *s1, *s2; - char *s_seed; + opaque s_seed[MAX_SEED_SIZE]; + opaque o1[MAX_PRF_BYTES], o2[MAX_PRF_BYTES]; + int result; + if (total_bytes > MAX_PRF_BYTES) { + gnutls_assert(); + return GNUTLS_E_INTERNAL; + } /* label+seed = s_seed */ s_seed_size = seed_size + label_size; - s_seed = gnutls_malloc(s_seed_size); - if (s_seed==NULL) { + + if (s_seed_size > MAX_SEED_SIZE) { gnutls_assert(); - return NULL; + return GNUTLS_E_INTERNAL; } memcpy(s_seed, label, label_size); @@ -364,26 +366,23 @@ svoid *gnutls_PRF( opaque * secret, int secret_size, uint8 * label, int label_si l_s++; } - o1 = gnutls_P_hash( GNUTLS_MAC_MD5, s1, l_s, s_seed, s_seed_size, total_bytes); - if (o1==NULL) { + result = gnutls_P_hash( GNUTLS_MAC_MD5, s1, l_s, s_seed, s_seed_size, total_bytes, o1); + if (result<0) { gnutls_assert(); - return NULL; + return result; } - o2 = gnutls_P_hash( GNUTLS_MAC_SHA, s2, l_s, s_seed, s_seed_size, total_bytes); - if (o2==NULL) { + result = gnutls_P_hash( GNUTLS_MAC_SHA, s2, l_s, s_seed, s_seed_size, total_bytes, o2); + if (result<0) { gnutls_assert(); - return NULL; + return result; } - - gnutls_free(s_seed); - _gnutls_xor(o1, o2, total_bytes); - secure_free(o2); + memcpy( ret, o1, total_bytes); - return o1; + return 0; /* ok */ } |