aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/src/ssl_cipher.erl76
-rw-r--r--lib/ssl/src/ssl_cipher.hrl11
-rw-r--r--lib/ssl/src/ssl_record.hrl1
-rw-r--r--lib/ssl/src/tls_v1.erl4
4 files changed, 78 insertions, 14 deletions
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 79b772d2a2..e1d89c149e 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -44,7 +44,7 @@
key_algo/0]).
-type cipher() :: null |rc4_128 | idea_cbc | des40_cbc | des_cbc | '3des_ede_cbc'
- | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm.
+ | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305.
-type hash() :: null | sha | md5 | sha224 | sha256 | sha384 | sha512.
-type key_algo() :: null | rsa | dhe_rsa | dhe_dss | ecdhe_ecdsa| ecdh_ecdsa | ecdh_rsa| srp_rsa| srp_dss | psk | dhe_psk | rsa_psk | dh_anon | ecdh_anon | srp_anon.
-type erl_cipher_suite() :: {key_algo(), cipher(), hash()}.
@@ -141,8 +141,16 @@ cipher(?AES_CBC, CipherState, Mac, Fragment, Version) ->
%% Use for suites that use authenticated encryption with associated data (AEAD)
%%-------------------------------------------------------------------
cipher_aead(?AES_GCM, CipherState, SeqNo, AAD, Fragment, Version) ->
- aead_cipher(aes_gcm, CipherState, SeqNo, AAD, Fragment, Version).
+ aead_cipher(aes_gcm, CipherState, SeqNo, AAD, Fragment, Version);
+cipher_aead(?CHACHA20_POLY1305, CipherState, SeqNo, AAD, Fragment, Version) ->
+ aead_cipher(chacha20_poly1305, CipherState, SeqNo, AAD, Fragment, Version).
+aead_cipher(chacha20_poly1305, #cipher_state{key=Key} = CipherState, SeqNo, AAD0, Fragment, _Version) ->
+ CipherLen = erlang:iolist_size(Fragment),
+ AAD = <<AAD0/binary, ?UINT16(CipherLen)>>,
+ Nonce = <<SeqNo:64/integer>>,
+ {Content, CipherTag} = crypto:block_encrypt(chacha20_poly1305, Key, Nonce, {AAD, Fragment}),
+ {<<Content/binary, CipherTag/binary>>, CipherState};
aead_cipher(Type, #cipher_state{key=Key, iv = IV0, nonce = Nonce} = CipherState, _SeqNo, AAD0, Fragment, _Version) ->
CipherLen = erlang:iolist_size(Fragment),
AAD = <<AAD0/binary, ?UINT16(CipherLen)>>,
@@ -224,7 +232,9 @@ decipher(?AES_CBC, HashSz, CipherState, Fragment, Version) ->
%% Use for suites that use authenticated encryption with associated data (AEAD)
%%-------------------------------------------------------------------
decipher_aead(?AES_GCM, CipherState, SeqNo, AAD, Fragment, Version) ->
- aead_decipher(aes_gcm, CipherState, SeqNo, AAD, Fragment, Version).
+ aead_decipher(aes_gcm, CipherState, SeqNo, AAD, Fragment, Version);
+decipher_aead(?CHACHA20_POLY1305, CipherState, SeqNo, AAD, Fragment, Version) ->
+ aead_decipher(chacha20_poly1305, CipherState, SeqNo, AAD, Fragment, Version).
block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
HashSz, Fragment, Version) ->
@@ -256,6 +266,12 @@ block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end.
+aead_ciphertext_to_state(chacha20_poly1305, SeqNo, _IV, AAD0, Fragment, _Version) ->
+ CipherLen = size(Fragment) - 16,
+ <<CipherText:CipherLen/bytes, CipherTag:16/bytes>> = Fragment,
+ AAD = <<AAD0/binary, ?UINT16(CipherLen)>>,
+ Nonce = <<SeqNo:64/integer>>,
+ {Nonce, AAD, CipherText, CipherTag};
aead_ciphertext_to_state(_, _SeqNo, <<Salt:4/bytes, _/binary>>, AAD0, Fragment, _Version) ->
CipherLen = size(Fragment) - 24,
<<ExplicitNonce:8/bytes, CipherText:CipherLen/bytes, CipherTag:16/bytes>> = Fragment,
@@ -674,7 +690,15 @@ suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
suite_definition(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
{ecdh_rsa, aes_128_gcm, null, sha256};
suite_definition(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
- {ecdh_rsa, aes_256_gcm, null, sha384}.
+ {ecdh_rsa, aes_256_gcm, null, sha384};
+
+%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite_definition(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ {ecdhe_rsa, chacha20_poly1305, null, sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ {ecdhe_ecdsa, chacha20_poly1305, null, sha256};
+suite_definition(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ {dhe_rsa, chacha20_poly1305, null, sha256}.
%%--------------------------------------------------------------------
-spec suite(erl_cipher_suite()) -> cipher_suite().
@@ -954,7 +978,16 @@ suite({ecdhe_rsa, aes_256_gcm, null}) ->
suite({ecdh_rsa, aes_128_gcm, null}) ->
?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
suite({ecdh_rsa, aes_256_gcm, null}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384.
+ ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
+
+
+%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite({ecdhe_rsa, chacha20_poly1305, null}) ->
+ ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+suite({ecdhe_ecdsa, chacha20_poly1305, null}) ->
+ ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
+suite({dhe_rsa, chacha20_poly1305, null}) ->
+ ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
%%--------------------------------------------------------------------
-spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
@@ -1373,6 +1406,9 @@ is_acceptable_cipher(Cipher, Algos)
when Cipher == aes_128_gcm;
Cipher == aes_256_gcm ->
proplists:get_bool(aes_gcm, Algos);
+is_acceptable_cipher(Cipher, Algos)
+ when Cipher == chacha20_poly1305 ->
+ proplists:get_bool(Cipher, Algos);
is_acceptable_cipher(_, _) ->
true.
@@ -1403,7 +1439,9 @@ bulk_cipher_algorithm(Cipher) when Cipher == aes_128_cbc;
?AES_CBC;
bulk_cipher_algorithm(Cipher) when Cipher == aes_128_gcm;
Cipher == aes_256_gcm ->
- ?AES_GCM.
+ ?AES_GCM;
+bulk_cipher_algorithm(chacha20_poly1305) ->
+ ?CHACHA20_POLY1305.
type(Cipher) when Cipher == null;
Cipher == rc4_128 ->
@@ -1415,7 +1453,8 @@ type(Cipher) when Cipher == des_cbc;
Cipher == aes_256_cbc ->
?BLOCK;
type(Cipher) when Cipher == aes_128_gcm;
- Cipher == aes_256_gcm ->
+ Cipher == aes_256_gcm;
+ Cipher == chacha20_poly1305 ->
?AEAD.
key_material(null) ->
@@ -1433,6 +1472,8 @@ key_material(aes_256_cbc) ->
key_material(aes_128_gcm) ->
16;
key_material(aes_256_gcm) ->
+ 32;
+key_material(chacha20_poly1305) ->
32.
expanded_key_material(null) ->
@@ -1446,7 +1487,8 @@ expanded_key_material('3des_ede_cbc') ->
expanded_key_material(Cipher) when Cipher == aes_128_cbc;
Cipher == aes_256_cbc;
Cipher == aes_128_gcm;
- Cipher == aes_256_gcm ->
+ Cipher == aes_256_gcm;
+ Cipher == chacha20_poly1305 ->
unknown.
@@ -1461,11 +1503,13 @@ effective_key_bits(Cipher) when Cipher == rc4_128;
effective_key_bits('3des_ede_cbc') ->
168;
effective_key_bits(Cipher) when Cipher == aes_256_cbc;
- Cipher == aes_256_gcm ->
+ Cipher == aes_256_gcm;
+ Cipher == chacha20_poly1305 ->
256.
iv_size(Cipher) when Cipher == null;
- Cipher == rc4_128 ->
+ Cipher == rc4_128;
+ Cipher == chacha20_poly1305->
0;
iv_size(Cipher) when Cipher == aes_128_gcm;
@@ -1482,7 +1526,8 @@ block_size(Cipher) when Cipher == des_cbc;
block_size(Cipher) when Cipher == aes_128_cbc;
Cipher == aes_256_cbc;
Cipher == aes_128_gcm;
- Cipher == aes_256_gcm ->
+ Cipher == aes_256_gcm;
+ Cipher == chacha20_poly1305 ->
16.
prf_algorithm(default_prf, {3, N}) when N >= 3 ->
@@ -1638,7 +1683,8 @@ dhe_rsa_suites() ->
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
?TLS_DHE_RSA_WITH_DES_CBC_SHA,
?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384].
+ ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+ ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256].
psk_rsa_suites() ->
[?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
@@ -1687,7 +1733,8 @@ ecdhe_rsa_suites() ->
?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384].
+ ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256].
dsa_signed_suites() ->
dhe_dss_suites() ++ srp_dss_suites().
@@ -1737,7 +1784,8 @@ ecdhe_ecdsa_suites() ->
?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384].
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256].
filter_keyuse(OtpCert, Ciphers, Suites, SignSuites) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index 747ca8cdcd..448c2405aa 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -543,4 +543,15 @@
%% TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = {0xC0,0x32};
-define(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, <<?BYTE(16#C0), ?BYTE(16#32)>>).
+%%% Chacha20/Poly1305 Suites draft-agl-tls-chacha20poly1305-04
+
+%% TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = {0xcc, 0x13}
+-define(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#13)>>).
+
+%% TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = {0xcc, 0x14}
+-define(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#14)>>).
+
+%% TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = {0xcc, 0x15}
+-define(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#15)>>).
+
-endif. % -ifdef(ssl_cipher).
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index 78117681b4..53b5f2399b 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -92,6 +92,7 @@
-define(IDEA, 6).
-define(AES_CBC, 7).
-define(AES_GCM, 8).
+-define(CHACHA20_POLY1305, 9).
%% CipherType
-define(STREAM, 0).
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index 19b8512cdb..c4114278a4 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -221,6 +221,9 @@ suites(Minor) when Minor == 1; Minor == 2 ->
];
suites(3) ->
[
+ ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+
?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
@@ -230,6 +233,7 @@ suites(3) ->
?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,