summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2001-12-10 08:25:38 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2001-12-10 08:25:38 +0000
commit7da050075cf1fa29bb1354cd663ab10db72993c2 (patch)
tree1de7ae76815065ed3062e465e092c42f7382f224
parent148b257d2430cd3edd23f1e416139d86b8f0c900 (diff)
downloadgnutls-7da050075cf1fa29bb1354cd663ab10db72993c2.tar.gz
optimizations and fixes in the TLS PRF calculation (and the SSL3 equivalent)
-rw-r--r--doc/TODO4
-rw-r--r--lib/auth_anon.c2
-rw-r--r--lib/auth_rsa.c6
-rw-r--r--lib/gnutls_constate.c61
-rw-r--r--lib/gnutls_datum.c4
-rw-r--r--lib/gnutls_datum.h2
-rw-r--r--lib/gnutls_errors.c1
-rw-r--r--lib/gnutls_errors_int.h1
-rw-r--r--lib/gnutls_global.c2
-rw-r--r--lib/gnutls_handshake.c93
-rw-r--r--lib/gnutls_hash_int.c45
-rw-r--r--lib/gnutls_hash_int.h2
-rw-r--r--lib/gnutls_int.h21
-rw-r--r--lib/gnutls_kx.c34
-rw-r--r--lib/gnutls_mem.c42
-rw-r--r--lib/gnutls_mem.h20
-rw-r--r--lib/gnutls_record.c57
17 files changed, 233 insertions, 164 deletions
diff --git a/doc/TODO b/doc/TODO
index 85f06464ea..aabefcbe8e 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -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 */
}