diff options
-rw-r--r-- | lib/gnutls.h.in.in | 13 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 28 | ||||
-rw-r--r-- | lib/gnutls_algorithms.h | 1 | ||||
-rw-r--r-- | lib/gnutls_cipher_int.c | 1 | ||||
-rw-r--r-- | lib/gnutls_constate.c | 173 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 22 | ||||
-rw-r--r-- | lib/gnutls_int.h | 6 | ||||
-rw-r--r-- | lib/gnutls_state.c | 18 | ||||
-rw-r--r-- | src/cli.c | 3 |
9 files changed, 198 insertions, 67 deletions
diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in index 9b9ede21c4..7e50ae2745 100644 --- a/lib/gnutls.h.in.in +++ b/lib/gnutls.h.in.in @@ -35,9 +35,16 @@ extern "C" { #define GNUTLS_CIPHER_AES_256_CBC GNUTLS_CIPHER_RIJNDAEL_256_CBC #define GNUTLS_CIPHER_RIJNDAEL_CBC GNUTLS_CIPHER_RIJNDAEL_128_CBC -typedef enum GNUTLS_BulkCipherAlgorithm { GNUTLS_CIPHER_NULL=1, GNUTLS_CIPHER_ARCFOUR, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_RIJNDAEL_128_CBC, GNUTLS_CIPHER_TWOFISH_128_CBC, GNUTLS_CIPHER_RIJNDAEL_256_CBC } GNUTLS_BulkCipherAlgorithm; - -typedef enum GNUTLS_KXAlgorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP } GNUTLS_KXAlgorithm; +typedef enum GNUTLS_BulkCipherAlgorithm { GNUTLS_CIPHER_NULL=1, + GNUTLS_CIPHER_ARCFOUR, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_RIJNDAEL_128_CBC, + GNUTLS_CIPHER_TWOFISH_128_CBC, GNUTLS_CIPHER_RIJNDAEL_256_CBC, + GNUTLS_CIPHER_ARCFOUR_EXPORT +} GNUTLS_BulkCipherAlgorithm; + +typedef enum GNUTLS_KXAlgorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, + GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP, + GNUTLS_KX_RSA_EXPORT +} GNUTLS_KXAlgorithm; typedef enum GNUTLS_CredType { GNUTLS_CRD_CERTIFICATE=1, GNUTLS_CRD_ANON, GNUTLS_CRD_SRP } GNUTLS_CredType; diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index 3e99f76301..50c3191ae8 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -80,6 +80,7 @@ struct gnutls_cipher_entry { size_t keysize; CipherType block; size_t iv; + int export_flag; /* 0 non export */ }; typedef struct gnutls_cipher_entry gnutls_cipher_entry; @@ -89,12 +90,13 @@ typedef struct gnutls_cipher_entry gnutls_cipher_entry; * protecting communications" by Hugo Krawczyk - CRYPTO 2001 */ static const gnutls_cipher_entry algorithms[] = { - {"3DES 168 CBC", GNUTLS_CIPHER_3DES_CBC, 8, 24, CIPHER_BLOCK, 8 }, - {"RIJNDAEL 128 CBC", GNUTLS_CIPHER_RIJNDAEL_128_CBC, 16, 16, CIPHER_BLOCK, 16 }, - {"RIJNDAEL 256 CBC", GNUTLS_CIPHER_RIJNDAEL_256_CBC, 16, 32, CIPHER_BLOCK, 16 }, - {"TWOFISH 128 CBC", GNUTLS_CIPHER_TWOFISH_128_CBC, 16, 16, CIPHER_BLOCK, 16 }, - {"ARCFOUR 128", GNUTLS_CIPHER_ARCFOUR, 1, 16, CIPHER_STREAM, 0 }, - {"NULL", GNUTLS_CIPHER_NULL, 1, 0, CIPHER_STREAM, 0 }, + {"3DES 168 CBC", GNUTLS_CIPHER_3DES_CBC, 8, 24, CIPHER_BLOCK, 8, 0 }, + {"RIJNDAEL 128 CBC", GNUTLS_CIPHER_RIJNDAEL_128_CBC, 16, 16, CIPHER_BLOCK, 16, 0 }, + {"RIJNDAEL 256 CBC", GNUTLS_CIPHER_RIJNDAEL_256_CBC, 16, 32, CIPHER_BLOCK, 16, 0 }, + {"TWOFISH 128 CBC", GNUTLS_CIPHER_TWOFISH_128_CBC, 16, 16, CIPHER_BLOCK, 16, 0 }, + {"ARCFOUR 128", GNUTLS_CIPHER_ARCFOUR, 1, 16, CIPHER_STREAM, 0, 0 }, + {"ARCFOUR 40", GNUTLS_CIPHER_ARCFOUR_EXPORT, 1, 5, CIPHER_STREAM, 0, 1 }, + {"NULL", GNUTLS_CIPHER_NULL, 1, 0, CIPHER_STREAM, 0, 0 }, {0} }; @@ -241,6 +243,8 @@ typedef struct { #define GNUTLS_RSA_ARCFOUR_MD5 { 0x00, 0x04 } #define GNUTLS_RSA_3DES_EDE_CBC_SHA { 0x00, 0x0A } +#define GNUTLS_RSA_ARCFOUR_EXPORT_MD5 { 0x00, 0x03 } + /* draft-ietf-tls-ciphersuite-05: */ #define GNUTLS_RSA_RIJNDAEL_128_CBC_SHA { 0x00, 0x2F } @@ -359,6 +363,10 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = { GNUTLS_CIPHER_NULL, GNUTLS_KX_RSA, GNUTLS_MAC_MD5, GNUTLS_SSL3), + GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_RSA_ARCFOUR_EXPORT_MD5, + GNUTLS_CIPHER_ARCFOUR_EXPORT, + GNUTLS_KX_RSA, GNUTLS_MAC_MD5, GNUTLS_SSL3), + GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_RSA_ARCFOUR_SHA, GNUTLS_CIPHER_ARCFOUR, GNUTLS_KX_RSA, GNUTLS_MAC_SHA, GNUTLS_SSL3), @@ -579,6 +587,14 @@ int _gnutls_cipher_get_iv_size(BulkCipherAlgorithm algorithm) } +int _gnutls_cipher_get_export_flag(BulkCipherAlgorithm algorithm) +{ /* In bytes */ + size_t ret = 0; + GNUTLS_ALG_LOOP(ret = p->export_flag); + return ret; + +} + /** * gnutls_cipher_get_name - Returns a string with the name of the specified cipher algorithm * @algorithm: is an encryption algorithm diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h index 4a5ae8e623..3996c447ae 100644 --- a/lib/gnutls_algorithms.h +++ b/lib/gnutls_algorithms.h @@ -55,6 +55,7 @@ int _gnutls_cipher_is_block(BulkCipherAlgorithm algorithm); int _gnutls_cipher_is_ok(BulkCipherAlgorithm algorithm); size_t gnutls_cipher_get_key_size(BulkCipherAlgorithm algorithm); int _gnutls_cipher_get_iv_size(BulkCipherAlgorithm algorithm); +int _gnutls_cipher_get_export_flag(BulkCipherAlgorithm algorithm); const char *gnutls_cipher_get_name(BulkCipherAlgorithm algorithm); /* functions for key exchange */ diff --git a/lib/gnutls_cipher_int.c b/lib/gnutls_cipher_int.c index bbbfefd93f..65e1aec03c 100644 --- a/lib/gnutls_cipher_int.c +++ b/lib/gnutls_cipher_int.c @@ -61,6 +61,7 @@ GNUTLS_CIPHER_HANDLE ret; #endif break; case GNUTLS_CIPHER_ARCFOUR: + case GNUTLS_CIPHER_ARCFOUR_EXPORT: #ifdef USE_MCRYPT ret = mcrypt_module_open( "arcfour", NULL, "stream", NULL); #else diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c index 85d7257c9b..5811dc0cea 100644 --- a/lib/gnutls_constate.c +++ b/lib/gnutls_constate.c @@ -32,15 +32,28 @@ #include <gnutls_datum.h> #include <gnutls_state.h> +static const char keyexp[] = "key expansion"; +static const int keyexp_length = sizeof(keyexp) - 1; + +static const char ivblock[] = "IV block"; +static const int ivblock_length = sizeof(ivblock) - 1; + +static const char cliwrite[] = "client write key"; +static const int cliwrite_length = sizeof(cliwrite) - 1; + +static const char servwrite[] = "server write key"; +static const int servwrite_length = sizeof(servwrite) - 1; + +#define EXPORT_FINAL_KEY_SIZE 16 + /* This function is to be called after handshake, when master_secret, * client_random and server_random have been initialized. * This function creates the keys and stores them into pending state. * (state->cipher_specs) */ -int _gnutls_set_keys(GNUTLS_STATE state, int hash_size, int IV_size, int key_size) +int _gnutls_set_keys(GNUTLS_STATE state, int hash_size, int IV_size, int key_size, int export_flag) { opaque *key_block; - char keyexp[] = "key expansion"; char random[2*TLS_RANDOM_SIZE]; int pos, ret; int block_size; @@ -52,9 +65,10 @@ int _gnutls_set_keys(GNUTLS_STATE state, int hash_size, int IV_size, int key_siz state->cipher_specs.generated_keys=0; return 0; } - - block_size = 2 * hash_size + 2 * key_size + 2 * IV_size; + block_size = 2 * hash_size + 2 * key_size; + if (export_flag == 0) block_size += 2 * IV_size; + key_block = gnutls_secure_malloc( block_size); if (key_block==NULL) { gnutls_assert(); @@ -70,7 +84,7 @@ int _gnutls_set_keys(GNUTLS_STATE state, int hash_size, int IV_size, int key_siz } else { /* TLS 1.0 */ ret = _gnutls_PRF( state->security_parameters.master_secret, TLS_MASTER_SIZE, - keyexp, strlen(keyexp), random, 2*TLS_RANDOM_SIZE, + keyexp, keyexp_length, random, 2*TLS_RANDOM_SIZE, block_size, key_block); } @@ -98,19 +112,113 @@ int _gnutls_set_keys(GNUTLS_STATE state, int hash_size, int IV_size, int key_siz } if (key_size > 0) { - if (gnutls_sset_datum( &state->cipher_specs.client_write_key, &key_block[pos], key_size) < 0 ) { + opaque * client_write_key, *server_write_key; + int client_write_key_size, server_write_key_size; + int free_keys = 0; + + if (export_flag==0) { + client_write_key = &key_block[pos]; + client_write_key_size = key_size; + + pos += key_size; + + server_write_key = &key_block[pos]; + server_write_key_size = key_size; + + pos += key_size; + + } else { /* export */ + free_keys = 1; + + client_write_key = gnutls_secure_malloc( EXPORT_FINAL_KEY_SIZE); + if (client_write_key == NULL) { + gnutls_assert(); + gnutls_free(key_block); + return GNUTLS_E_MEMORY_ERROR; + } + + server_write_key = gnutls_secure_malloc( EXPORT_FINAL_KEY_SIZE); + if (server_write_key == NULL) { + gnutls_assert(); + gnutls_free(key_block); + gnutls_free( client_write_key); + return GNUTLS_E_MEMORY_ERROR; + } + + /* generate the final keys */ + + /* SSL3: check */ + if ( state->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ + ret = _gnutls_ssl3_generate_random( &key_block[pos], key_size, + random, 2*TLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, + client_write_key); + } else { /* TLS 1.0 */ + ret = + _gnutls_PRF( &key_block[pos], key_size, + cliwrite, cliwrite_length, random, 2*TLS_RANDOM_SIZE, + EXPORT_FINAL_KEY_SIZE, client_write_key); + } + + if (ret<0) { + gnutls_assert(); + gnutls_free(key_block); + gnutls_free( server_write_key); + gnutls_free( client_write_key); + return ret; + } + + client_write_key_size = EXPORT_FINAL_KEY_SIZE; + pos += key_size; + + if ( state->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ + ret = _gnutls_ssl3_generate_random( &key_block[pos], key_size, + random, 2*TLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, + server_write_key); + } else { /* TLS 1.0 */ + ret = + _gnutls_PRF( &key_block[pos], key_size, + servwrite, servwrite_length, random, 2*TLS_RANDOM_SIZE, + EXPORT_FINAL_KEY_SIZE, server_write_key); + } + + if (ret<0) { + gnutls_assert(); + gnutls_free(key_block); + gnutls_free( server_write_key); + gnutls_free( client_write_key); + return ret; + } + + server_write_key_size = EXPORT_FINAL_KEY_SIZE; + pos += key_size; + + } + if (gnutls_sset_datum( &state->cipher_specs.client_write_key, + client_write_key, client_write_key_size) < 0 ) { gnutls_free(key_block); + gnutls_free( server_write_key); + gnutls_free( client_write_key); return GNUTLS_E_MEMORY_ERROR; } - pos+=key_size; - if (gnutls_sset_datum( &state->cipher_specs.server_write_key, &key_block[pos], key_size) < 0 ) { + if (gnutls_sset_datum( &state->cipher_specs.server_write_key, + server_write_key, server_write_key_size) < 0 ) { gnutls_free(key_block); + gnutls_free( server_write_key); + gnutls_free( client_write_key); return GNUTLS_E_MEMORY_ERROR; } - pos+=key_size; + + if (free_keys != 0) { + gnutls_free( server_write_key); + gnutls_free( client_write_key); + } } - if (IV_size > 0) { + + + /* IV generation in export and non export ciphers. + */ + if (IV_size > 0 && export_flag == 0) { if (gnutls_sset_datum( &state->cipher_specs.client_write_IV, &key_block[pos], IV_size) < 0 ) { gnutls_free(key_block); return GNUTLS_E_MEMORY_ERROR; @@ -122,6 +230,41 @@ int _gnutls_set_keys(GNUTLS_STATE state, int hash_size, int IV_size, int key_siz return GNUTLS_E_MEMORY_ERROR; } pos+=IV_size; + } else if (IV_size > 0 && export_flag != 0) { + opaque *iv_block = gnutls_alloca( IV_size * 2); + + if (iv_block == NULL) { + gnutls_assert(); + gnutls_free(key_block); + return GNUTLS_E_MEMORY_ERROR; + } + + /* SSL3: check */ + if ( state->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ + ret = _gnutls_ssl3_generate_random( "", 0, random, 2*TLS_RANDOM_SIZE, + IV_size*2, iv_block); + } else { /* TLS 1.0 */ + ret = + _gnutls_PRF( "", 0, + ivblock, ivblock_length, random, 2*TLS_RANDOM_SIZE, + IV_size*2, iv_block); + } + + if (ret<0) { + gnutls_assert(); + gnutls_free(key_block); + return ret; + } + + if (gnutls_sset_datum( &state->cipher_specs.client_write_IV, iv_block, IV_size) < 0 ) { + gnutls_free(key_block); + return GNUTLS_E_MEMORY_ERROR; + } + + if (gnutls_sset_datum( &state->cipher_specs.server_write_IV, &iv_block[IV_size], IV_size) < 0 ) { + gnutls_free(key_block); + return GNUTLS_E_MEMORY_ERROR; + } } gnutls_free(key_block); @@ -135,7 +278,7 @@ int _gnutls_set_read_keys(GNUTLS_STATE state) { int hash_size; int IV_size; - int key_size; + int key_size, export_flag; BulkCipherAlgorithm algo; MACAlgorithm mac_algo; @@ -145,15 +288,16 @@ int _gnutls_set_read_keys(GNUTLS_STATE state) hash_size = _gnutls_mac_get_digest_size( mac_algo); IV_size = _gnutls_cipher_get_iv_size( algo); key_size = gnutls_cipher_get_key_size( algo); + export_flag = _gnutls_cipher_get_export_flag( algo); - return _gnutls_set_keys( state, hash_size, IV_size, key_size); + return _gnutls_set_keys( state, hash_size, IV_size, key_size, export_flag); } int _gnutls_set_write_keys(GNUTLS_STATE state) { int hash_size; int IV_size; - int key_size; + int key_size, export_flag; BulkCipherAlgorithm algo; MACAlgorithm mac_algo; @@ -163,8 +307,9 @@ int _gnutls_set_write_keys(GNUTLS_STATE state) hash_size = _gnutls_mac_get_digest_size( mac_algo); IV_size = _gnutls_cipher_get_iv_size( algo); key_size = gnutls_cipher_get_key_size( algo); + export_flag = _gnutls_cipher_get_export_flag( algo); - return _gnutls_set_keys( state, hash_size, IV_size, key_size); + return _gnutls_set_keys( state, hash_size, IV_size, key_size, export_flag); } #define CPY_COMMON dst->entity = src->entity; \ diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index b461483a2b..f07a7cb93c 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -1063,8 +1063,6 @@ int _gnutls_recv_handshake(GNUTLS_STATE state, uint8 ** data, return ret; } -const static opaque EXPORT_CIPHERSUITE[2] = { 0x00, 0x03 }; - /* This function checks if the given cipher suite is supported, and sets it * to the state; */ @@ -1076,12 +1074,6 @@ static int _gnutls_client_set_ciphersuite(GNUTLS_STATE state, uint16 x; int i, err; - if (state->gnutls_internals.exportable_detection_hack != 0) - if ( memcmp( suite, EXPORT_CIPHERSUITE, 2)==0) { - gnutls_assert(); - return GNUTLS_E_EXPORT_CIPHER_SUITE; - } - z = 1; x = _gnutls_supported_ciphersuites(state, &cipher_suites); for (i = 0; i < x; i++) { @@ -1351,11 +1343,6 @@ static int _gnutls_copy_ciphersuites(GNUTLS_STATE state, cipher_num = ret; - /* for the EXPORT DETECTION */ - if ( state->gnutls_internals.exportable_detection_hack != 0) { - cipher_num += 1; /* add 1 for the export cipher suite */ - } - cipher_num *= sizeof(uint16); /* in order to get bytes */ datalen = pos = 0; @@ -1368,9 +1355,6 @@ static int _gnutls_copy_ciphersuites(GNUTLS_STATE state, return GNUTLS_E_MEMORY_ERROR; } - - /* add 2 for the export cipher suite - */ _gnutls_write_uint16(cipher_num, *ret_data); pos += 2; @@ -1379,12 +1363,6 @@ static int _gnutls_copy_ciphersuites(GNUTLS_STATE state, pos += 2; } - /* for the EXPORT DETECTION */ - if ( state->gnutls_internals.exportable_detection_hack != 0) { - memcpy( &(*ret_data)[pos], EXPORT_CIPHERSUITE, 2); - pos += 2; - } - gnutls_free(cipher_suites); return datalen; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index a746db703f..f330f3280e 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -156,7 +156,8 @@ typedef enum ConnectionEnd { GNUTLS_SERVER=1, GNUTLS_CLIENT typedef enum BulkCipherAlgorithm { GNUTLS_CIPHER_NULL=1, GNUTLS_CIPHER_ARCFOUR, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_RIJNDAEL_128_CBC, - GNUTLS_CIPHER_TWOFISH_128_CBC, GNUTLS_CIPHER_RIJNDAEL_256_CBC + GNUTLS_CIPHER_TWOFISH_128_CBC, GNUTLS_CIPHER_RIJNDAEL_256_CBC, + GNUTLS_CIPHER_ARCFOUR_EXPORT } BulkCipherAlgorithm; #define GNUTLS_BulkCipherAlgorithm BulkCipherAlgorithm @@ -164,7 +165,8 @@ typedef enum Extensions { GNUTLS_EXTENSION_MAX_RECORD_SIZE=1, GNUTLS_EXTENSION_S } Extensions; typedef enum KXAlgorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, - GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP + GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP, + GNUTLS_KX_RSA_EXPORT } KXAlgorithm; #define GNUTLS_KXAlgorithm KXAlgorithm diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index fa31816649..60d2382485 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -468,24 +468,6 @@ void gnutls_record_set_cbc_protection(GNUTLS_STATE state, int prot) } /** - * gnutls_handshake_set_exportable_detection - Used to enable the detection of server's export cipher suites - * @state: is a &GNUTLS_STATE structure. - * @det: is an integer (0 or 1) - * - * The function will allow clients to detect if a server only - * supports exportable ciphersuites. In that case an error code - * of GNUTLS_E_EXPORT_CIPHER_SUITE is returned. - * - * This check will be enabled if det != 0, and disabled otherwise - * (the default behaviour). - * - **/ -void gnutls_handshake_set_exportable_detection(GNUTLS_STATE state, int det) -{ - state->gnutls_internals.exportable_detection_hack = det; -} - -/** * gnutls_handshake_set_private_extensions - Used to enable the private cipher suites * @state: is a &GNUTLS_STATE structure. * @allow: is an integer (0 or 1) @@ -77,7 +77,7 @@ int kx_priority[16] = GNUTLS_KX_ANON_DH, 0 }; int cipher_priority[16] = - { GNUTLS_CIPHER_RIJNDAEL_128_CBC, GNUTLS_CIPHER_3DES_CBC, + { GNUTLS_CIPHER_ARCFOUR_EXPORT, GNUTLS_CIPHER_RIJNDAEL_128_CBC, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0 }; int comp_priority[16] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 }; @@ -235,7 +235,6 @@ int main(int argc, char **argv) /* allow the use of private ciphersuites. */ gnutls_handshake_set_private_extensions( state, 1); - gnutls_handshake_set_exportable_detection( state, 1); if (i == 1) { gnutls_session_set_data(state, session, session_size); |