From: Nikos Mavrogiannopoulos Date: Fri, 17 Mar 2000 21:41:15 +0000 (+0000) Subject: Added the client hello handshake message. X-Git-Tag: gnutls0-0-4~108 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b2a9e127bd0c3a33fbf003cdfe37a4c8e5ce9b66;p=thirdparty%2Fgnutls.git Added the client hello handshake message. --- diff --git a/src/Makefile.am b/src/Makefile.am index 9b0d80a993..98edf34bac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ include_HEADERS = gnutls.h -EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h gnutls_cipher.h gnutls_buffers.h gnutls_errors.h gnutls_int.h +EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h gnutls_cipher.h gnutls_buffers.h gnutls_errors.h gnutls_int.h gnutls_handshake.h lib_LTLIBRARIES = libgnutls.la -libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c gnutls_cipher.c gnutls_buffers.c +libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c gnutls_cipher.c gnutls_buffers.c gnutls_handshake.c libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) bin_PROGRAMS = test test_SOURCES = test.c diff --git a/src/defines.h b/src/defines.h index 917bc4f1a9..546aaed186 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1,7 +1,5 @@ #include - - #ifdef STDC_HEADERS # include # include diff --git a/src/gnutls.c b/src/gnutls.c index c2ac1069e1..a1dd22c557 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -6,8 +6,6 @@ #include "gnutls_plaintext.h" #include "gnutls_cipher.h" #include "gnutls_buffers.h" -#include -#include #include int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end) @@ -32,6 +30,7 @@ int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end) (*state)->cipher_specs.client_write_key = NULL; (*state)->gnutls_internals.buffer = NULL; + (*state)->gnutls_internals.resumable = RESUME_TRUE; } int gnutls_deinit(GNUTLS_STATE * state) @@ -242,14 +241,17 @@ int gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in if (write( cd, &gcipher->type, sizeof(ContentType)) != sizeof(ContentType)) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } if (write( cd, &gcipher->version.major, 1) != 1) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } if (write( cd, &gcipher->version.minor, 1) != 1) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } #ifdef WORDS_BIGENDIAN @@ -259,11 +261,13 @@ int gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in #endif if (write( cd, &length, sizeof(uint16)) != sizeof(uint16)) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } if (write( cd, gcipher->fragment, gcipher->length) != gcipher->length) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } state->connection_state.write_sequence_number++; @@ -301,22 +305,27 @@ int gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in #endif if (write( cd, &gcipher->type, sizeof(ContentType)) != sizeof(ContentType)) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } if (write( cd, &gcipher->version.major, 1) != 1) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } if (write( cd, &gcipher->version.minor, 1) != 1) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } if (write( cd, &length, sizeof(uint16)) != sizeof(uint16)) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } if (write( cd, gcipher->fragment, gcipher->length) != gcipher->length) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNABLE_SEND_DATA; } state->connection_state.write_sequence_number++; @@ -347,21 +356,31 @@ int gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in if (read( cd, &gcipher.type, sizeof(ContentType)) != sizeof(ContentType)) { _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_INTERNAL_ERROR); state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - if (read( cd, &gcipher.version, sizeof(ProtocolVersion)) != sizeof(ProtocolVersion)) { + if (read( cd, &gcipher.version.major, 1) != 1) { _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_INTERNAL_ERROR); state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + if (read( cd, &gcipher.version.minor, 1) != 1) { + _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_INTERNAL_ERROR); + state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } if ( gcipher.version.major != GNUTLS_VERSION_MAJOR || gcipher.version.minor != GNUTLS_VERSION_MINOR) { _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_PROTOCOL_VERSION); + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; } if (read( cd, &gcipher.length, sizeof(uint16)) != sizeof(uint16)) { _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_INTERNAL_ERROR); state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } #ifndef WORDS_BIGENDIAN @@ -370,6 +389,7 @@ int gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in if ( gcipher.length > 18432) { /* 2^14+2048 */ _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_RECORD_OVERFLOW); state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } gcipher.fragment = gnutls_malloc(gcipher.length); @@ -379,17 +399,19 @@ int gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in gnutls_free(gcipher.fragment); _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_INTERNAL_ERROR); state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } if (ret = _gnutls_TLSCiphertext2TLSCompressed( state, &gcomp, &gcipher) < 0){ gnutls_free(gcipher.fragment); - if (ret=GNUTLS_E_MAC_FAILED) { + if (ret == GNUTLS_E_MAC_FAILED) { _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_BAD_RECORD_MAC); } else { _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_DECRYPTION_FAILED); } state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return ret; } gnutls_free(gcipher.fragment); @@ -397,6 +419,7 @@ int gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in if (ret = _gnutls_TLSCompressed2TLSPlaintext( state, >xt, gcomp) < 0){ _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_DECOMPRESSION_FAILURE); state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return ret; } _gnutls_freeTLSCompressed(gcomp); @@ -404,6 +427,7 @@ int gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in if (ret = _gnutls_TLSPlaintext2text( &tmpdata, gtxt) < 0){ _gnutls_send_alert( cd, state, GNUTLS_FATAL, GNUTLS_INTERNAL_ERROR); state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return ret; } tmplen = gtxt->length; @@ -423,10 +447,20 @@ int gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, in } else { if ( ((Alert*)tmpdata)->level == GNUTLS_FATAL) { state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; return GNUTLS_E_ALERT_RECEIVED; } } break; + case GNUTLS_CHANGE_CIPHER_SPEC: + if ( ((ChangeCipherSpecType)tmpdata) == GNUTLS_TYPE_CHANGE_CIPHER_SPEC && tmplen == 1) { + _gnutls_connection_state_init(state); + } else { + state->gnutls_internals.valid_connection=VALID_FALSE; + state->gnutls_internals.resumable = RESUME_FALSE; + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + break; } } diff --git a/src/gnutls_handshake.c b/src/gnutls_handshake.c new file mode 100644 index 0000000000..9c4fcc3ca9 --- /dev/null +++ b/src/gnutls_handshake.c @@ -0,0 +1,134 @@ +#include +#include "gnutls_int.h" +#include "gnutls_errors.h" +#include "debug.h" +#include "gnutls_compress.h" +#include "gnutls_plaintext.h" +#include "gnutls_cipher.h" +#include "gnutls_buffers.h" + +#define SUPPORTED_CIPHERSUITES 1 +int _gnutls_supported_ciphersuites(GNUTLS_CipherSuite **ciphers) { + + int i; + + *ciphers = gnutls_malloc( SUPPORTED_CIPHERSUITES * sizeof(GNUTLS_CipherSuite)); + + for (i=0;isecurity_parameters.entity == GNUTLS_CLIENT) { + + data[pos++] = GNUTLS_VERSION_MAJOR; + data[pos++] = GNUTLS_VERSION_MINOR; +#ifdef WORDS_BIGENDIAN + cur_time = time(NULL); +#else + cur_time = byteswap32(time(NULL)); +#endif + datalen = sizeof(uint32) + session_id_len + 28; + data = gnutls_malloc ( datalen); + + memmove( &data[pos], &cur_time, sizeof(uint32)); + pos += sizeof(uint32); + memmove( &data[pos], rand, 28); + pos+=28; + + if (session_id_len>0) memmove( &data[pos], SessionID, session_id_len); + pos+=session_id_len; + + x = _gnutls_supported_ciphersuites( &cipher_suites); + + for (i=0;i> (64 - (uint16)(n)))) #define rotr64(x,n) (((x) >> ((uint16)(n))) | ((x) << (64 - (uint16)(n)))) #define rotl32(x,n) (((x) << ((uint16)(n))) | ((x) >> (32 - (uint16)(n)))) @@ -22,7 +26,7 @@ typedef unsigned char opaque; -enum ChangeCipherSpecType { GNUTLS_TYPE_CHANGE_CIPHER_SPEC }; +enum ChangeCipherSpecType { GNUTLS_TYPE_CHANGE_CIPHER_SPEC=1 }; enum AlertLevel { GNUTLS_WARNING, GNUTLS_FATAL }; enum AlertDescription { GNUTLS_CLOSE_NOTIFY, GNUTLS_UNEXPECTED_MESSAGE=10, GNUTLS_BAD_RECORD_MAC=20, GNUTLS_DECRYPTION_FAILED, GNUTLS_RECORD_OVERFLOW, GNUTLS_DECOMPRESSION_FAILURE=30, @@ -57,8 +61,10 @@ enum MACAlgorithm { MAC_NULL, MAC_MD5, MAC_SHA }; enum CompressionMethod { COMPRESSION_NULL }; enum ValidSession { VALID_TRUE, VALID_FALSE }; +enum ResumableSession { RESUME_TRUE, RESUME_FALSE }; typedef enum ValidSession ValidSession; +typedef enum ResumableSession ResumableSession; typedef enum ConnectionEnd ConnectionEnd; typedef enum BulkCipherAlgorithm BulkCipherAlgorithm; typedef enum CipherType CipherType; @@ -104,6 +110,7 @@ typedef struct { typedef struct { char* buffer; uint32 bufferSize; + ResumableSession resumable; ValidSession valid_connection; AlertDescription last_alert; } GNUTLS_INTERNALS; @@ -170,4 +177,48 @@ typedef struct { } GNUTLSCiphertext; +/* Handshake protocol */ + +enum HandshakeType { GNUTLS_HELLO_REQUEST, GNUTLS_CLIENT_HELLO, GNUTLS_SERVER_HELLO, + GNUTLS_CERTIFICATE=11, GNUTLS_SERVER_KEY_EXCHANGE, + GNUTLS_CERTIFICATE_REQUEST, GNUTLS_SERVER_HELLO_DONE, + GNUTLS_CERTIFICATE_VERIFY, GNUTLS_CLIENT_KEY_EXCHANGE, + GNUTLS_FINISHED=20 }; + +typedef enum HandshakeType HandshakeType; + +typedef struct { + HandshakeType msg_type; + uint24 length; + void* body; +} GNUTLS_Handshake; + +typedef struct { + uint32 gmt_unix_time; + opaque random_bytes[28]; +} GNUTLS_random; + +typedef struct { + uint8 CipherSuite[2]; +} GNUTLS_CipherSuite; + +typedef struct { + ProtocolVersion client_version; + GNUTLS_random random; + opaque* session_id; + GNUTLS_CipherSuite* cipher_suites; + CompressionMethod* compression_methods; +} GNUTLS_ClientHello; + +typedef struct { + ProtocolVersion server_version; + GNUTLS_random random; + opaque* session_id; + GNUTLS_CipherSuite cipher_suite; + CompressionMethod compression_method; +} GNUTLS_ServerHello; + +#define GNUTLS_DH_anon_WITH_3DES_EDE_CBC_SHA { 0x00, 0x1B } + +/* functions */ int _gnutls_send_alert( int cd, GNUTLS_STATE state, AlertLevel level, AlertDescription desc);