]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added the client hello handshake message.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 17 Mar 2000 21:41:15 +0000 (21:41 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 17 Mar 2000 21:41:15 +0000 (21:41 +0000)
src/Makefile.am
src/defines.h
src/gnutls.c
src/gnutls_handshake.c [new file with mode: 0644]
src/gnutls_handshake.h [new file with mode: 0644]
src/gnutls_int.h

index 9b0d80a99321530284586a99e787430ec3df3dc6..98edf34bac0dae32fcb22399bd4fc221f65bae04 100644 (file)
@@ -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
index 917bc4f1a93b6a30a8431999756ec68f0d24a3f7..546aaed1866152e60ce98c49800d514b9176d729 100644 (file)
@@ -1,7 +1,5 @@
 #include <config.h>
 
-
-
 #ifdef STDC_HEADERS
 # include <string.h>
 # include <stdlib.h>
index c2ac1069e19f6d1d84e9a940d886597b8540eab0..a1dd22c55759f2f34e827ca7f32df635930620b3 100644 (file)
@@ -6,8 +6,6 @@
 #include "gnutls_plaintext.h"
 #include "gnutls_cipher.h"
 #include "gnutls_buffers.h"
-#include <stdio.h>
-#include <stdlib.h>
 #include <mhash.h>
 
 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, &gtxt, 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 (file)
index 0000000..9c4fcc3
--- /dev/null
@@ -0,0 +1,134 @@
+#include <defines.h>
+#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;i<SUPPORTED_CIPHERSUITES;i++) {
+               (*ciphers)[i].CipherSuite[0] = 0x00;
+       }
+
+       /* GNUTLS_DH_anon_WITH_3DES_EDE_CBC_SHA */
+//     (*ciphers)[0].CipherSuite[1] = 0x1B;
+
+       /* GNUTLS_NULL_WITH_NULL_NULL */
+       (*ciphers)[0].CipherSuite[1] = 0x0;
+
+       return SUPPORTED_CIPHERSUITES;
+}
+
+
+#define SUPPORTED_COMPRESSION_METHODS 1
+int _gnutls_supported_compression_methods(CompressionMethod **comp) {
+
+       int i;
+
+       *comp = gnutls_malloc( SUPPORTED_COMPRESSION_METHODS * sizeof(CompressionMethod));
+
+/* NULL Compression */
+       (*comp)[0] = COMPRESSION_NULL;
+
+       return SUPPORTED_COMPRESSION_METHODS;
+}
+
+int _gnutls_send_handshake(int cd, GNUTLS_STATE state, void* i_data, uint32 i_datasize, HandshakeType type) {
+       int ret;
+       char *data;
+       uint24 length;
+       uint32 datasize;
+       
+#ifdef WORDS_BIGENDIAN
+       datasize = i_datalen;
+#else 
+       datasize = byteswap32(i_datalen);
+#endif 
+       
+       length.pint[0] = ((uint8*)i_datalen)[1];
+       length.pint[1] = ((uint8*)i_datalen)[2];
+       length.pint[2] = ((uint8*)i_datalen)[3];
+       
+       data = gnutls_malloc( i_datasize + 3 + 1);
+       memmove( &data[pos++], &type, 1);
+       memmove( &data[pos++], &length.pint[0], 1);
+       memmove( &data[pos++], &length.pint[1], 1);
+       memmove( &data[pos++], &length.pint[2], 1);
+       memmove( &data[pos], i_data, i_datalen);
+
+       ret = gnutls_send_int( cd, state, GNUTLS_HANDSHAKE, data, i_datalen);
+       
+       return ret;
+}
+
+
+
+
+int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque* SessionID) {
+       char* rand;
+       char *data=NULL;
+       int session_id_len=0;
+       uint32 cur_time;
+       int pos=0;
+       GNUTLS_CipherSuite* cipher_suites;
+       CompressionMethod* compression_methods;
+       int i,x, datalen, ret;
+       
+       if (SessionID!=NULL) session_id_len=strlen(SessionID);
+       rand=gcry_random_bytes( 28, GCRY_STRONG_RANDOM);
+       
+       if (state->security_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<x;i++) {
+                       datalen += 2;
+                       data = gnutls_realloc( data, datalen);
+                       memmove( &data[pos], &cipher_suites[i], sizeof(uint8)*2);
+                       pos+=2;
+               }
+               x = _gnutls_supported_compression_methods( &compression_methods);
+               for (i=0;i<x;i++) {
+                       datalen += 1;
+                       data = gnutls_realloc( data, datalen);
+                       memmove( &data[pos], &compression_methods[i], 1);
+                       pos++;
+               }
+               ret = _gnutls_send_handshake( cd, state, data, datalen, GNUTLS_CLIENT_HELLO);
+               gnutls_free(data);
+               gcry_free(rand);
+               
+
+       } else {
+       
+       }
+
+       return ret;
+}
+
diff --git a/src/gnutls_handshake.h b/src/gnutls_handshake.h
new file mode 100644 (file)
index 0000000..e69de29
index 1716f2e1f45707fbea54b3a121ddee68dc16a756..aa7b24c6e7371c0626fca47b05f0eecb4ba3f045 100644 (file)
@@ -8,6 +8,10 @@
 #define gnutls_calloc calloc
 #define gnutls_free free
 
+typedef struct {
+       uint8   pint[3];
+} uint24;
+
 #define rotl64(x,n)   (((x) << ((uint16)(n))) | ((x) >> (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);