#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)
(*state)->cipher_specs.client_write_key = NULL;
(*state)->gnutls_internals.buffer = NULL;
+ (*state)->gnutls_internals.resumable = RESUME_TRUE;
}
int gnutls_deinit(GNUTLS_STATE * state)
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
#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++;
#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++;
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
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);
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);
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);
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;
} 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;
}
}
--- /dev/null
+#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;
+}
+
#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))))
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,
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;
typedef struct {
char* buffer;
uint32 bufferSize;
+ ResumableSession resumable;
ValidSession valid_connection;
AlertDescription last_alert;
} GNUTLS_INTERNALS;
} 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);