diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-06-19 08:52:01 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-06-19 08:52:01 +0000 |
commit | d8b7191de9df39cd78a2c4e5f5c7e6be000e0401 (patch) | |
tree | 104e7aad5e32267ab863dae50f3488f5e28141dc | |
parent | 669edad5e2e0a92411d721064e68e9c8698dd386 (diff) | |
download | gnutls-d8b7191de9df39cd78a2c4e5f5c7e6be000e0401.tar.gz |
fixes in session resuming..
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | doc/TODO | 1 | ||||
-rw-r--r-- | lib/auth_rsa.c | 12 | ||||
-rw-r--r-- | lib/debug.c | 40 | ||||
-rw-r--r-- | lib/debug.h | 3 | ||||
-rw-r--r-- | lib/gnutls.h.in | 2 | ||||
-rw-r--r-- | lib/gnutls_cipher.c | 14 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 547 | ||||
-rw-r--r-- | lib/gnutls_int.h | 8 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 98 | ||||
-rw-r--r-- | lib/gnutls_kx.h | 1 | ||||
-rw-r--r-- | lib/gnutls_record.c | 55 | ||||
-rw-r--r-- | lib/gnutls_session.c | 2 | ||||
-rw-r--r-- | lib/gnutls_v2_compat.c | 3 | ||||
-rw-r--r-- | src/serv.c | 41 |
15 files changed, 478 insertions, 350 deletions
@@ -4,6 +4,7 @@ Version 0.1.4 - Added RSA Ciphersuites (server side only). - Fixes in SSL 2.0 client hello parsing. - Added ASN.1 and DER parsers. +- Bugfixes in session resuming Version 0.1.3 (01/06/2001) - Updated API (and the way it is documented - we use inline documentation) @@ -8,4 +8,3 @@ only one parse of the der structures. * Create global variables that hold read/write and initialize the ASN.1 parser's structures. -* Fix session resuming diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 04a4b4941c..5259359980 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -74,8 +74,8 @@ int _gnutls_calc_rsa_signature( GNUTLS_KEY key, const opaque* data, int data_siz gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - gnutls_hash( td, key->client_random, 32); - gnutls_hash( td, key->server_random, 32); + gnutls_hash( td, key->client_random, TLS_RANDOM_SIZE); + gnutls_hash( td, key->server_random, TLS_RANDOM_SIZE); gnutls_hash( td, data, data_size); md5 = gnutls_hash_deinit(td); @@ -92,8 +92,8 @@ int _gnutls_calc_rsa_signature( GNUTLS_KEY key, const opaque* data, int data_siz gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - gnutls_hash( td, key->client_random, 32); - gnutls_hash( td, key->server_random, 32); + gnutls_hash( td, key->client_random, TLS_RANDOM_SIZE); + gnutls_hash( td, key->server_random, TLS_RANDOM_SIZE); gnutls_hash( td, data, data_size); sha = gnutls_hash_deinit(td); @@ -388,7 +388,7 @@ int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) return pdatasize; } -#define RANDOMIZE_X(x) x.size=48; x.data=gnutls_malloc(x.size); \ +#define RANDOMIZE_X(x) x.size=TLS_MASTER_SIZE; x.data=gnutls_malloc(x.size); \ if (x.data==NULL) return GNUTLS_E_MEMORY_ERROR; \ if (_gnutls_get_random( key->key.data, key->key.size, GNUTLS_WEAK_RANDOM) < 0) { \ return GNUTLS_E_MEMORY_ERROR; \ @@ -419,7 +419,7 @@ int proc_rsa_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { RANDOMIZE_X(key->key); } else { ret = 0; - if (plaintext.size != 48) { /* WOW */ + if (plaintext.size != TLS_MASTER_SIZE) { /* WOW */ RANDOMIZE_X(key->key); } else { if (key->version.major != plaintext.data[0]) ret = GNUTLS_E_DECRYPTION_FAILED; diff --git a/lib/debug.c b/lib/debug.c index 2c61d408bd..98b39f5fea 100644 --- a/lib/debug.c +++ b/lib/debug.c @@ -77,46 +77,6 @@ void _gnutls_print_state(GNUTLS_STATE state) } -void _gnutls_print_TLSCompressed(GNUTLSCompressed * compressed) -{ - fprintf(stderr, "TLSCompressed packet:\n"); - fprintf(stderr, "type: %d\n", compressed->type); - fprintf(stderr, "version: %d,%d\n", compressed->version.major, - compressed->version.minor); - fprintf(stderr, "length: %d\n", compressed->length); - fprintf(stderr, "fragment: %s\n", - _gnutls_bin2hex(compressed->fragment, compressed->length)); - fprintf(stderr, "\n"); -} - - -void _gnutls_print_TLSPlaintext(GNUTLSPlaintext * plaintext) -{ - fprintf(stderr, "TLSPlaintext packet:\n"); - fprintf(stderr, "type: %d\n", plaintext->type); - fprintf(stderr, "version: %d,%d\n", plaintext->version.major, - plaintext->version.minor); - fprintf(stderr, "length: %d\n", plaintext->length); - fprintf(stderr, "fragment: %s\n", - _gnutls_bin2hex(plaintext->fragment, plaintext->length)); - fprintf(stderr, "\n"); -} - - -void _gnutls_print_TLSCiphertext(GNUTLSCiphertext * ciphertext) -{ - - fprintf(stderr, "TLSCiphertext packet:\n"); - fprintf(stderr, "type: %d\n", ciphertext->type); - fprintf(stderr, "version: %d,%d\n", ciphertext->version.major, - ciphertext->version.minor); - fprintf(stderr, "length: %d\n", ciphertext->length); - - fprintf(stderr, "fragment: %s\n", - _gnutls_bin2hex(ciphertext->fragment, ciphertext->length)); - fprintf(stderr, "\n"); -} - char* _gnutls_alert2str( int alert) { static char str[512]; diff --git a/lib/debug.h b/lib/debug.h index b793c1a106..85ad14b261 100644 --- a/lib/debug.h +++ b/lib/debug.h @@ -20,9 +20,6 @@ #ifdef DEBUG void _gnutls_print_state(GNUTLS_STATE state); -void _gnutls_print_TLSCompressed(GNUTLSCompressed * compressed); -void _gnutls_print_TLSPlaintext(GNUTLSPlaintext * plaintext); -void _gnutls_print_TLSCiphertext( GNUTLSCiphertext *); char * _gnutls_bin2hex(const unsigned char *old, const size_t oldlen); void _gnutls_dump_mpi(char* prefix,MPI a); char* _gnutls_packet2str( int packet); diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in index 80a5e61748..9283d26f0f 100644 --- a/lib/gnutls.h.in +++ b/lib/gnutls.h.in @@ -56,6 +56,8 @@ typedef struct { int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end); int gnutls_deinit(GNUTLS_STATE state); int gnutls_bye(SOCKET cd, GNUTLS_STATE state); +int gnutls_bye_nowait(SOCKET cd, GNUTLS_STATE state); + int gnutls_handshake(SOCKET cd, GNUTLS_STATE state); int gnutls_check_pending(GNUTLS_STATE state); int gnutls_rehandshake(SOCKET cd, GNUTLS_STATE state); diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c index 942bff194a..41b451d2c0 100644 --- a/lib/gnutls_cipher.c +++ b/lib/gnutls_cipher.c @@ -30,6 +30,7 @@ #include "gnutls_random.h" #include "gnutls_num.h" #include "gnutls_datum.h" +#include "gnutls_kx.h" int _gnutls_encrypt(GNUTLS_STATE state, const char *data, size_t data_size, uint8 ** ciphertext, ContentType type) @@ -186,7 +187,7 @@ int _gnutls_set_mac(GNUTLS_STATE state, MACAlgorithm algo) */ int _gnutls_connection_state_init(GNUTLS_STATE state) { - int rc, mac_size; + int rc, mac_size, ret; uint64zero(&state->connection_state.write_sequence_number); uint64zero(&state->connection_state.read_sequence_number); @@ -225,19 +226,20 @@ int _gnutls_connection_state_init(GNUTLS_STATE state) /* clear the resumed security parameters */ memset( &state->gnutls_internals.resumed_security_parameters, 0, sizeof(SecurityParameters)); -#ifdef HARD_DEBUG - fprintf(stderr, "Master Secret: %s\n", _gnutls_bin2hex(state->security_parameters.master_secret, 48)); -#endif } /* Setup the keys since we have the master secret */ - _gnutls_set_keys(state); + if ( (ret=_gnutls_generate_master(state)) < 0) { + gnutls_assert(); + return ret; + } + _gnutls_set_keys(state); #ifdef DEBUG fprintf(stderr, "Cipher Suite: %s\n", _gnutls_cipher_suite_get_name(state-> - security_parameters.current_suite)); + security_parameters.current_cipher_suite)); #endif if (state->connection_state.write_mac_secret!=NULL) diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 957bd009f1..f268270941 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -46,18 +46,63 @@ #define TRUE 1 #define FALSE 0 -static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, int datalen); -int _gnutls_SelectCompMethod(GNUTLS_STATE state, CompressionMethod * ret, opaque * data, int datalen); +static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, + int datalen); +int _gnutls_SelectCompMethod(GNUTLS_STATE state, CompressionMethod * ret, + opaque * data, int datalen); -void _gnutls_set_server_random( GNUTLS_STATE state, uint8* random) { - memcpy( state->security_parameters.server_random, random, TLS_RANDOM_SIZE); - if (state->gnutls_key!=NULL) - memcpy( state->gnutls_key->server_random, random, TLS_RANDOM_SIZE); +/* this will keep as less data to security_parameters. + */ +static void resume_copy_required_values(GNUTLS_STATE state) { + /* get the new random values */ + memcpy(state->gnutls_internals.resumed_security_parameters. + server_random, + state->security_parameters.server_random, + TLS_RANDOM_SIZE); + memcpy(state->gnutls_internals.resumed_security_parameters. + client_random, + state->security_parameters.client_random, + TLS_RANDOM_SIZE); + + /* keep the ciphersuite and compression + * That is because the client must see these in our + * hello message. + */ + memcpy(state->security_parameters.current_cipher_suite. + CipherSuite, + state->gnutls_internals.resumed_security_parameters. + current_cipher_suite.CipherSuite, 2); + state->gnutls_internals.compression_method = + state->gnutls_internals.resumed_security_parameters. + compression_algorithm; + + memcpy(state->security_parameters.session_id, + state->gnutls_internals.resumed_security_parameters. + session_id, sizeof(state->security_parameters.session_id)); + state->security_parameters.session_id_size = + state->gnutls_internals.resumed_security_parameters. + session_id_size; + + + return; } -void _gnutls_set_client_random( GNUTLS_STATE state, uint8* random) { - memcpy( state->security_parameters.client_random, random, TLS_RANDOM_SIZE); - if (state->gnutls_key!=NULL) - memcpy( state->gnutls_key->client_random, random, TLS_RANDOM_SIZE); + +void _gnutls_set_server_random(GNUTLS_STATE state, uint8 * random) +{ + memcpy(state->security_parameters.server_random, random, + TLS_RANDOM_SIZE); + if (state->gnutls_key != NULL) + memcpy(state->gnutls_key->server_random, random, + TLS_RANDOM_SIZE); +} + +void _gnutls_set_client_random(GNUTLS_STATE state, uint8 * random) +{ + memcpy(state->security_parameters.client_random, random, + TLS_RANDOM_SIZE); + if (state->gnutls_key != NULL) + memcpy(state->gnutls_key->client_random, random, + TLS_RANDOM_SIZE); } /* Calculate The SSL3 Finished message */ @@ -157,19 +202,21 @@ void *_gnutls_finished(GNUTLS_STATE state, int type, int skip) /* this function will produce TLS_RANDOM_SIZE bytes of random data * and put it to dst. */ -int _gnutls_create_random( opaque* dst) { -uint32 tim; -opaque rand[TLS_RANDOM_SIZE-4]; +int _gnutls_create_random(opaque * dst) +{ + uint32 tim; + opaque rand[TLS_RANDOM_SIZE - 4]; tim = time(NULL); /* generate server random value */ - WRITEuint32( tim, dst); + WRITEuint32(tim, dst); - if (_gnutls_get_random(rand, TLS_RANDOM_SIZE-4, GNUTLS_STRONG_RANDOM) < 0) { + if (_gnutls_get_random + (rand, TLS_RANDOM_SIZE - 4, GNUTLS_STRONG_RANDOM) < 0) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - memcpy( &dst[4], rand, 28); + memcpy(&dst[4], rand, 28); return 0; } @@ -194,7 +241,7 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, int err; opaque random[TLS_RANDOM_SIZE]; - if (state->gnutls_internals.v2_hello!=0) { /* version 2.0 */ + if (state->gnutls_internals.v2_hello != 0) { /* version 2.0 */ return _gnutls_read_client_hello_v2(state, data, datalen); } @@ -218,11 +265,11 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, pos += 2; DECR_LEN(len, TLS_RANDOM_SIZE); - _gnutls_set_client_random( state, &data[pos]); + _gnutls_set_client_random(state, &data[pos]); pos += TLS_RANDOM_SIZE; - _gnutls_create_random( random); - _gnutls_set_server_random( state, random); + _gnutls_create_random(random); + _gnutls_set_server_random(state, random); state->security_parameters.timestamp = time(NULL); @@ -234,7 +281,7 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - + DECR_LEN(len, session_id_len); ret = _gnutls_server_restore_session(state, &data[pos], @@ -242,24 +289,7 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, pos += session_id_len; if (ret == 0) { /* resumed! */ - /* get the new random values */ - memcpy(state->gnutls_internals.resumed_security_parameters. - server_random, - state->security_parameters.server_random, TLS_RANDOM_SIZE); - memcpy(state->gnutls_internals.resumed_security_parameters. - client_random, - state->security_parameters.client_random, TLS_RANDOM_SIZE); - - /* keep the ciphersuite and compression - * That is because the client must see these in our - * hello message. - */ - memcpy( state->security_parameters.current_cipher_suite.CipherSuite, - state->gnutls_internals.resumed_security_parameters.current_cipher_suite.CipherSuite, - 2); - state->gnutls_internals.compression_method = - state->gnutls_internals.resumed_security_parameters.compression_algorithm; - + resume_copy_required_values(state); state->gnutls_internals.resumed = RESUME_TRUE; return 0; @@ -273,7 +303,7 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, } /* Select a ciphersuite */ DECR_LEN(len, 2); - sizeOfSuites = READuint16( &data[pos]); + sizeOfSuites = READuint16(&data[pos]); pos += 2; DECR_LEN(len, sizeOfSuites); @@ -321,10 +351,12 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, DECR_LEN(len, z); ret = _gnutls_SelectCompMethod(state, &state-> - gnutls_internals.compression_method, - &data[pos], z); -#ifdef HARD_DEBUG - fprintf(stderr, "Selected Compression Method: %s\n", gnutls_compression_get_name(state->gnutls_internals.compression_method)); + gnutls_internals.compression_method, + &data[pos], z); +#ifdef HANDSHAKE_DEBUG + fprintf(stderr, "Selected Compression Method: %s\n", + gnutls_compression_get_name(state->gnutls_internals. + compression_method)); #endif pos += z; @@ -444,7 +476,7 @@ static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, GNUTLS_CipherSuite *ciphers; x = _gnutls_supported_ciphersuites(state, &ciphers); -#ifdef HARD_DEBUG +#ifdef HANDSHAKE_DEBUG fprintf(stderr, "Requested cipher suites: \n"); for (j = 0; j < datalen; j += 2) fprintf(stderr, "\t%s\n", @@ -462,7 +494,7 @@ static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, for (i = 0; i < x; i++) { if (memcmp(ciphers[i].CipherSuite, &data[j], 2) == 0) { -#ifdef HARD_DEBUG +#ifdef HANDSHAKE_DEBUG fprintf(stderr, "Selected cipher suite: "); fprintf(stderr, "%s\n", _gnutls_cipher_suite_get_name(* @@ -486,7 +518,7 @@ static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, /* This selects the best supported compression method from the ones provided */ int _gnutls_SelectCompMethod(GNUTLS_STATE state, CompressionMethod * ret, - opaque * data, int datalen) + opaque * data, int datalen) { int x, i, j; uint8 *ciphers; @@ -497,7 +529,8 @@ int _gnutls_SelectCompMethod(GNUTLS_STATE state, CompressionMethod * ret, for (j = 0; j < datalen; j++) { for (i = 0; i < x; i++) { if (ciphers[i] == data[j]) { - *ret = _gnutls_compression_get_id(ciphers[i]); + *ret = + _gnutls_compression_get_id(ciphers[i]); gnutls_free(ciphers); return 0; } @@ -527,8 +560,8 @@ int _gnutls_send_handshake(SOCKET cd, GNUTLS_STATE state, void *i_data, data = gnutls_malloc(i_datasize); memcpy(&data[pos++], &type, 1); - WRITEuint24( datasize, &data[pos]); - pos+=3; + WRITEuint24(datasize, &data[pos]); + pos += 3; if (i_datasize > 4) memcpy(&data[pos], i_data, i_datasize - 4); @@ -563,41 +596,51 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, { int ret; uint32 length32 = 0, sum = 0; - uint8 *dataptr=NULL; /* for realloc */ + uint8 *dataptr = NULL; /* for realloc */ int handshake_headers = HANDSHAKE_HEADERS_SIZE; HandshakeType recv_type; if (type == GNUTLS_CERTIFICATE) { /* If the ciphersuite does not support certificate just quit */ if (state->security_parameters.entity == GNUTLS_CLIENT) { - if (_gnutls_kx_server_certificate( _gnutls_cipher_suite_get_kx_algo( state->security_parameters.current_cipher_suite) ) == 0) + if (_gnutls_kx_server_certificate + (_gnutls_cipher_suite_get_kx_algo + (state->security_parameters. + current_cipher_suite)) == 0) return 0; } else { /* server */ - if (_gnutls_kx_client_certificate( _gnutls_cipher_suite_get_kx_algo( state->security_parameters.current_cipher_suite) ) == 0) + if (_gnutls_kx_client_certificate + (_gnutls_cipher_suite_get_kx_algo + (state->security_parameters. + current_cipher_suite)) == 0) return 0; } } dataptr = gnutls_malloc(HANDSHAKE_HEADERS_SIZE); - + ret = - _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, dataptr, SSL2_HEADERS); + _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, dataptr, + SSL2_HEADERS); if (ret < 0) { gnutls_assert(); gnutls_free(dataptr); return ret; } - if (ret!=SSL2_HEADERS) { + if (ret != SSL2_HEADERS) { gnutls_assert(); gnutls_free(dataptr); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - if ( state->gnutls_internals.v2_hello == 0 || type != GNUTLS_CLIENT_HELLO) { + if (state->gnutls_internals.v2_hello == 0 + || type != GNUTLS_CLIENT_HELLO) { ret = - _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, &dataptr[SSL2_HEADERS], - HANDSHAKE_HEADERS_SIZE-SSL2_HEADERS); + _gnutls_Recv_int(cd, state, GNUTLS_HANDSHAKE, + &dataptr[SSL2_HEADERS], + HANDSHAKE_HEADERS_SIZE - + SSL2_HEADERS); if (ret < 0) { gnutls_assert(); gnutls_free(dataptr); @@ -610,14 +653,14 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, } recv_type = dataptr[0]; - + if (recv_type != type) { gnutls_assert(); gnutls_free(dataptr); return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET; } - - length32 = READuint24( &dataptr[1]); + + length32 = READuint24(&dataptr[1]); #ifdef HANDSHAKE_DEBUG fprintf(stderr, "Handshake: %s was received [%ld bytes]\n", @@ -626,31 +669,31 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, #endif - } else { /* v2 hello */ - length32 = state->gnutls_internals.v2_hello - SSL2_HEADERS; /* we've read the first byte */ - - handshake_headers = SSL2_HEADERS; /* we've already read one byte */ + } else { /* v2 hello */ + length32 = state->gnutls_internals.v2_hello - SSL2_HEADERS; /* we've read the first byte */ + + handshake_headers = SSL2_HEADERS; /* we've already read one byte */ recv_type = dataptr[0]; #ifdef HANDSHAKE_DEBUG - fprintf(stderr, "Handshake: %s(v2) was received [%ld bytes]\n", + fprintf(stderr, + "Handshake: %s(v2) was received [%ld bytes]\n", _gnutls_handshake2str(recv_type), length32 + handshake_headers); #endif - if (recv_type != GNUTLS_CLIENT_HELLO) { /* it should be one or nothing */ + if (recv_type != GNUTLS_CLIENT_HELLO) { /* it should be one or nothing */ gnutls_assert(); return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET; } } - dataptr = - gnutls_realloc(dataptr, length32 + handshake_headers); + dataptr = gnutls_realloc(dataptr, length32 + handshake_headers); if (length32 > 0 && data != NULL) *data = gnutls_malloc(length32); if (datalen != NULL) - *datalen = length32; + *datalen = length32; sum = handshake_headers; do { @@ -659,7 +702,7 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, &dataptr[sum], length32); sum += ret; } while (((sum - handshake_headers) < length32) && (ret > 0)); - + if (ret < 0) { gnutls_assert(); gnutls_free(dataptr); @@ -671,9 +714,10 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, memcpy(*data, &dataptr[handshake_headers], length32); /* here we buffer the handshake messages - needed at Finished message */ - - if (recv_type!=GNUTLS_HELLO_REQUEST) - gnutls_insertHashDataBuffer(state, dataptr, length32 + handshake_headers); + + if (recv_type != GNUTLS_HELLO_REQUEST) + gnutls_insertHashDataBuffer(state, dataptr, + length32 + handshake_headers); switch (recv_type) { case GNUTLS_CLIENT_HELLO: @@ -703,7 +747,7 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, ret = length32; break; case GNUTLS_CERTIFICATE_REQUEST: -#ifdef HARD_DEBUG +#ifdef HANDSHAKE_DEBUG fprintf(stderr, "Requested Client Certificate!\n"); #endif /* FIXME: just ignore that message for the time being @@ -734,14 +778,14 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, **/ int gnutls_rehandshake(SOCKET cd, GNUTLS_STATE state) { -int ret; + int ret; /* only server sends that handshake packet */ if (state->security_parameters.entity == GNUTLS_CLIENT) return GNUTLS_E_UNIMPLEMENTED_FEATURE; ret = _gnutls_send_handshake(cd, state, NULL, 0, - GNUTLS_HELLO_REQUEST); + GNUTLS_HELLO_REQUEST); if (ret < 0) { gnutls_assert(); @@ -764,7 +808,7 @@ int _gnutls_send_client_certificate(SOCKET cd, GNUTLS_STATE state) /* we do not have that functionality yet */ state->gnutls_internals.certificate_verify_needed = 0; -#ifdef HARD_DEBUG +#ifdef HANDSHAKE_DEBUG fprintf(stderr, "Sending Client Certificate\n"); #endif @@ -778,7 +822,8 @@ int _gnutls_send_client_certificate(SOCKET cd, GNUTLS_STATE state) return ret; } -static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datalen) +static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, + int datalen) { uint8 session_id_len = 0, z; int pos = 0; @@ -809,7 +854,7 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale pos += 2; DECR_LEN(len, TLS_RANDOM_SIZE); - _gnutls_set_server_random( state, &data[pos]); + _gnutls_set_server_random(state, &data[pos]); pos += TLS_RANDOM_SIZE; DECR_LEN(len, 1); @@ -822,7 +867,7 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale DECR_LEN(len, session_id_len); -#ifdef HARD_DEBUG +#ifdef HANDSHAKE_DEBUG fprintf(stderr, "SessionID length: %d\n", session_id_len); fprintf(stderr, "SessionID: %s\n", _gnutls_bin2hex(&data[pos], session_id_len)); @@ -852,9 +897,9 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale session_id_len; memcpy(state->security_parameters.session_id, &data[pos], session_id_len); - } - pos += session_id_len; - DECR_LEN(len, 2); + } + pos += session_id_len; + DECR_LEN(len, 2); memcpy(cipher_suite.CipherSuite, &data[pos], 2); pos += 2; @@ -873,15 +918,15 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale } memcpy(state->security_parameters. - current_cipher_suite.CipherSuite, - cipher_suite.CipherSuite, 2); + current_cipher_suite.CipherSuite, + cipher_suite.CipherSuite, 2); -#ifdef HARD_DEBUG +#ifdef HANDSHAKE_DEBUG fprintf(stderr, "Selected cipher suite: "); fprintf(stderr, "%s\n", _gnutls_cipher_suite_get_name(state-> - security_parameters. - current_cipher_suite)); + security_parameters. + current_cipher_suite)); #endif /* check if the credentials (username, public key etc. are ok - actually check if they exist) @@ -905,8 +950,8 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale (cipher_suite)); if (state->gnutls_internals.auth_struct == NULL) { #ifdef DEBUG - fprintf(stderr, - "Cannot find the appropriate handler for the KX algorithm\n"); + fprintf(stderr, + "Cannot find the appropriate handler for the KX algorithm\n"); #endif gnutls_assert(); return GNUTLS_E_UNKNOWN_CIPHER_TYPE; @@ -933,7 +978,7 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM; } state->gnutls_internals.compression_method = - _gnutls_compression_get_id( compression_method); + _gnutls_compression_get_id(compression_method); gnutls_free(cipher_suites); gnutls_free(compression_methods); @@ -943,11 +988,12 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale gnutls_assert(); return ret; } - + return ret; } -int _gnutls_send_hello(SOCKET cd, GNUTLS_STATE state) + +static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state) { char *data = NULL; opaque *extdata; @@ -960,140 +1006,168 @@ int _gnutls_send_hello(SOCKET cd, GNUTLS_STATE state) uint16 x; opaque random[TLS_RANDOM_SIZE]; - if (state->security_parameters.entity == GNUTLS_CLIENT) { - opaque * SessionID = state->gnutls_internals.resumed_security_parameters.session_id; - uint8 session_id_len = state->gnutls_internals.resumed_security_parameters.session_id_size; - - if (SessionID==NULL) session_id_len = 0; - - datalen = 2 + 4 + (session_id_len + 1) + 28 + 3; - /* 2 for version, 4 for unix time, 28 for random bytes 2 for cipher suite's - * size and 1 for compression method's size - */ - data = gnutls_malloc(datalen); + opaque *SessionID = + state->gnutls_internals.resumed_security_parameters.session_id; + uint8 session_id_len = + state->gnutls_internals.resumed_security_parameters. + session_id_size; + + if (SessionID == NULL) + session_id_len = 0; - data[pos++] = - _gnutls_version_get_major(state->connection_state. - version); - data[pos++] = - _gnutls_version_get_minor(state->connection_state. - version); + datalen = 2 + 4 + (session_id_len + 1) + 28 + 3; + /* 2 for version, 4 for unix time, 28 for random bytes 2 for cipher suite's + * size and 1 for compression method's size + */ + data = gnutls_malloc(datalen); - _gnutls_create_random( random); - _gnutls_set_client_random( state, random); - - state->security_parameters.timestamp = time(0); + data[pos++] = + _gnutls_version_get_major(state->connection_state.version); + data[pos++] = + _gnutls_version_get_minor(state->connection_state.version); - memcpy(&data[pos], - state->security_parameters.client_random, TLS_RANDOM_SIZE); - pos += TLS_RANDOM_SIZE; + _gnutls_create_random(random); + _gnutls_set_client_random(state, random); - memcpy(&data[pos++], &session_id_len, 1); + state->security_parameters.timestamp = time(0); - if (session_id_len > 0) { - memcpy(&data[pos], SessionID, session_id_len); - } - pos += session_id_len; + memcpy(&data[pos], + state->security_parameters.client_random, TLS_RANDOM_SIZE); + pos += TLS_RANDOM_SIZE; - x = _gnutls_supported_ciphersuites_sorted(state, - &cipher_suites); - x *= sizeof(uint16); /* in order to get bytes */ + memcpy(&data[pos++], &session_id_len, 1); - WRITEuint16( x, &data[pos]); - pos += sizeof(uint16); + if (session_id_len > 0) { + memcpy(&data[pos], SessionID, session_id_len); + } + pos += session_id_len; - datalen += x; - data = gnutls_realloc(data, datalen); + x = _gnutls_supported_ciphersuites_sorted(state, &cipher_suites); + x *= sizeof(uint16); /* in order to get bytes */ - for (i = 0; i < x / 2; i++) { - memcpy(&data[pos], cipher_suites[i].CipherSuite, - 2); - pos += 2; - } - gnutls_free(cipher_suites); + WRITEuint16(x, &data[pos]); + pos += sizeof(uint16); + + datalen += x; + data = gnutls_realloc(data, datalen); + + for (i = 0; i < x / 2; i++) { + memcpy(&data[pos], cipher_suites[i].CipherSuite, 2); + pos += 2; + } + gnutls_free(cipher_suites); + + z = _gnutls_supported_compression_methods + (state, &compression_methods); + + memcpy(&data[pos++], &z, 1); /* put the number of compression methods */ - z = _gnutls_supported_compression_methods - (state, &compression_methods); + datalen += z; + data = gnutls_realloc(data, datalen); + + for (i = 0; i < z; i++) { + memcpy(&data[pos++], &compression_methods[i], 1); + } - memcpy(&data[pos++], &z, 1); /* put the number of compression methods */ + gnutls_free(compression_methods); - datalen += z; + extdatalen = _gnutls_gen_extensions(state, &extdata); + if (extdatalen > 0) { + datalen += extdatalen; data = gnutls_realloc(data, datalen); + memcpy(&data[pos], extdata, extdatalen); + gnutls_free(extdata); + } - for (i = 0; i < z; i++) { - memcpy(&data[pos++], &compression_methods[i], 1); - } + ret = + _gnutls_send_handshake(cd, state, data, datalen, + GNUTLS_CLIENT_HELLO); + gnutls_free(data); - gnutls_free(compression_methods); - extdatalen = _gnutls_gen_extensions(state, &extdata); - if (extdatalen > 0) { - datalen += extdatalen; - data = gnutls_realloc(data, datalen); - memcpy(&data[pos], extdata, extdatalen); - gnutls_free(extdata); - } - ret = - _gnutls_send_handshake(cd, state, data, datalen, - GNUTLS_CLIENT_HELLO); - gnutls_free(data); + return ret; +} +static int _gnutls_send_server_hello(SOCKET cd, GNUTLS_STATE state) +{ + char *data = NULL; + opaque *extdata; + int extdatalen; + int pos = 0; + int datalen, ret = 0; + uint8 comp; + opaque *SessionID = state->security_parameters.session_id; + uint8 session_id_len = state->security_parameters.session_id_size; - } else { /* SERVER */ - uint8 comp; - opaque * SessionID = state->security_parameters.session_id; - uint8 session_id_len = state->security_parameters.session_id_size; - - if (SessionID==NULL) session_id_len = 0; - - datalen = 2 + session_id_len + 1 + TLS_RANDOM_SIZE; - data = gnutls_malloc(datalen); - - data[pos++] = - _gnutls_version_get_major(state->connection_state. - version); - data[pos++] = - _gnutls_version_get_minor(state->connection_state. - version); - - memcpy(&data[pos], - state->security_parameters.server_random, TLS_RANDOM_SIZE); - pos += TLS_RANDOM_SIZE; - - memcpy(&data[pos++], &session_id_len, sizeof(uint8)); - if (session_id_len > 0) { - memcpy(&data[pos], SessionID, session_id_len); - } - pos += session_id_len; + if (SessionID == NULL) + session_id_len = 0; - datalen += 2; - data = gnutls_realloc(data, datalen); - - memcpy(&data[pos], - state->security_parameters. - current_cipher_suite.CipherSuite, 2); - pos += 2; + datalen = 2 + session_id_len + 1 + TLS_RANDOM_SIZE; + data = gnutls_malloc(datalen); + + data[pos++] = + _gnutls_version_get_major(state->connection_state.version); + data[pos++] = + _gnutls_version_get_minor(state->connection_state.version); + + memcpy(&data[pos], + state->security_parameters.server_random, TLS_RANDOM_SIZE); + pos += TLS_RANDOM_SIZE; + + data[pos++] = session_id_len; + if (session_id_len > 0) { + memcpy(&data[pos], SessionID, session_id_len); + } + pos += session_id_len; + +#ifdef HANDSHAKE_DEBUG + fprintf(stderr, "Handshake: SessionID: %s\n", + _gnutls_bin2hex(SessionID, session_id_len)); +#endif + + datalen += 2; + data = gnutls_realloc(data, datalen); + + memcpy(&data[pos], + state->security_parameters. + current_cipher_suite.CipherSuite, 2); + pos += 2; + + datalen += 1; + data = gnutls_realloc(data, datalen); - datalen += 1; + comp = + (uint8) _gnutls_compression_get_num(state->gnutls_internals. + compression_method); + memcpy(&data[pos++], &comp, 1); + + extdatalen = _gnutls_gen_extensions(state, &extdata); + if (extdatalen > 0) { + datalen += extdatalen; data = gnutls_realloc(data, datalen); - - comp = (uint8) _gnutls_compression_get_num(state->gnutls_internals.compression_method); - memcpy(&data[pos++], &comp, 1); - - extdatalen = _gnutls_gen_extensions(state, &extdata); - if (extdatalen > 0) { - datalen += extdatalen; - data = gnutls_realloc(data, datalen); - memcpy(&data[pos], extdata, extdatalen); - gnutls_free(extdata); - } + memcpy(&data[pos], extdata, extdatalen); + gnutls_free(extdata); + } - ret = - _gnutls_send_handshake(cd, state, data, datalen, - GNUTLS_SERVER_HELLO); - gnutls_free(data); + ret = + _gnutls_send_handshake(cd, state, data, datalen, + GNUTLS_SERVER_HELLO); + gnutls_free(data); + + + return ret; +} + +int _gnutls_send_hello(SOCKET cd, GNUTLS_STATE state) +{ + int ret; + + if (state->security_parameters.entity == GNUTLS_CLIENT) { + ret = _gnutls_send_client_hello(cd, state); + } else { /* SERVER */ + ret = _gnutls_send_server_hello(cd, state); } return ret; @@ -1103,14 +1177,15 @@ int _gnutls_send_hello(SOCKET cd, GNUTLS_STATE state) * hello message is expected. It uses the security_parameters.current_cipher_suite * and gnutls_internals.compression_method. */ -int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data, int datalen) +int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data, + int datalen) { -int ret; + int ret; if (state->security_parameters.entity == GNUTLS_CLIENT) { ret = _gnutls_read_server_hello(state, data, datalen); if (ret < 0) { - _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_HANDSHAKE_FAILURE); /* send handshake failure */ + _gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_HANDSHAKE_FAILURE); /* send handshake failure */ gnutls_assert(); return ret; } @@ -1118,7 +1193,7 @@ int ret; ret = _gnutls_read_client_hello(state, data, datalen); if (ret < 0) { - _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_HANDSHAKE_FAILURE); /* send handshake failure */ + _gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_HANDSHAKE_FAILURE); /* send handshake failure */ gnutls_assert(); return ret; } @@ -1141,7 +1216,7 @@ int _gnutls_recv_certificate(SOCKET cd, GNUTLS_STATE state, char *data, return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - sizeOfCert = READuint24( &data[pos]); + sizeOfCert = READuint24(&data[pos]); pos += 3; if (sizeOfCert > MAX24) { @@ -1217,7 +1292,7 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) int ret; if (state->security_parameters.entity == GNUTLS_CLIENT) { -#ifdef HARD_DEBUG +#ifdef HANDSHAKE_DEBUG if (state->gnutls_internals.resumed_security_parameters. session_id_size > 0) fprintf(stderr, "Ask to resume: %s\n", @@ -1228,8 +1303,7 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) resumed_security_parameters. session_id_size)); #endif - ret = - _gnutls_send_hello(cd, state); + ret = _gnutls_send_hello(cd, state); if (ret < 0) { ERR("send hello", ret); gnutls_clearHashDataBuffer(state); @@ -1269,8 +1343,7 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) return ret; } - ret = - _gnutls_send_hello(cd, state); + ret = _gnutls_send_hello(cd, state); if (ret < 0) { ERR("send hello", ret); gnutls_assert(); @@ -1339,7 +1412,6 @@ static int _gnutls_send_handshake_final(SOCKET cd, GNUTLS_STATE state, ret = _gnutls_send_change_cipher_spec(cd, state); if (ret < 0) { ERR("send ChangeCipherSpec", ret); - gnutls_clearHashDataBuffer(state); return ret; } @@ -1348,7 +1420,6 @@ static int _gnutls_send_handshake_final(SOCKET cd, GNUTLS_STATE state, ret = _gnutls_connection_state_init(state); if (ret < 0) { gnutls_assert(); - gnutls_clearHashDataBuffer(state); return ret; } } @@ -1357,7 +1428,6 @@ static int _gnutls_send_handshake_final(SOCKET cd, GNUTLS_STATE state, ret = _gnutls_send_finished(cd, state); if (ret < 0) { ERR("send Finished", ret); - gnutls_clearHashDataBuffer(state); return ret; } return ret; @@ -1375,7 +1445,6 @@ static int _gnutls_recv_handshake_final(SOCKET cd, GNUTLS_STATE state, NULL, 0, 0); if (ret < 0) { ERR("recv ChangeCipherSpec", ret); - gnutls_clearHashDataBuffer(state); return ret; } @@ -1384,7 +1453,6 @@ static int _gnutls_recv_handshake_final(SOCKET cd, GNUTLS_STATE state, ret = _gnutls_connection_state_init(state); if (ret < 0) { gnutls_assert(); - gnutls_clearHashDataBuffer(state); return ret; } } @@ -1392,7 +1460,6 @@ static int _gnutls_recv_handshake_final(SOCKET cd, GNUTLS_STATE state, ret = _gnutls_recv_finished(cd, state); if (ret < 0) { ERR("recv finished", ret); - gnutls_clearHashDataBuffer(state); return ret; } return ret; @@ -1534,7 +1601,9 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) gnutls_assert(); gnutls_clearHashDataBuffer(state); /* for srp */ - if (state->security_parameters.kx_algorithm==GNUTLS_KX_SRP) return GNUTLS_E_AUTH_FAILED; + if (state->security_parameters.kx_algorithm == + GNUTLS_KX_SRP) + return GNUTLS_E_AUTH_FAILED; return ret; } @@ -1558,7 +1627,9 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) gnutls_assert(); gnutls_clearHashDataBuffer(state); /* in srp failure here - means authentication error */ - if (state->security_parameters.kx_algorithm==GNUTLS_KX_SRP) return GNUTLS_E_AUTH_FAILED; + if (state->security_parameters.kx_algorithm == + GNUTLS_KX_SRP) + return GNUTLS_E_AUTH_FAILED; return ret; } } @@ -1577,7 +1648,8 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) int _gnutls_generate_session_id(char *session_id, uint8 * len) { opaque rand[TLS_RANDOM_SIZE]; - if (_gnutls_get_random(rand, TLS_RANDOM_SIZE, GNUTLS_WEAK_RANDOM) < 0) { + if (_gnutls_get_random(rand, TLS_RANDOM_SIZE, GNUTLS_WEAK_RANDOM) < + 0) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } @@ -1585,45 +1657,50 @@ int _gnutls_generate_session_id(char *session_id, uint8 * len) memcpy(session_id, rand, TLS_RANDOM_SIZE); *len = TLS_RANDOM_SIZE; -#ifdef HARD_DEBUG +#ifdef HANDSHAKE_DEBUG fprintf(stderr, "Generated SessionID: %s\n", _gnutls_bin2hex(session_id, TLS_RANDOM_SIZE)); #endif return 0; } + #define RENEGOTIATE -int _gnutls_recv_hello_request(SOCKET cd, GNUTLS_STATE state, void* data, uint32 data_size) { +int _gnutls_recv_hello_request(SOCKET cd, GNUTLS_STATE state, void *data, + uint32 data_size) +{ #ifndef RENEGOTIATE -int ret; + int ret; /* only client should receive that */ if (state->security_parameters.entity == GNUTLS_SERVER) return GNUTLS_E_UNEXPECTED_PACKET; /* just return an alert that we don't like that */ - ret = _gnutls_send_alert( cd, state, GNUTLS_WARNING, GNUTLS_NO_RENEGOTIATION); + ret = + _gnutls_send_alert(cd, state, GNUTLS_WARNING, + GNUTLS_NO_RENEGOTIATION); if (ret < 0) { gnutls_assert(); return ret; } return 0; -#else /* this does not seem to work - yet */ -uint8 type; +#else /* this does not seem to work - yet */ + uint8 type; if (state->security_parameters.entity == GNUTLS_SERVER) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET; } - + if (data_size < 1) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - - type = ((uint8*)data)[0]; - if (type==GNUTLS_HELLO_REQUEST) - return gnutls_handshake( cd, state); + + type = ((uint8 *) data)[0]; + if (type == GNUTLS_HELLO_REQUEST) + return gnutls_handshake(cd, state); else { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 487cd44ece..0b81352850 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -27,10 +27,11 @@ #define READ_DEBUG #define WRITE_DEBUG #define BUFFERS_DEBUG -#define HANDSHAKE_DEBUG +*/#define HANDSHAKE_DEBUG +/*#define RECORD_DEBUG #define HARD_DEBUG -#define DEBUG */ +#define DEBUG #define SOCKET int #define LIST ... @@ -41,6 +42,7 @@ #define TLS_RANDOM_SIZE 32 #define TLS_MAX_SESSION_ID_SIZE 32 +#define TLS_MASTER_SIZE 48 /* the default for TCP */ #define DEFAULT_LOWAT 1 @@ -207,7 +209,7 @@ typedef struct { uint8 key_size; uint8 key_material_length; uint8 hash_size; - opaque master_secret[48]; + opaque master_secret[TLS_MASTER_SIZE]; opaque client_random[TLS_RANDOM_SIZE]; opaque server_random[TLS_RANDOM_SIZE]; opaque session_id[TLS_MAX_SESSION_ID_SIZE]; diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index b31dfacfc6..261ece77d1 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Nikos Mavroyanopoulos + * Copyright (C) 2000,2001 Nikos Mavroyanopoulos * * This file is part of GNUTLS. * @@ -29,52 +29,105 @@ #include "gnutls_gcry.h" #define MASTER_SECRET "master secret" +static int generate_normal_master( GNUTLS_STATE state); +static int generate_resumed_master( GNUTLS_STATE state); +int _gnutls_generate_master( GNUTLS_STATE state) { + if (state->gnutls_internals.resumed==RESUME_FALSE) + return generate_normal_master(state); + return 0; +} -static int generate_master( GNUTLS_STATE state) { +static int generate_normal_master( GNUTLS_STATE state) { int premaster_size; #ifdef HARD_DEBUG int i; #endif opaque* premaster, *master; int ret = 0; -char random[64]; +char random[2*TLS_RANDOM_SIZE]; - memmove(random, state->security_parameters.client_random, 32); - memmove(&random[32], state->security_parameters.server_random, 32); + memmove(random, state->security_parameters.client_random, TLS_RANDOM_SIZE); + memmove(&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 - fprintf(stderr, "PREMASTER SECRET: "); - for (i=0;i<premaster_size;i++) fprintf(stderr, "%x",premaster[i]); - fprintf(stderr, "\n"); + fprintf(stderr, "PREMASTER SECRET[%d]: %s\n", premaster_size, _gnutls_bin2hex(premaster, premaster_size)); + fprintf(stderr, "CLIENT RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.client_random,32)); + fprintf(stderr, "SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.server_random,32)); #endif if (_gnutls_version_ssl3(state->connection_state.version) == 0) { master = gnutls_ssl3_generate_random( premaster, premaster_size, - random, 64, 48); + random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE); } else { master = gnutls_PRF( premaster, premaster_size, MASTER_SECRET, strlen(MASTER_SECRET), - random, 64, 48); + random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE); } secure_free(premaster); state->gnutls_key->key.size = 0; state->gnutls_key->key.data = NULL; + if (master==NULL) return GNUTLS_E_MEMORY_ERROR; + #ifdef HARD_DEBUG - fprintf(stderr, "MASTER SECRET: %s\n", _gnutls_bin2hex(master, 48)); + fprintf(stderr, "MASTER SECRET: %s\n", _gnutls_bin2hex(master, TLS_MASTER_SIZE)); #endif - memmove(state->security_parameters.master_secret, master, 48); + memmove(state->security_parameters.master_secret, master, TLS_MASTER_SIZE); secure_free(master); return ret; +} + +static int generate_resumed_master( GNUTLS_STATE state) { +int premaster_size; +#ifdef HARD_DEBUG +int i; +#endif +opaque* premaster, *master; +int ret = 0; +char random[2*TLS_RANDOM_SIZE]; + + memmove(random, state->security_parameters.client_random, TLS_RANDOM_SIZE); + memmove(&random[TLS_RANDOM_SIZE], state->security_parameters.server_random, TLS_RANDOM_SIZE); + + /* generate premaster */ + premaster_size = sizeof(state->security_parameters.master_secret); + premaster = state->security_parameters.master_secret; + +#ifdef HARD_DEBUG + fprintf(stderr, "RESUME...\n"); + fprintf(stderr, "PREMASTER SECRET[%d]: %s\n", premaster_size, _gnutls_bin2hex(premaster, premaster_size)); + fprintf(stderr, "CLIENT RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.client_random,32)); + fprintf(stderr, "SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.server_random,32)); +#endif + + if (_gnutls_version_ssl3(state->connection_state.version) == 0) { + master = + gnutls_ssl3_generate_random( premaster, premaster_size, + random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE); + + } else { + master = + gnutls_PRF( premaster, premaster_size, + MASTER_SECRET, strlen(MASTER_SECRET), + random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE); + } + +#ifdef HARD_DEBUG + fprintf(stderr, "MASTER SECRET: %s\n", _gnutls_bin2hex(master, TLS_MASTER_SIZE)); +#endif + if (master==NULL) return GNUTLS_E_MEMORY_ERROR; + memmove(state->security_parameters.master_secret, master, TLS_MASTER_SIZE); + secure_free(master); + return ret; } /* This is called when we want to receive the key exchange message of the @@ -142,11 +195,6 @@ int _gnutls_send_server_kx_message2(SOCKET cd, GNUTLS_STATE state) return ret; } - ret = generate_master( state); - if (ret<0) { - gnutls_assert(); - return ret; - } } return data_size; } @@ -187,12 +235,6 @@ int _gnutls_send_client_kx_message(SOCKET cd, GNUTLS_STATE state) return ret; } - ret = generate_master( state); - if (ret<0) { - gnutls_assert(); - return ret; - } - return ret; } @@ -326,11 +368,6 @@ int _gnutls_recv_server_kx_message2(SOCKET cd, GNUTLS_STATE state) if (ret < 0) return ret; - ret = generate_master( state); - if (ret<0) { - gnutls_assert(); - return ret; - } } return ret; } @@ -368,11 +405,6 @@ int _gnutls_recv_client_kx_message(SOCKET cd, GNUTLS_STATE state) if (ret < 0) return ret; - ret = generate_master( state); - if (ret<0) { - gnutls_assert(); - return ret; - } } return ret; diff --git a/lib/gnutls_kx.h b/lib/gnutls_kx.h index 6408832a35..68ab4a3b9e 100644 --- a/lib/gnutls_kx.h +++ b/lib/gnutls_kx.h @@ -28,3 +28,4 @@ int _gnutls_recv_client_kx_message(int cd, GNUTLS_STATE state); int _gnutls_recv_client_kx_message0(int cd, GNUTLS_STATE state); int _gnutls_send_client_certificate_verify(int cd, GNUTLS_STATE state); int _gnutls_send_certificate(int cd, GNUTLS_STATE state); +int _gnutls_generate_master( GNUTLS_STATE state); diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index cea9ce1e25..91e0b02d89 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -34,6 +34,7 @@ #include "gnutls_auth_int.h" #include "gnutls_num.h" #include "gnutls_record.h" + #ifdef HAVE_ERRNO_H # include <errno.h> #endif @@ -189,6 +190,7 @@ int gnutls_deinit(GNUTLS_STATE state) GNUTLS_FREE(state->gnutls_internals.db_name); + memset( state, 0, sizeof(GNUTLS_STATE_INT)); GNUTLS_FREE(state); return 0; } @@ -356,25 +358,33 @@ int _gnutls_set_keys(GNUTLS_STATE state) int hash_size; int IV_size; int key_size; - + int block_size; + hash_size = state->security_parameters.hash_size; IV_size = state->security_parameters.IV_size; key_size = state->security_parameters.key_material_length; memmove(random, state->security_parameters.server_random, TLS_RANDOM_SIZE); - memmove(&random[TLS_RANDOM_SIZE], state->security_parameters.client_random, 32); + memmove(&random[TLS_RANDOM_SIZE], state->security_parameters.client_random, TLS_RANDOM_SIZE); + + block_size = 2 * hash_size + 2 * key_size + 2 * IV_size; if (_gnutls_version_ssl3(state->connection_state.version) == 0) { /* SSL 3 */ - key_block = gnutls_ssl3_generate_random( state->security_parameters.master_secret, 48, random, 64, - 2 * hash_size + 2 * key_size + 2 * IV_size); + key_block = gnutls_ssl3_generate_random( state->security_parameters.master_secret, TLS_MASTER_SIZE, random, 2*TLS_RANDOM_SIZE, + block_size); } else { /* TLS 1.0 */ key_block = - gnutls_PRF( state->security_parameters.master_secret, 48, - keyexp, strlen(keyexp), random, 64, 2 * hash_size + 2 * key_size + 2 * IV_size); + gnutls_PRF( state->security_parameters.master_secret, TLS_MASTER_SIZE, + keyexp, strlen(keyexp), random, 2*TLS_RANDOM_SIZE, + block_size); } if (key_block==NULL) return GNUTLS_E_MEMORY_ERROR; +#ifdef HARD_DEBUG + fprintf(stderr, "KEY BLOCK[%d]: %s\n",block_size, _gnutls_bin2hex(key_block, block_size)); +#endif + if (hash_size>0) { state->cipher_specs.client_write_mac_secret = secure_malloc(hash_size); if (state->cipher_specs.client_write_mac_secret==NULL) @@ -451,6 +461,27 @@ int gnutls_bye(SOCKET cd, GNUTLS_STATE state) return ret; } +/** + * gnutls_bye_nowait - This function terminates the current TLS/SSL connection. + * @cd: is a connection descriptor. + * @state: is a &GNUTLS_STATE structure. + * + * Terminates the current TLS/SSL connection. The connection should + * have been initiated using gnutls_handshake() or similar function. + * This function does not wait for the other peer to close the TLS + * connection. + **/ +int gnutls_bye_nowait(SOCKET cd, GNUTLS_STATE state) +{ + int ret; + + ret = _gnutls_send_alert(cd, state, GNUTLS_WARNING, GNUTLS_CLOSE_NOTIFY); + + state->gnutls_internals.valid_connection = VALID_FALSE; + + return ret; +} + int gnutls_close_nowait(SOCKET cd, GNUTLS_STATE state) { int ret; @@ -496,7 +527,7 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, const v headers[1]=_gnutls_version_get_major(state->connection_state.version); headers[2]=_gnutls_version_get_minor(state->connection_state.version); -#ifdef HARD_DEBUG +#ifdef RECORD_DEBUG fprintf(stderr, "Record: Sending Packet[%d] %s(%d) with length: %d\n", (int) uint64touint32(&state->connection_state.write_sequence_number), _gnutls_packet2str(type), type, sizeofdata); #endif @@ -523,7 +554,7 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, const v gnutls_assert(); return GNUTLS_E_UNABLE_SEND_DATA; } -#ifdef HARD_DEBUG +#ifdef RECORD_DEBUG fprintf(stderr, "Record: Sended Packet[%d] %s(%d) with length: %d\n", (int) uint64touint32(&state->connection_state.write_sequence_number), _gnutls_packet2str(type), type, cipher_size); #endif @@ -592,7 +623,7 @@ ssize_t _gnutls_send_change_cipher_spec(SOCKET cd, GNUTLS_STATE state) headers[2] = _gnutls_version_get_minor(state->connection_state.version); #ifdef HANDSHAKE_DEBUG - fprintf(stderr, "ChangeCipherSpec was sent\n"); + fprintf(stderr, "Record: ChangeCipherSpec was sent\n"); #endif WRITEuint16( 1, &headers[3]); @@ -722,7 +753,7 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, char *d } -#ifdef HARD_DEBUG +#ifdef RECORD_DEBUG fprintf(stderr, "Record: Expected Packet[%d] %s(%d) with length: %d\n", (int) uint64touint32(&state->connection_state.read_sequence_number), _gnutls_packet2str(type), type, sizeofdata); fprintf(stderr, "Record: Received Packet[%d] %s(%d) with length: %d\n", @@ -795,7 +826,7 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, char *d } if (type == GNUTLS_CHANGE_CIPHER_SPEC && recv_type == GNUTLS_CHANGE_CIPHER_SPEC) { -#ifdef HARD_DEBUG +#ifdef RECORD_DEBUG fprintf(stderr, "Record: ChangeCipherSpec Packet was received\n"); #endif gnutls_free(ciphertext); @@ -826,7 +857,7 @@ ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, char *d return tmplen; } -#ifdef HARD_DEBUG +#ifdef RECORD_DEBUG fprintf(stderr, "Record: Decrypted Packet[%d] %s(%d) with length: %d\n", (int) uint64touint32(&state->connection_state.read_sequence_number), _gnutls_packet2str(recv_type), recv_type, tmplen); #endif diff --git a/lib/gnutls_session.c b/lib/gnutls_session.c index 548e0dadc3..58db045728 100644 --- a/lib/gnutls_session.c +++ b/lib/gnutls_session.c @@ -86,7 +86,7 @@ int gnutls_get_current_session_id( GNUTLS_STATE state, void* session, int *sessi * * Sets all session parameters - in order to support resuming * session must be the one returned by gnutls_get_current_session(); - * This function should be called before gnutls_handshake_begin() or gnutls_handshake(). + * This function should be called before gnutls_handshake(). * Keep in mind that session resuming is advisory. The server may * choose not to resume the session, thus a full handshake will be * performed. diff --git a/lib/gnutls_v2_compat.c b/lib/gnutls_v2_compat.c index 7192d3d60e..f441baee8c 100644 --- a/lib/gnutls_v2_compat.c +++ b/lib/gnutls_v2_compat.c @@ -207,9 +207,6 @@ int _gnutls_read_client_hello_v2(GNUTLS_STATE state, opaque * data, DECR_LEN(len, challenge); memset( random, 0, TLS_RANDOM_SIZE); - /* Well, I think that this is not what TLS 1.0 defines, - * but with this, we are compatible with netscape browser! - */ memcpy( &random[TLS_RANDOM_SIZE-challenge], &data[pos], challenge); _gnutls_set_client_random( state, random); diff --git a/src/serv.c b/src/serv.c index 7225a31b3b..24091ac960 100644 --- a/src/serv.c +++ b/src/serv.c @@ -138,6 +138,15 @@ void print_info(GNUTLS_STATE state) const SRP_AUTH_INFO *srp_info; const ANON_AUTH_INFO *dh_info; char *tmp; + unsigned char sesid[32]; + int sesid_size, i; + + /* print session_id specific data */ + gnutls_get_current_session_id( state, sesid, &sesid_size); + printf("\n- Session ID: "); + for(i=0;i<sesid_size;i++) + printf("%.2X", sesid[i]); + printf("\n"); /* print srp specific data */ if (gnutls_get_current_kx(state) == GNUTLS_KX_SRP) { @@ -177,13 +186,24 @@ void print_info(GNUTLS_STATE state) } +/* Creates html with the current state information. + */ #define tmp2 &http_buffer[strlen(http_buffer)] void peer_print_info(int cd, GNUTLS_STATE state) { const SRP_AUTH_INFO *srp_info; const ANON_AUTH_INFO *dh_info; char *tmp; + unsigned char sesid[32]; + int sesid_size, i; + /* print session_id */ + gnutls_get_current_session_id( state, sesid, &sesid_size); + sprintf(tmp2, "\n<p>Session ID: <i>"); + for(i=0;i<sesid_size;i++) + sprintf(tmp2, "%.2X", sesid[i]); + sprintf(tmp2, "</i></p>\n"); + /* print srp specific data */ if (gnutls_get_current_kx(state) == GNUTLS_KX_SRP) { srp_info = gnutls_get_auth_info(state); @@ -231,23 +251,29 @@ void peer_print_info(int cd, GNUTLS_STATE state) return; } +/* actually something like readline. + * if rnl!=1 then reads an http request in the form REQ\n\n + */ int read_request(int cd, GNUTLS_STATE state, char *data, int data_size, int rnl) { - /* rnl is the requested new lines. Eg. return if 3 newlines - * were given - */ int n, rc, nl = 0; - char c, *ptr; + char c, *ptr, p1=0, p2=0; ptr = data; for (n = 1; n < data_size; n++) { if ((rc = gnutls_read(cd, state, &c, 1)) == 1) { + *ptr++ = c; - if (c == '\n') { + if (c == '\n' && rnl==1) break; + + if (c=='\n' && p1=='\r' && p2=='\n') { nl++; - if (nl == rnl) + if (nl == 1) break; } + p2 = p1; + p1 = c; + } else if (rc == 0) { if (n == 1) return 0; @@ -257,6 +283,7 @@ int read_request(int cd, GNUTLS_STATE state, char *data, int data_size, int rnl) return rc; } } +fprintf(stderr, "\n"); *ptr = 0; return n; } @@ -384,7 +411,7 @@ int main(int argc, char **argv) } } printf("\n"); - gnutls_bye(sd, state); + gnutls_bye_nowait(sd, state); close(sd); gnutls_deinit(state); } |