diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2000-11-15 18:18:22 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2000-11-15 18:18:22 +0000 |
commit | aaf36ea4324c46b6034182d1aa8ab9d8f2142005 (patch) | |
tree | 9382a1ecf04765c98eeed0f5038b9d551ebbf83c | |
parent | ce3d63f2ea71c90e7134273ad51a2a33c6871b38 (diff) | |
download | gnutls-aaf36ea4324c46b6034182d1aa8ab9d8f2142005.tar.gz |
several cleanups in order to support ssl3
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | lib/gnutls.c | 304 | ||||
-rw-r--r-- | lib/gnutls.h | 4 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 25 | ||||
-rw-r--r-- | lib/gnutls_algorithms.h | 2 | ||||
-rw-r--r-- | lib/gnutls_cipher.c | 90 | ||||
-rw-r--r-- | lib/gnutls_cipher.h | 1 | ||||
-rw-r--r-- | lib/gnutls_cipher_int.c | 2 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 2 | ||||
-rw-r--r-- | lib/gnutls_errors.h | 2 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 16 | ||||
-rw-r--r-- | lib/gnutls_int.h | 7 |
12 files changed, 227 insertions, 232 deletions
diff --git a/configure.in b/configure.in index 9da7f0115f..9b122f348f 100644 --- a/configure.in +++ b/configure.in @@ -11,7 +11,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os") GNUTLS_MAJOR_VERSION=0 GNUTLS_MINOR_VERSION=0 -GNUTLS_MICRO_VERSION=3 +GNUTLS_MICRO_VERSION=4 GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION @@ -27,7 +27,7 @@ AM_PATH_GCRYPT(1.1.1a,, AC_MSG_ERROR([[ *** *** libgcrypt was not found. You may want to get it from -*** ftp://ftp.gnupg.org/gcrypt/devel/ +*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/gnupg/ *** ]])) diff --git a/lib/gnutls.c b/lib/gnutls.c index df95fd1a67..d370b59df4 100644 --- a/lib/gnutls.c +++ b/lib/gnutls.c @@ -30,19 +30,6 @@ #include "gnutls_hash_int.h" #include "gnutls_cipher_int.h" -/* This function should check if we support the version of the peer. - * However now we only support version 3.1 - */ -int _gnutls_valid_version(GNUTLS_STATE state, int major, int minor) -{ -GNUTLS_Version ver = {0, major, minor}; - - if (_gnutls_version_is_supported(ver) > 0 ) { - return 0; /* supported */ - } - return 1; -} - GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state) { GNUTLS_Version ver; ver.local = state->connection_state.version.local; @@ -337,15 +324,17 @@ int gnutls_close_nowait(int cd, GNUTLS_STATE state) * send (if called by the user the Content is specific) * It is intended to transfer data, under the current state. */ -ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char *data, size_t sizeofdata) +#define MAX_ENC_LEN 16384 +ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, void *_data, size_t sizeofdata) { - GNUTLSPlaintext *gtxt; - GNUTLSCompressed *gcomp; - GNUTLSCiphertext *gcipher; - int iterations, i, err; + uint8 *cipher; + int i, err, cipher_size; + int ret = 0; + int iterations; uint16 length; - int ret = 0, Size; - + int Size; + uint8 headers[5]; + uint8 *data=_data; if (sizeofdata == 0) return 0; @@ -353,148 +342,71 @@ ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char *data return GNUTLS_E_INVALID_SESSION; } - if (sizeofdata < 16384) { + if (sizeofdata < MAX_ENC_LEN) { iterations = 1; Size = sizeofdata; } else { - iterations = sizeofdata / 16384; - Size = 16384; + iterations = sizeofdata / MAX_ENC_LEN; + Size = MAX_ENC_LEN; } + headers[0]=type; + headers[1]=state->connection_state.version.major; + headers[2]=state->connection_state.version.minor; + for (i = 0; i < iterations; i++) { - err = _gnutls_text2TLSPlaintext(state, type, >xt, &data[i * Size], Size); - if (err < 0) { - /*gnutls_perror(err); */ - return err; - } - - err = _gnutls_TLSPlaintext2TLSCompressed(state, &gcomp, gtxt); - if (err < 0) { - /*gnutls_perror(err); */ - return err; - } - - _gnutls_freeTLSPlaintext(gtxt); - - err = _gnutls_TLSCompressed2TLSCiphertext(state, &gcipher, gcomp); - if (err < 0) { - /*gnutls_perror(err); */ - return err; - } - - _gnutls_freeTLSCompressed(gcomp); - - if (Write(cd, &gcipher->type, 1) != 1) { - state->gnutls_internals.valid_connection = VALID_FALSE; - state->gnutls_internals.resumable = RESUME_FALSE; - gnutls_assert(); - 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; - gnutls_assert(); - 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; - gnutls_assert(); - return GNUTLS_E_UNABLE_SEND_DATA; - } -#ifdef HARD_DEBUG - fprintf(stderr, "Send Packet[%d] %s(%d) with length: %d\n", - (int) state->connection_state.write_sequence_number, _gnutls_packet2str(gcipher->type), gcipher->type, gcipher->length); -#endif + cipher_size = _gnutls_encrypt( state, &data[i*Size], Size, &cipher, type); + if (cipher_size<=0) return cipher_size; #ifdef WORDS_BIGENDIAN - length = gcipher->length; + length = cipher_size; #else - length = byteswap16(gcipher->length); + length = byteswap16(cipher_size); #endif - if (Write(cd, &length, sizeof(uint16)) != sizeof(uint16)) { + memmove( &headers[3], &length, sizeof(uint16)); + if (Write(cd, headers, sizeof(headers)) != sizeof(headers)) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNABLE_SEND_DATA; } - - if (Write(cd, gcipher->fragment, gcipher->length) != gcipher->length) { + if (Write(cd, cipher, cipher_size) != cipher_size) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNABLE_SEND_DATA; } state->connection_state.write_sequence_number++; - ret += Size; - - _gnutls_freeTLSCiphertext(gcipher); } - /* rest data */ + /* rest data */ if (iterations > 1) { - Size = sizeofdata % 16384; - err = _gnutls_text2TLSPlaintext(state, type, >xt, &data[ret], Size); - if (err < 0) { - /*gnutls_perror(err); */ - return err; - } - - err = _gnutls_TLSPlaintext2TLSCompressed(state, &gcomp, gtxt); - if (err < 0) { - /*gnutls_perror(err); */ - return err; - } - - _gnutls_freeTLSPlaintext(gtxt); - - err = _gnutls_TLSCompressed2TLSCiphertext(state, &gcipher, gcomp); - if (err < 0) { - /*gnutls_perror(err); */ - return err; - } - _gnutls_freeTLSCompressed(gcomp); + Size = sizeofdata % MAX_ENC_LEN; + cipher_size = _gnutls_encrypt( state, &data[i*Size], Size, &cipher, type); + if (cipher_size<=0) return cipher_size; #ifdef WORDS_BIGENDIAN - length = gcipher->length; + length = cipher_size; #else - length = byteswap16(gcipher->length); + length = byteswap16(cipher_size); #endif - if (Write(cd, &gcipher->type, 1) != 1) { + memmove( &headers[3], &length, sizeof(uint16)); + if (Write(cd, headers, sizeof(headers)) != sizeof(headers)) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); 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; - gnutls_assert(); - 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; - gnutls_assert(); - 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; - gnutls_assert(); - return GNUTLS_E_UNABLE_SEND_DATA; - } - if (Write(cd, gcipher->fragment, gcipher->length) != gcipher->length) { + if (Write(cd, cipher, cipher_size) != cipher_size) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNABLE_SEND_DATA; } state->connection_state.write_sequence_number++; - ret += Size; - - _gnutls_freeTLSCiphertext(gcipher); } + ret += sizeofdata; + + gnutls_free(cipher); + return ret; } @@ -507,31 +419,16 @@ ssize_t _gnutls_send_change_cipher_spec(int cd, GNUTLS_STATE state) int ret = 0, Size; uint8 type=GNUTLS_CHANGE_CIPHER_SPEC; char data[1] = { GNUTLS_TYPE_CHANGE_CIPHER_SPEC }; + uint8 headers[5]; if (state->gnutls_internals.valid_connection == VALID_FALSE) { return GNUTLS_E_INVALID_SESSION; } - if (Write(cd, &type, 1) != 1) { - state->gnutls_internals.valid_connection = VALID_FALSE; - state->gnutls_internals.resumable = RESUME_FALSE; - gnutls_assert(); - return GNUTLS_E_UNABLE_SEND_DATA; - } - - if (Write(cd, &state->connection_state.version.major, 1) != 1) { - state->gnutls_internals.valid_connection = VALID_FALSE; - state->gnutls_internals.resumable = RESUME_FALSE; - gnutls_assert(); - return GNUTLS_E_UNABLE_SEND_DATA; - } + headers[0] = type; + headers[1] = state->connection_state.version.major; + headers[2] = state->connection_state.version.minor; - if (Write(cd, &state->connection_state.version.minor, 1) != 1) { - state->gnutls_internals.valid_connection = VALID_FALSE; - state->gnutls_internals.resumable = RESUME_FALSE; - gnutls_assert(); - return GNUTLS_E_UNABLE_SEND_DATA; - } #ifdef HARD_DEBUG fprintf(stderr, "Send Change Cipher Spec\n"); #endif @@ -541,7 +438,9 @@ ssize_t _gnutls_send_change_cipher_spec(int cd, GNUTLS_STATE state) #else length = byteswap16((uint16)1); #endif - if (Write(cd, &length, sizeof(uint16)) != sizeof(uint16)) { + memmove( &headers[3], &length, sizeof(uint16)); + + if (Write(cd, headers, 5) != 5) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); @@ -564,13 +463,15 @@ ssize_t _gnutls_send_change_cipher_spec(int cd, GNUTLS_STATE state) * send (if called by the user the Content is specific) * It is intended to receive data, under the current state. */ +#define MAX_RECV_SIZE 18432 /* 2^14+2048 */ ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char *data, size_t sizeofdata) { - GNUTLSPlaintext *gtxt; - GNUTLSCompressed *gcomp; - GNUTLSCiphertext gcipher; uint8 *tmpdata; int tmplen; + GNUTLS_Version version; + uint8 recv_type; + uint16 length; + uint8 *ciphertext; int ret = 0; /* If we have enough data in the cache do not bother receiving @@ -585,62 +486,61 @@ ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char *data return GNUTLS_E_INVALID_SESSION; } - if (Read(cd, &gcipher.type, 1) != 1) { + if ( Read(cd, &recv_type, 1) != 1) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - /* If we expect a change cipher spec then just return - no decryption */ - - if (Read(cd, &gcipher.version.major, 1) != 1) { + version.local = 0; /* TLS/SSL 3.0 */ + + if (Read(cd, &version.major, 1) != 1) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - if (Read(cd, &gcipher.version.minor, 1) != 1) { + if (Read(cd, &version.minor, 1) != 1) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - if (_gnutls_valid_version(state, gcipher.version.major, gcipher.version.minor) != 0) { + if (_gnutls_version_is_supported(state, version) == 0) { #ifdef DEBUG - fprintf(stderr, "INVALID VERSION PACKET: %d.%d\n", gcipher.version.major, gcipher.version.minor); + fprintf(stderr, "INVALID VERSION PACKET: %d.%d\n", version.major, version.minor); #endif _gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_PROTOCOL_VERSION); state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; } else { - GNUTLS_Version ver = { 0, gcipher.version.major, gcipher.version.minor }; - gnutls_set_current_version(state, ver); + gnutls_set_current_version(state, version); } - if (Read(cd, &gcipher.length, 2) != 2) { + if (Read(cd, &length, 2) != 2) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } #ifndef WORDS_BIGENDIAN - gcipher.length = byteswap16(gcipher.length); + length = byteswap16(length); #endif #ifdef HARD_DEBUG fprintf(stderr, "Expected Packet[%d] %s(%d) with length: %d\n", (int) state->connection_state.read_sequence_number, _gnutls_packet2str(type), type, sizeofdata); fprintf(stderr, "Received Packet[%d] %s(%d) with length: %d\n", - (int) state->connection_state.read_sequence_number, _gnutls_packet2str(gcipher.type), gcipher.type, gcipher.length); + (int) state->connection_state.read_sequence_number, _gnutls_packet2str(recv_type), recv_type, length); #endif - if (gcipher.length > 18432) { /* 2^14+2048 */ + if (length > MAX_RECV_SIZE) { #ifdef DEBUG - fprintf(stderr, "FATAL ERROR: Received packet with length: %d\n", gcipher.length); + fprintf(stderr, "FATAL ERROR: Received packet with length: %d\n", length); #endif _gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_RECORD_OVERFLOW); state->gnutls_internals.valid_connection = VALID_FALSE; @@ -648,72 +548,62 @@ ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char *data gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - gcipher.fragment = gnutls_malloc(gcipher.length); - /* read ciphertext */ + ciphertext = gnutls_malloc(length); - ret = Read(cd, gcipher.fragment, gcipher.length); + /* read ciphertext */ + ret = Read(cd, ciphertext, length); - if (ret != gcipher.length) { + if (ret != length) { #ifdef DEBUG - fprintf(stderr, "Received packet with length: %d\nExpected %d\n", ret, gcipher.length); + fprintf(stderr, "Received packet with length: %d\nExpected %d\n", ret, length); #endif - gnutls_free(gcipher.fragment); + gnutls_free(ciphertext); state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - - if (type == GNUTLS_CHANGE_CIPHER_SPEC && gcipher.type == GNUTLS_CHANGE_CIPHER_SPEC) { + + if (type == GNUTLS_CHANGE_CIPHER_SPEC && recv_type == GNUTLS_CHANGE_CIPHER_SPEC) { #ifdef HARD_DEBUG fprintf(stderr, "Received Change Cipher Spec Packet\n"); #endif - if (gcipher.length!=1) return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + if (length!=1) { + gnutls_assert(); + gnutls_free(ciphertext); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } return 0; } - - ret = _gnutls_TLSCiphertext2TLSCompressed(state, &gcomp, &gcipher); - if (ret < 0) { - gnutls_free(gcipher.fragment); - 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); + tmplen = _gnutls_decrypt( state, ciphertext, length, &tmpdata, type); + if (tmplen < 0) { + switch (tmplen) { + case GNUTLS_E_MAC_FAILED: + _gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_BAD_RECORD_MAC); + break; + case GNUTLS_E_DECRYPTION_FAILED: + _gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_DECRYPTION_FAILED); + break; + case GNUTLS_E_DECOMPRESSION_FAILED: + _gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_DECOMPRESSION_FAILURE); + break; } state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; - return ret; - } - gnutls_free(gcipher.fragment); - - ret = _gnutls_TLSCompressed2TLSPlaintext(state, >xt, gcomp); - if (ret < 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); - - ret = _gnutls_TLSPlaintext2text((void *) &tmpdata, gtxt); - if (ret < 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; + gnutls_assert(); + gnutls_free(ciphertext); + return tmplen; } - tmplen = gtxt->length; - - _gnutls_freeTLSPlaintext(gtxt); + gnutls_free(ciphertext); - if (gcipher.type == type && (type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE)) { + if ( (recv_type == type) && (type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE)) { gnutls_insertDataBuffer(type, state, (void *) tmpdata, tmplen); } else { - switch (gcipher.type) { + switch (recv_type) { case GNUTLS_ALERT: #ifdef HARD_DEBUG fprintf(stderr, "Alert[%d|%d] - %s - was received\n", tmpdata[0], tmpdata[1], _gnutls_alert2str((int)tmpdata[1])); @@ -758,18 +648,16 @@ ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char *data - /* Insert Application data to buffer */ - if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE) && gcipher.type == type) { + /* Get Application data from buffer */ + if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE) && (recv_type == type)) { ret = gnutls_getDataFromBuffer(type, state, data, sizeofdata); gnutls_free(tmpdata); } else { - if (gcipher.type != type) { + if (recv_type != type) { gnutls_assert(); return GNUTLS_E_RECEIVED_BAD_MESSAGE; } - /* this is an error because we have messages of fixed - * length */ - + gnutls_assert(); /* this shouldn't have happened */ ret = GNUTLS_E_RECEIVED_BAD_MESSAGE; } diff --git a/lib/gnutls.h b/lib/gnutls.h index fba8ac3c5c..cf712f8822 100644 --- a/lib/gnutls.h +++ b/lib/gnutls.h @@ -20,7 +20,7 @@ enum ContentType { GNUTLS_APPLICATION_DATA=23 }; typedef enum ContentType ContentType; -enum BulkCipherAlgorithm { GNUTLS_NULL, GNUTLS_ARCFOUR=1, GNUTLS_DES=3, GNUTLS_3DES = 4, GNUTLS_AES }; +enum BulkCipherAlgorithm { GNUTLS_NULL, GNUTLS_ARCFOUR=1, GNUTLS_DES=3, GNUTLS_3DES = 4, GNUTLS_RIJNDAEL }; typedef enum BulkCipherAlgorithm BulkCipherAlgorithm; enum KXAlgorithm { GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_DH_DSS, GNUTLS_KX_DH_RSA, GNUTLS_KX_ANON_DH }; typedef enum KXAlgorithm KXAlgorithm; @@ -45,7 +45,7 @@ typedef struct GNUTLS_STATE_INT* GNUTLS_STATE; int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end); int gnutls_deinit(GNUTLS_STATE * state); -ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char* data, size_t sizeofdata); +ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, void* data, size_t sizeofdata); ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, size_t sizeofdata); int gnutls_close(int cd, GNUTLS_STATE state); int gnutls_handshake(int cd, GNUTLS_STATE state); diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index 3d797d678f..3b676ca625 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -63,7 +63,7 @@ typedef struct gnutls_cipher_entry gnutls_cipher_entry; static gnutls_cipher_entry algorithms[] = { GNUTLS_CIPHER_ENTRY(GNUTLS_3DES, 8, 24, 1, 8, -1), - GNUTLS_CIPHER_ENTRY(GNUTLS_AES, 16, 16, 1, 16, -1), + GNUTLS_CIPHER_ENTRY(GNUTLS_RIJNDAEL, 16, 16, 1, 16, -1), #ifdef USE_MCRYPT GNUTLS_CIPHER_ENTRY(GNUTLS_DES, 8, 8, 1, 8, -1), GNUTLS_CIPHER_ENTRY(GNUTLS_ARCFOUR, 1, 16, 0, 0, -1), @@ -173,11 +173,11 @@ typedef struct { #define GNUTLS_DHE_DSS_WITH_DES_CBC_SHA { 0x00, 0x12 } #define GNUTLS_DHE_RSA_WITH_DES_CBC_SHA { 0x00, 0x15 } -#define GNUTLS_RSA_WITH_AES_128_CBC_SHA { 0xFF, 0x2F } -#define GNUTLS_DH_DSS_WITH_AES_128_CBC_SHA { 0xFF, 0x30 } -#define GNUTLS_DH_RSA_WITH_AES_128_CBC_SHA { 0xFF, 0x31 } -#define GNUTLS_DHE_DSS_WITH_AES_128_CBC_SHA { 0xFF, 0x32 } -#define GNUTLS_DHE_RSA_WITH_AES_128_CBC_SHA { 0xFF, 0x33 } +#define GNUTLS_RSA_WITH_RIJNDAEL_128_CBC_SHA { 0x00, 0x2F } +#define GNUTLS_DH_DSS_WITH_RIJNDAEL_128_CBC_SHA { 0x00, 0x30 } +#define GNUTLS_DH_RSA_WITH_RIJNDAEL_128_CBC_SHA { 0x00, 0x31 } +#define GNUTLS_DHE_DSS_WITH_RIJNDAEL_128_CBC_SHA { 0x00, 0x32 } +#define GNUTLS_DHE_RSA_WITH_RIJNDAEL_128_CBC_SHA { 0x00, 0x33 } static gnutls_cipher_suite_entry cs_algorithms[] = { @@ -195,11 +195,11 @@ static gnutls_cipher_suite_entry cs_algorithms[] = { GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_RSA_WITH_ARCFOUR_MD5, GNUTLS_ARCFOUR, GNUTLS_KX_RSA, GNUTLS_MAC_MD5), GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_RSA_WITH_3DES_EDE_CBC_SHA, GNUTLS_3DES, GNUTLS_KX_RSA, GNUTLS_MAC_SHA), GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_RSA_WITH_DES_CBC_SHA, GNUTLS_DES, GNUTLS_KX_RSA, GNUTLS_MAC_SHA), - GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_RSA_WITH_AES_128_CBC_SHA, GNUTLS_AES, GNUTLS_KX_RSA, GNUTLS_MAC_SHA), - GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_DH_DSS_WITH_AES_128_CBC_SHA, GNUTLS_AES, GNUTLS_KX_DH_DSS, GNUTLS_MAC_SHA), - GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_DH_RSA_WITH_AES_128_CBC_SHA, GNUTLS_AES, GNUTLS_KX_DH_RSA, GNUTLS_MAC_SHA), - GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_DHE_DSS_WITH_AES_128_CBC_SHA, GNUTLS_AES, GNUTLS_KX_DHE_DSS, GNUTLS_MAC_SHA), - GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_DHE_RSA_WITH_AES_128_CBC_SHA, GNUTLS_AES, GNUTLS_KX_DHE_RSA, GNUTLS_MAC_SHA), + GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_RSA_WITH_RIJNDAEL_128_CBC_SHA, GNUTLS_RIJNDAEL, GNUTLS_KX_RSA, GNUTLS_MAC_SHA), + GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_DH_DSS_WITH_RIJNDAEL_128_CBC_SHA, GNUTLS_RIJNDAEL, GNUTLS_KX_DH_DSS, GNUTLS_MAC_SHA), + GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_DH_RSA_WITH_RIJNDAEL_128_CBC_SHA, GNUTLS_RIJNDAEL, GNUTLS_KX_DH_RSA, GNUTLS_MAC_SHA), + GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_DHE_DSS_WITH_RIJNDAEL_128_CBC_SHA, GNUTLS_RIJNDAEL, GNUTLS_KX_DHE_DSS, GNUTLS_MAC_SHA), + GNUTLS_CIPHER_SUITE_ENTRY( GNUTLS_DHE_RSA_WITH_RIJNDAEL_128_CBC_SHA, GNUTLS_RIJNDAEL, GNUTLS_KX_DHE_RSA, GNUTLS_MAC_SHA), {0} }; @@ -521,9 +521,10 @@ int _gnutls_version_cmp(GNUTLS_Version ver1, GNUTLS_Version ver2) { return 0; } -int _gnutls_version_is_supported(const GNUTLS_Version version) +int _gnutls_version_is_supported(GNUTLS_STATE state, const GNUTLS_Version version) { size_t ret = 0; + /* FIXME: make it to read it from the state */ GNUTLS_VERSION_ALG_LOOP(ret = p->supported); return ret; } diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h index 96f80303a3..2b3a19b78d 100644 --- a/lib/gnutls_algorithms.h +++ b/lib/gnutls_algorithms.h @@ -1,5 +1,5 @@ /* functions for version */ -int _gnutls_version_is_supported(const GNUTLS_Version version); +int _gnutls_version_is_supported(GNUTLS_STATE state, const GNUTLS_Version version); /* functions for macs */ int _gnutls_mac_get_digest_size(MACAlgorithm algorithm); diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c index e0257a58ca..3c8d8cb413 100644 --- a/lib/gnutls_cipher.c +++ b/lib/gnutls_cipher.c @@ -27,6 +27,96 @@ #include "gnutls_hash_int.h" #include "gnutls_cipher_int.h" +int _gnutls_encrypt( GNUTLS_STATE state, char* data, size_t data_size, uint8** ciphertext, ContentType type) +{ + GNUTLSPlaintext *gtxt; + GNUTLSCompressed *gcomp; + GNUTLSCiphertext *gcipher; + int total_length=0, err, i; + + if (data_size == 0) + return 0; + + err = _gnutls_text2TLSPlaintext(state, type, >xt, data, data_size); + if (err < 0) { + gnutls_assert(); + return err; + } + + err = _gnutls_TLSPlaintext2TLSCompressed(state, &gcomp, gtxt); + if (err < 0) { + gnutls_assert(); + return err; + } + + _gnutls_freeTLSPlaintext(gtxt); + + err = _gnutls_TLSCompressed2TLSCiphertext(state, &gcipher, gcomp); + if (err < 0) { + gnutls_assert(); + return err; + } + + _gnutls_freeTLSCompressed(gcomp); + + *ciphertext = gnutls_malloc( gcipher->length); + if ( *ciphertext == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + memmove( (*ciphertext), gcipher->fragment, gcipher->length); + + total_length += gcipher->length; + _gnutls_freeTLSCiphertext(gcipher); + + return total_length; +} + +int _gnutls_decrypt( GNUTLS_STATE state, char* ciphertext, size_t ciphertext_size, uint8** data, ContentType type) +{ + GNUTLSPlaintext *gtxt; + GNUTLSCompressed *gcomp; + GNUTLSCiphertext gcipher; + int iterations, i; + int err, ret; + int total_length=0; + + if (ciphertext_size == 0) + return 0; + + gcipher.type = type; + gcipher.length = ciphertext_size; + gcipher.version.major = state->connection_state.version.major; + gcipher.version.minor = state->connection_state.version.minor; + gcipher.fragment = gnutls_malloc(ciphertext_size); + memmove( gcipher.fragment, ciphertext, ciphertext_size); + + ret = _gnutls_TLSCiphertext2TLSCompressed(state, &gcomp, &gcipher); + if (ret < 0) { + gnutls_free(gcipher.fragment); + return ret; + } + gnutls_free(gcipher.fragment); + + ret = _gnutls_TLSCompressed2TLSPlaintext(state, >xt, gcomp); + if (ret < 0) { + return ret; + } + + _gnutls_freeTLSCompressed(gcomp); + + ret = _gnutls_TLSPlaintext2text((void *) data, gtxt); + if (ret < 0) { + return ret; + } + ret = gtxt->length; + + _gnutls_freeTLSPlaintext(gtxt); + + return ret; +} + + /* Sets the specified cipher into the pending state */ int _gnutls_set_cipher(GNUTLS_STATE state, BulkCipherAlgorithm algo) { diff --git a/lib/gnutls_cipher.h b/lib/gnutls_cipher.h index 1ba32edab2..b078f365ac 100644 --- a/lib/gnutls_cipher.h +++ b/lib/gnutls_cipher.h @@ -1,3 +1,4 @@ +int _gnutls_encrypt( GNUTLS_STATE state, char* data, size_t data_size, uint8** ciphertext, ContentType type); int _gnutls_TLSCompressed2TLSCiphertext(GNUTLS_STATE state, GNUTLSCiphertext** cipher, diff --git a/lib/gnutls_cipher_int.c b/lib/gnutls_cipher_int.c index 547b9b65ea..38c6be1075 100644 --- a/lib/gnutls_cipher_int.c +++ b/lib/gnutls_cipher_int.c @@ -38,7 +38,7 @@ GNUTLS_CIPHER_HANDLE ret; ret = GNUTLS_CIPHER_FAILED; #endif break; - case GNUTLS_AES: + case GNUTLS_RIJNDAEL: #ifdef USE_MCRYPT ret = mcrypt_module_open( "rijndael-128", NULL, "cbc", NULL); #else diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index 99ce837d82..c7299aedcc 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -58,6 +58,8 @@ static gnutls_error_entry error_algorithms[] = { GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_KX_ALGORITHM, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_MPI_SCAN_FAILED, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_DECRYPTION_FAILED, 1), + GNUTLS_ERROR_ENTRY( GNUTLS_E_DECOMPRESSION_FAILED, 1), + GNUTLS_ERROR_ENTRY( GNUTLS_E_MEMORY_ERROR, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_UNIMPLEMENTED_FEATURE, 1), {0} }; diff --git a/lib/gnutls_errors.h b/lib/gnutls_errors.h index 808da9a72d..c3909ca1be 100644 --- a/lib/gnutls_errors.h +++ b/lib/gnutls_errors.h @@ -24,6 +24,8 @@ #define GNUTLS_E_UNWANTED_ALGORITHM -22 #define GNUTLS_E_MPI_SCAN_FAILED -23 #define GNUTLS_E_DECRYPTION_FAILED -24 +#define GNUTLS_E_MEMORY_ERROR -25 +#define GNUTLS_E_DECOMPRESSION_FAILED -26 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -50 diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index c12f6d440a..1ec032fa42 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -593,6 +593,7 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen, CompressionMethod compression_method, *compression_methods; int i, ret=0; uint16 x, sizeOfSuites; + GNUTLS_Version version; if (state->security_parameters.entity == GNUTLS_CLIENT) { if (datalen < 38) { @@ -603,8 +604,14 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen, #ifdef DEBUG fprintf(stderr, "Server's version: %d.%d\n", data[pos], data[pos+1]); #endif - if ( _gnutls_valid_version( state, data[pos], data[pos+1]) != 0) { + version.local = 0; /* TLS 1.0 / SSL 3.0 */ + version.major = data[pos]; + version.minor = data[pos+1]; + if ( _gnutls_version_is_supported( state, version) == 0) { + gnutls_assert(); return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; + } else { + gnutls_set_current_version(state, version); } pos+=2; @@ -679,9 +686,14 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen, #ifdef DEBUG fprintf(stderr, "Client's version: %d.%d\n", data[pos], data[pos+1]); #endif - if ( _gnutls_valid_version( state, data[pos], data[pos+1]) != 0) { + version.local = 0; /* TLS 1.0 / SSL 3.0 */ + version.major = data[pos]; + version.minor = data[pos+1]; + if ( _gnutls_version_is_supported( state, version) == 0) { gnutls_assert(); return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; + } else { + gnutls_set_current_version(state, version); } pos+=2; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 2b151ff41f..f8166e19ee 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -2,7 +2,7 @@ #define GNUTLS_INT_H -//#define HARD_DEBUG +#define HARD_DEBUG //#define READ_DEBUG //#define WRITE_DEBUG #define DEBUG @@ -82,7 +82,7 @@ typedef struct { /* STATE */ enum ConnectionEnd { GNUTLS_SERVER, GNUTLS_CLIENT }; -enum BulkCipherAlgorithm { GNUTLS_NULL, GNUTLS_ARCFOUR=1, GNUTLS_DES=3, GNUTLS_3DES = 4, GNUTLS_AES }; +enum BulkCipherAlgorithm { GNUTLS_NULL, GNUTLS_ARCFOUR=1, GNUTLS_DES=3, GNUTLS_3DES = 4, GNUTLS_RIJNDAEL }; enum KXAlgorithm { GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_DH_DSS, GNUTLS_KX_DH_RSA, GNUTLS_KX_ANON_DH }; enum KeyExchangeAlgorithm { GNUTLS_RSA, GNUTLS_DIFFIE_HELLMAN }; enum CipherType { CIPHER_STREAM, CIPHER_BLOCK }; @@ -291,11 +291,10 @@ int gnutls_close(int cd, GNUTLS_STATE state); svoid *gnutls_PRF( opaque * secret, int secret_size, uint8 * label, int label_size, opaque * seed, int seed_size, int total_bytes); -int _gnutls_valid_version( GNUTLS_STATE state, int major, int minor); void gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version); GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state); int _gnutls_set_keys(GNUTLS_STATE state); -ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char* data, size_t sizeofdata); +ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, void* data, size_t sizeofdata); ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, size_t sizeofdata); int _gnutls_send_change_cipher_spec(int cd, GNUTLS_STATE state); int _gnutls_version_cmp(GNUTLS_Version ver1, GNUTLS_Version ver2); |