diff options
Diffstat (limited to 'lib/ssl/src/ssl_cipher.erl')
-rw-r--r-- | lib/ssl/src/ssl_cipher.erl | 450 |
1 files changed, 419 insertions, 31 deletions
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index 173c53709b..dc413d6dfc 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -35,7 +35,7 @@ -export([security_parameters/3, suite_definition/1, decipher/5, cipher/5, suite/1, suites/1, anonymous_suites/0, psk_suites/1, srp_suites/0, - openssl_suite/1, openssl_suite_name/1, filter/2, + openssl_suite/1, openssl_suite_name/1, filter/2, filter_suites/1, hash_algorithm/1, sign_algorithm/1]). -compile(inline). @@ -73,25 +73,25 @@ cipher(?NULL, CipherState, <<>>, Fragment, _Version) -> {GenStreamCipherList, CipherState}; cipher(?RC4, CipherState, Mac, Fragment, _Version) -> State0 = case CipherState#cipher_state.state of - undefined -> crypto:rc4_set_key(CipherState#cipher_state.key); + undefined -> crypto:stream_init(rc4, CipherState#cipher_state.key); S -> S end, GenStreamCipherList = [Fragment, Mac], - {State1, T} = crypto:rc4_encrypt_with_state(State0, GenStreamCipherList), + {State1, T} = crypto:stream_encrypt(State0, GenStreamCipherList), {T, CipherState#cipher_state{state = State1}}; cipher(?DES, CipherState, Mac, Fragment, Version) -> block_cipher(fun(Key, IV, T) -> - crypto:des_cbc_encrypt(Key, IV, T) + crypto:block_encrypt(des_cbc, Key, IV, T) end, block_size(des_cbc), CipherState, Mac, Fragment, Version); cipher(?'3DES', CipherState, Mac, Fragment, Version) -> block_cipher(fun(<<K1:8/binary, K2:8/binary, K3:8/binary>>, IV, T) -> - crypto:des3_cbc_encrypt(K1, K2, K3, IV, T) + crypto:block_encrypt(des3_cbc, [K1, K2, K3], IV, T) end, block_size(des_cbc), CipherState, Mac, Fragment, Version); cipher(?AES, CipherState, Mac, Fragment, Version) -> block_cipher(fun(Key, IV, T) when byte_size(Key) =:= 16 -> - crypto:aes_cbc_128_encrypt(Key, IV, T); + crypto:block_encrypt(aes_cbc128, Key, IV, T); (Key, IV, T) when byte_size(Key) =:= 32 -> - crypto:aes_cbc_256_encrypt(Key, IV, T) + crypto:block_encrypt(aes_cbc256, Key, IV, T) end, block_size(aes_128_cbc), CipherState, Mac, Fragment, Version). build_cipher_block(BlockSz, Mac, Fragment) -> @@ -127,10 +127,10 @@ decipher(?NULL, _HashSz, CipherState, Fragment, _) -> {Fragment, <<>>, CipherState}; decipher(?RC4, HashSz, CipherState, Fragment, _) -> State0 = case CipherState#cipher_state.state of - undefined -> crypto:rc4_set_key(CipherState#cipher_state.key); + undefined -> crypto:stream_init(rc4, CipherState#cipher_state.key); S -> S end, - try crypto:rc4_encrypt_with_state(State0, Fragment) of + try crypto:stream_decrypt(State0, Fragment) of {State, Text} -> GSC = generic_stream_cipher_from_bin(Text, HashSz), #generic_stream_cipher{content = Content, mac = Mac} = GSC, @@ -147,17 +147,17 @@ decipher(?RC4, HashSz, CipherState, Fragment, _) -> decipher(?DES, HashSz, CipherState, Fragment, Version) -> block_decipher(fun(Key, IV, T) -> - crypto:des_cbc_decrypt(Key, IV, T) + crypto:block_decrypt(des_cbc, Key, IV, T) end, CipherState, HashSz, Fragment, Version); decipher(?'3DES', HashSz, CipherState, Fragment, Version) -> block_decipher(fun(<<K1:8/binary, K2:8/binary, K3:8/binary>>, IV, T) -> - crypto:des3_cbc_decrypt(K1, K2, K3, IV, T) + crypto:block_decrypt(des3_cbc, [K1, K2, K3], IV, T) end, CipherState, HashSz, Fragment, Version); decipher(?AES, HashSz, CipherState, Fragment, Version) -> block_decipher(fun(Key, IV, T) when byte_size(Key) =:= 16 -> - crypto:aes_cbc_128_decrypt(Key, IV, T); + crypto:block_decrypt(aes_cbc128, Key, IV, T); (Key, IV, T) when byte_size(Key) =:= 32 -> - crypto:aes_cbc_256_decrypt(Key, IV, T) + crypto:block_decrypt(aes_cbc256, Key, IV, T) end, CipherState, HashSz, Fragment, Version). block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0, @@ -212,10 +212,14 @@ anonymous_suites() -> ?TLS_DH_anon_WITH_AES_128_CBC_SHA, ?TLS_DH_anon_WITH_AES_256_CBC_SHA, ?TLS_DH_anon_WITH_AES_128_CBC_SHA256, - ?TLS_DH_anon_WITH_AES_256_CBC_SHA256]. + ?TLS_DH_anon_WITH_AES_256_CBC_SHA256, + ?TLS_ECDH_anon_WITH_RC4_128_SHA, + ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, + ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA, + ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA]. %%-------------------------------------------------------------------- --spec psk_suites(tls_version()) -> [cipher_suite()]. +-spec psk_suites(tls_version() | integer()) -> [cipher_suite()]. %% %% Description: Returns a list of the PSK cipher suites, only supported %% if explicitly set by user. @@ -274,6 +278,11 @@ srp_suites() -> %% TLS v1.1 suites suite_definition(?TLS_NULL_WITH_NULL_NULL) -> {null, null, null, null}; +%% RFC 5746 - Not a real cipher suite used to signal empty "renegotiation_info" extension +%% to avoid handshake failure from old servers that do not ignore +%% hello extension data as they should. +suite_definition(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) -> + {null, null, null, null}; %% suite_definition(?TLS_RSA_WITH_NULL_MD5) -> %% {rsa, null, md5, default_prf}; %% suite_definition(?TLS_RSA_WITH_NULL_SHA) -> @@ -423,8 +432,81 @@ suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) -> suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) -> {srp_rsa, aes_256_cbc, sha, default_prf}; suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) -> - {srp_dss, aes_256_cbc, sha, default_prf}. - + {srp_dss, aes_256_cbc, sha, default_prf}; + +%% RFC 4492 EC TLS suites +suite_definition(?TLS_ECDH_ECDSA_WITH_NULL_SHA) -> + {ecdh_ecdsa, null, sha, default_prf}; +suite_definition(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) -> + {ecdh_ecdsa, rc4_128, sha, default_prf}; +suite_definition(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) -> + {ecdh_ecdsa, '3des_ede_cbc', sha, default_prf}; +suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) -> + {ecdh_ecdsa, aes_128_cbc, sha, default_prf}; +suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) -> + {ecdh_ecdsa, aes_256_cbc, sha, default_prf}; + +suite_definition(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) -> + {ecdhe_ecdsa, null, sha, default_prf}; +suite_definition(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) -> + {ecdhe_ecdsa, rc4_128, sha, default_prf}; +suite_definition(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) -> + {ecdhe_ecdsa, '3des_ede_cbc', sha, default_prf}; +suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) -> + {ecdhe_ecdsa, aes_128_cbc, sha, default_prf}; +suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) -> + {ecdhe_ecdsa, aes_256_cbc, sha, default_prf}; + +suite_definition(?TLS_ECDH_RSA_WITH_NULL_SHA) -> + {ecdh_rsa, null, sha, default_prf}; +suite_definition(?TLS_ECDH_RSA_WITH_RC4_128_SHA) -> + {ecdh_rsa, rc4_128, sha, default_prf}; +suite_definition(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) -> + {ecdh_rsa, '3des_ede_cbc', sha, default_prf}; +suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) -> + {ecdh_rsa, aes_128_cbc, sha, default_prf}; +suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) -> + {ecdh_rsa, aes_256_cbc, sha, default_prf}; + +suite_definition(?TLS_ECDHE_RSA_WITH_NULL_SHA) -> + {ecdhe_rsa, null, sha, default_prf}; +suite_definition(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) -> + {ecdhe_rsa, rc4_128, sha, default_prf}; +suite_definition(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) -> + {ecdhe_rsa, '3des_ede_cbc', sha, default_prf}; +suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) -> + {ecdhe_rsa, aes_128_cbc, sha, default_prf}; +suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) -> + {ecdhe_rsa, aes_256_cbc, sha, default_prf}; + +suite_definition(?TLS_ECDH_anon_WITH_NULL_SHA) -> + {ecdh_anon, null, sha, default_prf}; +suite_definition(?TLS_ECDH_anon_WITH_RC4_128_SHA) -> + {ecdh_anon, rc4_128, sha, default_prf}; +suite_definition(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) -> + {ecdh_anon, '3des_ede_cbc', sha, default_prf}; +suite_definition(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) -> + {ecdh_anon, aes_128_cbc, sha, default_prf}; +suite_definition(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) -> + {ecdh_anon, aes_256_cbc, sha, default_prf}; + +%% RFC 5289 EC TLS suites +suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) -> + {ecdhe_ecdsa, aes_128_cbc, sha256, sha256}; +suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) -> + {ecdhe_ecdsa, aes_256_cbc, sha384, sha384}; +suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) -> + {ecdh_ecdsa, aes_128_cbc, sha256, sha256}; +suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) -> + {ecdh_ecdsa, aes_256_cbc, sha384, sha384}; +suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) -> + {ecdhe_rsa, aes_128_cbc, sha256, sha256}; +suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) -> + {ecdhe_rsa, aes_256_cbc, sha384, sha384}; +suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) -> + {ecdh_rsa, aes_128_cbc, sha256, sha256}; +suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) -> + {ecdh_rsa, aes_256_cbc, sha384, sha384}. %%-------------------------------------------------------------------- -spec suite(erl_cipher_suite()) -> cipher_suite(). @@ -573,7 +655,81 @@ suite({srp_anon, aes_256_cbc, sha}) -> suite({srp_rsa, aes_256_cbc, sha}) -> ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA; suite({srp_dss, aes_256_cbc, sha}) -> - ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA. + ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA; + +%%% RFC 4492 EC TLS suites +suite({ecdh_ecdsa, null, sha}) -> + ?TLS_ECDH_ECDSA_WITH_NULL_SHA; +suite({ecdh_ecdsa, rc4_128, sha}) -> + ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA; +suite({ecdh_ecdsa, '3des_ede_cbc', sha}) -> + ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA; +suite({ecdh_ecdsa, aes_128_cbc, sha}) -> + ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA; +suite({ecdh_ecdsa, aes_256_cbc, sha}) -> + ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA; + +suite({ecdhe_ecdsa, null, sha}) -> + ?TLS_ECDHE_ECDSA_WITH_NULL_SHA; +suite({ecdhe_ecdsa, rc4_128, sha}) -> + ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA; +suite({ecdhe_ecdsa, '3des_ede_cbc', sha}) -> + ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA; +suite({ecdhe_ecdsa, aes_128_cbc, sha}) -> + ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA; +suite({ecdhe_ecdsa, aes_256_cbc, sha}) -> + ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA; + +suite({ecdh_rsa, null, sha}) -> + ?TLS_ECDH_RSA_WITH_NULL_SHA; +suite({ecdh_rsa, rc4_128, sha}) -> + ?TLS_ECDH_RSA_WITH_RC4_128_SHA; +suite({ecdh_rsa, '3des_ede_cbc', sha}) -> + ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA; +suite({ecdh_rsa, aes_128_cbc, sha}) -> + ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA; +suite({ecdh_rsa, aes_256_cbc, sha}) -> + ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA; + +suite({ecdhe_rsa, null, sha}) -> + ?TLS_ECDHE_RSA_WITH_NULL_SHA; +suite({ecdhe_rsa, rc4_128, sha}) -> + ?TLS_ECDHE_RSA_WITH_RC4_128_SHA; +suite({ecdhe_rsa, '3des_ede_cbc', sha}) -> + ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA; +suite({ecdhe_rsa, aes_128_cbc, sha}) -> + ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA; +suite({ecdhe_rsa, aes_256_cbc, sha}) -> + ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; + +suite({ecdh_anon, null, sha}) -> + ?TLS_ECDH_anon_WITH_NULL_SHA; +suite({ecdh_anon, rc4_128, sha}) -> + ?TLS_ECDH_anon_WITH_RC4_128_SHA; +suite({ecdh_anon, '3des_ede_cbc', sha}) -> + ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA; +suite({ecdh_anon, aes_128_cbc, sha}) -> + ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA; +suite({ecdh_anon, aes_256_cbc, sha}) -> + ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA; + +%%% RFC 5289 EC TLS suites +suite({ecdhe_ecdsa, aes_128_cbc, sha256}) -> + ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; +suite({ecdhe_ecdsa, aes_256_cbc, sha384}) -> + ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384; +suite({ecdh_ecdsa, aes_128_cbc, sha256}) -> + ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256; +suite({ecdh_ecdsa, aes_256_cbc, sha384}) -> + ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384; +suite({ecdhe_rsa, aes_128_cbc, sha256}) -> + ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256; +suite({ecdhe_rsa, aes_256_cbc, sha384}) -> + ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384; +suite({ecdh_rsa, aes_128_cbc, sha256}) -> + ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256; +suite({ecdh_rsa, aes_256_cbc, sha384}) -> + ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384. %%-------------------------------------------------------------------- -spec openssl_suite(openssl_cipher_suite()) -> cipher_suite(). @@ -633,8 +789,62 @@ openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") -> openssl_suite("SRP-DSS-AES-128-CBC-SHA") -> ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA; openssl_suite("SRP-RSA-AES-128-CBC-SHA") -> - ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA. + ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA; +%% RFC 4492 EC TLS suites +openssl_suite("ECDH-ECDSA-RC4-SHA") -> + ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA; +openssl_suite("ECDH-ECDSA-DES-CBC3-SHA") -> + ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA; +openssl_suite("ECDH-ECDSA-AES128-SHA") -> + ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA; +openssl_suite("ECDH-ECDSA-AES256-SHA") -> + ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA; + +openssl_suite("ECDHE-ECDSA-RC4-SHA") -> + ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA; +openssl_suite("ECDHE-ECDSA-DES-CBC3-SHA") -> + ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA; +openssl_suite("ECDHE-ECDSA-AES128-SHA") -> + ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA; +openssl_suite("ECDHE-ECDSA-AES256-SHA") -> + ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA; + +openssl_suite("ECDHE-RSA-RC4-SHA") -> + ?TLS_ECDHE_RSA_WITH_RC4_128_SHA; +openssl_suite("ECDHE-RSA-DES-CBC3-SHA") -> + ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA; +openssl_suite("ECDHE-RSA-AES128-SHA") -> + ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA; +openssl_suite("ECDHE-RSA-AES256-SHA") -> + ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; + +openssl_suite("ECDH-RSA-RC4-SHA") -> + ?TLS_ECDH_RSA_WITH_RC4_128_SHA; +openssl_suite("ECDH-RSA-DES-CBC3-SHA") -> + ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA; +openssl_suite("ECDH-RSA-AES128-SHA") -> + ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA; +openssl_suite("ECDH-RSA-AES256-SHA") -> + ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA; + +%% RFC 5289 EC TLS suites +openssl_suite("ECDHE-ECDSA-AES128-SHA256") -> + ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; +openssl_suite("ECDHE-ECDSA-AES256-SHA384") -> + ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384; +openssl_suite("ECDH-ECDSA-AES128-SHA256") -> + ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256; +openssl_suite("ECDH-ECDSA-AES256-SHA384") -> + ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384; +openssl_suite("ECDHE-RSA-AES128-SHA256") -> + ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256; +openssl_suite("ECDHE-RSA-AES256-SHA384") -> + ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384; +openssl_suite("ECDH-RSA-AES128-SHA256") -> + ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256; +openssl_suite("ECDH-RSA-AES256-SHA384") -> + ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384. %%-------------------------------------------------------------------- -spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite(). @@ -716,6 +926,61 @@ openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) -> openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) -> "SRP-DSS-AES-256-CBC-SHA"; +%% RFC 4492 EC TLS suites +openssl_suite_name(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) -> + "ECDH-ECDSA-RC4-SHA"; +openssl_suite_name(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) -> + "ECDH-ECDSA-DES-CBC3-SHA"; +openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) -> + "ECDH-ECDSA-AES128-SHA"; +openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) -> + "ECDH-ECDSA-AES256-SHA"; + +openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) -> + "ECDHE-ECDSA-RC4-SHA"; +openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) -> + "ECDHE-ECDSA-DES-CBC3-SHA"; +openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) -> + "ECDHE-ECDSA-AES128-SHA"; +openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) -> + "ECDHE-ECDSA-AES256-SHA"; + +openssl_suite_name(?TLS_ECDH_RSA_WITH_RC4_128_SHA) -> + "ECDH-RSA-RC4-SHA"; +openssl_suite_name(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) -> + "ECDH-RSA-DES-CBC3-SHA"; +openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) -> + "ECDH-RSA-AES128-SHA"; +openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) -> + "ECDH-RSA-AES256-SHA"; + +openssl_suite_name(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) -> + "ECDHE-RSA-RC4-SHA"; +openssl_suite_name(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) -> + "ECDHE-RSA-DES-CBC3-SHA"; +openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) -> + "ECDHE-RSA-AES128-SHA"; +openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) -> + "ECDHE-RSA-AES256-SHA"; + +%% RFC 5289 EC TLS suites +openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) -> + "ECDHE-ECDSA-AES128-SHA256"; +openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) -> + "ECDHE-ECDSA-AES256-SHA384"; +openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) -> + "ECDH-ECDSA-AES128-SHA256"; +openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) -> + "ECDH-ECDSA-AES256-SHA384"; +openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) -> + "ECDHE-RSA-AES128-SHA256"; +openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) -> + "ECDHE-RSA-AES256-SHA384"; +openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) -> + "ECDH-RSA-AES128-SHA256"; +openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) -> + "ECDH-RSA-AES256-SHA384"; + %% No oppenssl name openssl_suite_name(Cipher) -> suite_definition(Cipher). @@ -730,14 +995,85 @@ filter(undefined, Ciphers) -> filter(DerCert, Ciphers) -> OtpCert = public_key:pkix_decode_cert(DerCert, otp), SigAlg = OtpCert#'OTPCertificate'.signatureAlgorithm, + PubKeyInfo = OtpCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.subjectPublicKeyInfo, + PubKeyAlg = PubKeyInfo#'OTPSubjectPublicKeyInfo'.algorithm, + + Ciphers1 = + case ssl_certificate:public_key_type(PubKeyAlg#'PublicKeyAlgorithm'.algorithm) of + rsa -> + filter_keyuse(OtpCert, ((Ciphers -- dsa_signed_suites()) -- ec_keyed_suites()) -- ecdh_suites(), + rsa_suites(), dhe_rsa_suites() ++ ecdhe_rsa_suites()); + dsa -> + (Ciphers -- rsa_keyed_suites()) -- ec_keyed_suites(); + ec -> + filter_keyuse(OtpCert, (Ciphers -- rsa_keyed_suites()) -- dsa_signed_suites(), + [], ecdhe_ecdsa_suites()) + end, case public_key:pkix_sign_types(SigAlg#'SignatureAlgorithm'.algorithm) of {_, rsa} -> - filter_rsa(OtpCert, Ciphers -- dsa_signed_suites()); + Ciphers1 -- ecdsa_signed_suites(); {_, dsa} -> - Ciphers -- rsa_signed_suites() + Ciphers1; + {_, ecdsa} -> + Ciphers1 -- rsa_signed_suites() end. %%-------------------------------------------------------------------- +-spec filter_suites([cipher_suite()]) -> [cipher_suite()]. +%% +%% Description: filter suites for algorithms +%%------------------------------------------------------------------- +filter_suites(Suites = [{_,_,_}|_]) -> + Algos = crypto:algorithms(), + lists:filter(fun({KeyExchange, Cipher, Hash}) -> + is_acceptable_keyexchange(KeyExchange, Algos) andalso + is_acceptable_cipher(Cipher, Algos) andalso + is_acceptable_hash(Hash, Algos) + end, Suites); + +filter_suites(Suites = [{_,_,_,_}|_]) -> + Algos = crypto:algorithms(), + lists:filter(fun({KeyExchange, Cipher, Hash, Prf}) -> + is_acceptable_keyexchange(KeyExchange, Algos) andalso + is_acceptable_cipher(Cipher, Algos) andalso + is_acceptable_hash(Hash, Algos) andalso + is_acceptable_prf(Prf, Algos) + end, Suites); + +filter_suites(Suites) -> + Algos = crypto:algorithms(), + lists:filter(fun(Suite) -> + {KeyExchange, Cipher, Hash, Prf} = ssl_cipher:suite_definition(Suite), + is_acceptable_keyexchange(KeyExchange, Algos) andalso + is_acceptable_cipher(Cipher, Algos) andalso + is_acceptable_hash(Hash, Algos) andalso + is_acceptable_prf(Prf, Algos) + end, Suites). + +is_acceptable_keyexchange(KeyExchange, Algos) + when KeyExchange == ecdh_ecdsa; + KeyExchange == ecdhe_ecdsa; + KeyExchange == ecdh_rsa; + KeyExchange == ecdhe_rsa; + KeyExchange == ecdh_anon -> + proplists:get_bool(ec, Algos); +is_acceptable_keyexchange(_, _) -> + true. + +is_acceptable_cipher(_, _) -> + true. + +is_acceptable_hash(null, _Algos) -> + true; +is_acceptable_hash(Hash, Algos) -> + proplists:get_bool(Hash, Algos). + +is_acceptable_prf(default_prf, _) -> + true; +is_acceptable_prf(Prf, Algos) -> + proplists:get_bool(Prf, Algos). + +%%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -950,7 +1286,13 @@ next_iv(Bin, IV) -> rsa_signed_suites() -> dhe_rsa_suites() ++ rsa_suites() ++ - psk_rsa_suites() ++ srp_rsa_suites(). + psk_rsa_suites() ++ srp_rsa_suites() ++ + ecdh_rsa_suites(). + +rsa_keyed_suites() -> + dhe_rsa_suites() ++ rsa_suites() ++ + psk_rsa_suites() ++ srp_rsa_suites() ++ + ecdhe_rsa_suites(). dhe_rsa_suites() -> [?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, @@ -982,7 +1324,25 @@ rsa_suites() -> ?TLS_RSA_WITH_RC4_128_SHA, ?TLS_RSA_WITH_RC4_128_MD5, ?TLS_RSA_WITH_DES_CBC_SHA]. - + +ecdh_rsa_suites() -> + [?TLS_ECDH_RSA_WITH_NULL_SHA, + ?TLS_ECDH_RSA_WITH_RC4_128_SHA, + ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384]. + +ecdhe_rsa_suites() -> + [?TLS_ECDHE_RSA_WITH_NULL_SHA, + ?TLS_ECDHE_RSA_WITH_RC4_128_SHA, + ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]. + dsa_signed_suites() -> dhe_dss_suites() ++ srp_dss_suites(). @@ -999,24 +1359,52 @@ srp_dss_suites() -> ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA]. -filter_rsa(OtpCert, RsaCiphers) -> +ec_keyed_suites() -> + ecdh_ecdsa_suites() ++ ecdhe_ecdsa_suites() + ++ ecdh_rsa_suites(). + +ecdsa_signed_suites() -> + ecdh_ecdsa_suites() ++ ecdhe_ecdsa_suites(). + +ecdh_suites() -> + ecdh_rsa_suites() ++ ecdh_ecdsa_suites(). + +ecdh_ecdsa_suites() -> + [?TLS_ECDH_ECDSA_WITH_NULL_SHA, + ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384]. + +ecdhe_ecdsa_suites() -> + [?TLS_ECDHE_ECDSA_WITH_NULL_SHA, + ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384]. + +filter_keyuse(OtpCert, Ciphers, Suites, SignSuites) -> TBSCert = OtpCert#'OTPCertificate'.tbsCertificate, TBSExtensions = TBSCert#'OTPTBSCertificate'.extensions, Extensions = ssl_certificate:extensions_list(TBSExtensions), case ssl_certificate:select_extension(?'id-ce-keyUsage', Extensions) of undefined -> - RsaCiphers; + Ciphers; #'Extension'{extnValue = KeyUse} -> - Result = filter_rsa_suites(keyEncipherment, - KeyUse, RsaCiphers, rsa_suites()), - filter_rsa_suites(digitalSignature, - KeyUse, Result, dhe_rsa_suites()) + Result = filter_keyuse_suites(keyEncipherment, + KeyUse, Ciphers, Suites), + filter_keyuse_suites(digitalSignature, + KeyUse, Result, SignSuites) end. -filter_rsa_suites(Use, KeyUse, CipherSuits, RsaSuites) -> +filter_keyuse_suites(Use, KeyUse, CipherSuits, Suites) -> case ssl_certificate:is_valid_key_usage(KeyUse, Use) of true -> CipherSuits; false -> - CipherSuits -- RsaSuites + CipherSuits -- Suites end. |