diff --git a/lib/modules/SSL.pmod/Cipher.pmod b/lib/modules/SSL.pmod/Cipher.pmod index 31572390049c4091492eaf3309adeaf8ac9328d7..cefce284ab939b7f13d55127a1eb76668dc0e801 100644 --- a/lib/modules/SSL.pmod/Cipher.pmod +++ b/lib/modules/SSL.pmod/Cipher.pmod @@ -51,6 +51,10 @@ class CipherSpec { //! The Message Authentication Code to use for the packets. program(MACAlgorithm) mac_algorithm; + //! Indication whether the combination uses strong or weak + //! (aka exportable) crypto. + int is_exportable; + //! The number of bytes in the MAC hashes. int hash_size; @@ -455,6 +459,7 @@ array lookup(int suite, ProtocolVersion|int version) case CIPHER_rc4_40: res->bulk_cipher_algorithm = Nettle.ARCFOUR_State; res->cipher_type = CIPHER_stream; + res->is_exportable = 1; res->key_material = 16; res->iv_size = 0; res->key_bits = 40; @@ -462,6 +467,7 @@ array lookup(int suite, ProtocolVersion|int version) case CIPHER_des40: res->bulk_cipher_algorithm = DES; res->cipher_type = CIPHER_block; + res->is_exportable = 1; res->key_material = 8; res->iv_size = 8; res->key_bits = 40; @@ -469,13 +475,16 @@ array lookup(int suite, ProtocolVersion|int version) case CIPHER_null: res->bulk_cipher_algorithm = 0; res->cipher_type = CIPHER_stream; + res->is_exportable = 1; res->key_material = 0; res->iv_size = 0; res->key_bits = 0; break; +#ifndef WEAK_CRYPTO_40BIT case CIPHER_rc4: res->bulk_cipher_algorithm = Nettle.ARCFOUR_State; res->cipher_type = CIPHER_stream; + res->is_exportable = 0; res->key_material = 16; res->iv_size = 0; res->key_bits = 128; @@ -483,6 +492,7 @@ array lookup(int suite, ProtocolVersion|int version) case CIPHER_des: res->bulk_cipher_algorithm = DES; res->cipher_type = CIPHER_block; + res->is_exportable = 0; res->key_material = 8; res->iv_size = 8; res->key_bits = 56; @@ -490,6 +500,7 @@ array lookup(int suite, ProtocolVersion|int version) case CIPHER_3des: res->bulk_cipher_algorithm = DES3; res->cipher_type = CIPHER_block; + res->is_exportable = 0; res->key_material = 24; res->iv_size = 8; res->key_bits = 168; @@ -497,6 +508,7 @@ array lookup(int suite, ProtocolVersion|int version) case CIPHER_idea: res->bulk_cipher_algorithm = IDEA; res->cipher_type = CIPHER_block; + res->is_exportable = 0; res->key_material = 16; res->iv_size = 8; res->key_bits = 128; @@ -504,6 +516,7 @@ array lookup(int suite, ProtocolVersion|int version) case CIPHER_aes: res->bulk_cipher_algorithm = AES; res->cipher_type = CIPHER_block; + res->is_exportable = 0; res->key_material = 16; res->iv_size = 16; res->key_bits = 128; @@ -511,10 +524,12 @@ array lookup(int suite, ProtocolVersion|int version) case CIPHER_aes256: res->bulk_cipher_algorithm = AES; res->cipher_type = CIPHER_block; + res->is_exportable = 0; res->key_material = 32; res->iv_size = 16; res->key_bits = 256; break; +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ default: return 0; } diff --git a/lib/modules/SSL.pmod/Constants.pmod b/lib/modules/SSL.pmod/Constants.pmod index 1f5cfe30c5a14729c5a3d79fb53a276540dd6493..aaf3202dd6b2f7cd985e836b60e0fe84b0fe6e04 100644 --- a/lib/modules/SSL.pmod/Constants.pmod +++ b/lib/modules/SSL.pmod/Constants.pmod @@ -61,6 +61,7 @@ constant CIPHER_null = 0; constant CIPHER_rc4_40 = 2; constant CIPHER_rc2 = 3; constant CIPHER_des40 = 6; +#ifndef WEAK_CRYPTO_40BIT constant CIPHER_rc4 = 1; constant CIPHER_des = 4; constant CIPHER_3des = 5; @@ -68,6 +69,7 @@ constant CIPHER_fortezza = 7; constant CIPHER_idea = 8; constant CIPHER_aes = 9; constant CIPHER_aes256 = 10; +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ //! Mapping from cipher algorithm to effective key length. constant CIPHER_algorithms = ([ @@ -75,6 +77,7 @@ constant CIPHER_algorithms = ([ CIPHER_rc4_40: 40, CIPHER_rc2: 40, CIPHER_des40: 40, +#ifndef WEAK_CRYPTO_40BIT CIPHER_rc4: 128, CIPHER_des: 56, CIPHER_3des: 168, @@ -82,6 +85,7 @@ constant CIPHER_algorithms = ([ CIPHER_idea: 128, CIPHER_aes: 128, CIPHER_aes256: 256, +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ ]); /* Hash algorithms as per RFC 5246 7.4.1.4.1. */ @@ -205,6 +209,7 @@ constant TLS_krb5_with_rc4_40_sha = 0x0028; constant TLS_krb5_with_des_cbc_40_md5 = 0x0029; constant TLS_krb5_with_rc2_cbc_40_md5 = 0x002a; constant TLS_krb5_with_rc4_40_md5 = 0x002b; +#ifndef WEAK_CRYPTO_40BIT constant SSL_rsa_with_rc4_128_md5 = 0x0004; constant SSL_rsa_with_rc4_128_sha = 0x0005; constant SSL_rsa_with_idea_cbc_sha = 0x0007; @@ -384,6 +389,7 @@ constant TLS_ecdhe_psk_with_aes_256_cbc_sha384 = 0xc038; constant TLS_ecdhe_psk_with_null_sha = 0xc039; constant TLS_ecdhe_psk_with_null_sha256 = 0xc03a; constant TLS_ecdhe_psk_with_null_sha384 = 0xc03b; +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ #if 0 /* Methods for signing any server_key_exchange message (RFC 5246 7.4.1.4.1) */ @@ -402,6 +408,7 @@ constant CIPHER_SUITES = SSL_rsa_export_with_rc4_40_md5 : ({ KE_rsa, CIPHER_rc4_40, HASH_md5 }), SSL_dhe_dss_export_with_des40_cbc_sha : ({ KE_dhe_dss, CIPHER_des40, HASH_sha }), +#ifndef WEAK_CRYPTO_40BIT SSL_rsa_with_rc4_128_sha : ({ KE_rsa, CIPHER_rc4, HASH_sha }), SSL_rsa_with_rc4_128_md5 : ({ KE_rsa, CIPHER_rc4, HASH_md5 }), SSL_rsa_with_idea_cbc_sha : ({ KE_rsa, CIPHER_idea, HASH_sha }), @@ -413,9 +420,11 @@ constant CIPHER_SUITES = TLS_dhe_dss_with_aes_128_cbc_sha : ({ KE_dhe_dss, CIPHER_aes, HASH_sha }), TLS_rsa_with_aes_256_cbc_sha : ({ KE_rsa, CIPHER_aes256, HASH_sha }), TLS_dhe_dss_with_aes_256_cbc_sha : ({ KE_dhe_dss, CIPHER_aes256, HASH_sha }), +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ ]); constant preferred_rsa_suites = ({ +#ifndef WEAK_CRYPTO_40BIT TLS_rsa_with_aes_256_cbc_sha, TLS_rsa_with_aes_128_cbc_sha, // Mandatory in RFC 5246 (TLS 1.2). SSL_rsa_with_idea_cbc_sha, @@ -423,16 +432,19 @@ constant preferred_rsa_suites = ({ SSL_rsa_with_rc4_128_md5, SSL_rsa_with_3des_ede_cbc_sha, // Mandatory in RFC 2246 (TLS 1.0). SSL_rsa_with_des_cbc_sha, +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ SSL_rsa_export_with_rc4_40_md5, SSL_rsa_with_null_sha, SSL_rsa_with_null_md5, }); constant preferred_dhe_dss_suites = ({ +#ifndef WEAK_CRYPTO_40BIT TLS_dhe_dss_with_aes_256_cbc_sha, TLS_dhe_dss_with_aes_128_cbc_sha, SSL_dhe_dss_with_3des_ede_cbc_sha, // Mandatory in RFC 2246 (TLS 1.0). SSL_dhe_dss_with_des_cbc_sha, +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ SSL_dhe_dss_export_with_des40_cbc_sha, }); diff --git a/lib/modules/SSL.pmod/context.pike b/lib/modules/SSL.pmod/context.pike index f61c4ef0e50c7ab9be2e9a61ac5501dc11f6240c..39108f39572d8a7f5862c932fb0dd0a6703757fc 100644 --- a/lib/modules/SSL.pmod/context.pike +++ b/lib/modules/SSL.pmod/context.pike @@ -152,9 +152,15 @@ int verify_certificates = 0; //! Temporary, non-certified, private keys, used with a //! server_key_exchange message. The rules are as follows: //! -//! If the long_rsa is not zero its public part will be sent. If it is -//! zero and short_rsa is set, its public part will be sent instead. -//! If they are both zero, no server_key_exchange message is sent. +//! If the negotiated cipher_suite has the "exportable" property, and +//! short_rsa is not zero, send a server_key_exchange message with the +//! (public part of) the short_rsa key. +//! +//! If the negotiated cipher_suite does not have the exportable +//! property, and long_rsa is not zero, send a server_key_exchange +//! message with the (public part of) the long_rsa key. +//! +//! Otherwise, dont send any server_key_exchange message. Crypto.RSA long_rsa; Crypto.RSA short_rsa; diff --git a/lib/modules/SSL.pmod/handshake.pike b/lib/modules/SSL.pmod/handshake.pike index 96c20311eb8749d7242687125388eab42b5e443e..47b590cb811dd0e33c3a2e8324e7ae70991e1c71 100644 --- a/lib/modules/SSL.pmod/handshake.pike +++ b/lib/modules/SSL.pmod/handshake.pike @@ -291,8 +291,14 @@ Packet server_key_exchange_packet() switch (session->ke_method) { case KE_rsa: - temp_key = context->long_rsa || context->short_rsa; - +#ifdef WEAK_CRYPTO_40BIT + temp_key = context->short_rsa; +#endif /* WEAK_CRYPTO_40BIT (magic comment) */ +#ifndef WEAK_CRYPTO_40BIT + temp_key = (session->cipher_spec->is_exportable + ? context->short_rsa + : context->long_rsa); +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ if (temp_key) { /* Send a ServerKeyExchange message. */ diff --git a/lib/modules/SSL.pmod/session.pike b/lib/modules/SSL.pmod/session.pike index 1d2be7de72da9266763da5a1637d94b2d956ef74..74c80225707402862e09c17a617330d650aa35b2 100644 --- a/lib/modules/SSL.pmod/session.pike +++ b/lib/modules/SSL.pmod/session.pike @@ -81,9 +81,17 @@ void set_compression_method(int compr) protected string generate_key_block(string client_random, string server_random, array(int) version) { - int required = 2 * ( cipher_spec->key_material + - cipher_spec->hash_size + - cipher_spec->iv_size ); + int required = 2 * ( +#ifndef WEAK_CRYPTO_40BIT + cipher_spec->is_exportable ? +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ + (5 + cipher_spec->hash_size) +#ifndef WEAK_CRYPTO_40BIT + : ( cipher_spec->key_material + + cipher_spec->hash_size + + cipher_spec->iv_size) +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ + ); string key = ""; if(version[1] == PROTOCOL_SSL_3_0) { @@ -163,13 +171,66 @@ array(string) generate_keys(string client_random, string server_random, // server_write_MAC_secret keys[1] = key_data->get_fix_string(cipher_spec->hash_size); - keys[2] = key_data->get_fix_string(cipher_spec->key_material); - keys[3] = key_data->get_fix_string(cipher_spec->key_material); - if (cipher_spec->iv_size) +#ifndef WEAK_CRYPTO_40BIT + if (cipher_spec->is_exportable) +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ { - keys[4] = key_data->get_fix_string(cipher_spec->iv_size); - keys[5] = key_data->get_fix_string(cipher_spec->iv_size); + // Exportable (ie weak) crypto. + if(version[1] == PROTOCOL_SSL_3_0) { + // SSL 3.0 + function(string:string) md5 = .Cipher.MACmd5()->hash_raw; + + keys[2] = md5(key_data->get_fix_string(5) + + client_random + server_random) + [..cipher_spec->key_material-1]; + keys[3] = md5(key_data->get_fix_string(5) + + server_random + client_random) + [..cipher_spec->key_material-1]; + if (cipher_spec->iv_size) + { + keys[4] = md5(client_random + + server_random)[..cipher_spec->iv_size-1]; + keys[5] = md5(server_random + + client_random)[..cipher_spec->iv_size-1]; + } + + } else if(version[1] >= PROTOCOL_TLS_1_0) { + // TLS 1.0 or later. + string client_wkey = key_data->get_fix_string(5); + string server_wkey = key_data->get_fix_string(5); + keys[2] = .Cipher.prf(client_wkey, "client write key", + client_random+server_random, + cipher_spec->key_material); + keys[3] = .Cipher.prf(server_wkey, "server write key", + client_random+server_random, + cipher_spec->key_material); + if(cipher_spec->iv_size) { + string iv_block = .Cipher.prf("", "IV block", + client_random+server_random, + 2*cipher_spec->iv_size); + keys[4]=iv_block[..cipher_spec->iv_size-1]; + keys[5]=iv_block[cipher_spec->iv_size..]; +#ifdef SSL3_DEBUG + werror("sizeof(keys[4]):%d sizeof(keys[5]):%d\n", + sizeof([string]keys[4]), sizeof([string]keys[4])); +#endif + } + + } + + } + +#ifndef WEAK_CRYPTO_40BIT + else { + keys[2] = key_data->get_fix_string(cipher_spec->key_material); + keys[3] = key_data->get_fix_string(cipher_spec->key_material); + if (cipher_spec->iv_size) + { + keys[4] = key_data->get_fix_string(cipher_spec->iv_size); + keys[5] = key_data->get_fix_string(cipher_spec->iv_size); + } } +#endif /* !WEAK_CRYPTO_40BIT (magic comment) */ #ifdef SSL3_DEBUG printKey( "client_write_MAC_secret",keys[0]);