summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2020-01-16 16:41:48 +0100
committerErlang/OTP <otp@erlang.org>2020-01-16 16:41:48 +0100
commite677c99701bc36b6d1096e7013576137ae84b882 (patch)
treed4d3db81c040324ec0dceb7341d8136dda2b6489
parentf1dd879fef88db3252a90b457d10a567ecaf936a (diff)
parentee9567ba1af27ef5d7a22271cb08643330720be3 (diff)
downloaderlang-e677c99701bc36b6d1096e7013576137ae84b882.tar.gz
Merge branch 'hans/ssh/fix_timing_20/OTP-16376' into maint-20
* hans/ssh/fix_timing_20/OTP-16376: ssh: Update crypto dependency ssh: Use constant time comparision in some places crypto: Add an equal-time comparision function. (NIF candidate)
-rw-r--r--lib/crypto/src/crypto.erl36
-rw-r--r--lib/ssh/src/ssh.app.src2
-rw-r--r--lib/ssh/src/ssh_auth.erl2
-rw-r--r--lib/ssh/src/ssh_transport.erl2
4 files changed, 39 insertions, 3 deletions
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 0d85b94b57..60f257f49f 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -24,6 +24,7 @@
-export([start/0, stop/0, info_lib/0, info_fips/0, supports/0, enable_fips_mode/1,
version/0, bytes_to_integer/1]).
+-export([equal_const_time/2]).
-export([hash/2, hash_init/1, hash_update/2, hash_final/1]).
-export([sign/4, sign/5, verify/5, verify/6]).
-export([generate_key/2, generate_key/3, compute_key/4]).
@@ -130,6 +131,41 @@ info_lib() -> ?nif_stub.
info_fips() -> ?nif_stub.
+%%%================================================================
+%%%
+%%% Compare in constant time
+%%%
+%%%================================================================
+
+%%% Candidate for a NIF
+
+equal_const_time(X1, X2) ->
+ equal_const_time(X1, X2, true).
+
+
+equal_const_time(<<B1,R1/binary>>, <<B2,R2/binary>>, Truth) ->
+ equal_const_time(R1, R2, Truth and (B1 == B2));
+equal_const_time(<<_,R1/binary>>, <<>>, Truth) ->
+ equal_const_time(R1, <<>>, Truth and false);
+equal_const_time(<<>>, <<>>, Truth) ->
+ Truth;
+
+equal_const_time([H1|T1], [H2|T2], Truth) ->
+ equal_const_time(T1, T2, Truth and (H1 == H2));
+equal_const_time([_|T1], [], Truth) ->
+ equal_const_time(T1, [], Truth and false);
+equal_const_time([], [], Truth) ->
+ Truth;
+
+equal_const_time(_, _, _) ->
+ false.
+
+%%%================================================================
+%%%
+%%% Hashing
+%%%
+%%%================================================================
+
-spec enable_fips_mode(boolean()) -> boolean().
enable_fips_mode(_) -> ?nif_stub.
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 4a22322333..59f6dd6cab 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -42,7 +42,7 @@
{env, []},
{mod, {ssh_app, []}},
{runtime_dependencies, [
- "crypto-4.2",
+ "crypto-@OTP-16376@",
"erts-6.0",
"kernel-3.0",
"public_key-1.5.2",
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 03d264745b..6d9373e9db 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -473,7 +473,7 @@ check_password(User, Password, Opts, Ssh) ->
case ?GET_OPT(pwdfun, Opts) of
undefined ->
Static = get_password_option(Opts, User),
- {Password == Static, Ssh};
+ {crypto:equal_const_time(Password,Static), Ssh};
Checker when is_function(Checker,2) ->
{Checker(User, Password), Ssh};
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 171c9abfee..87a81920b2 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -222,7 +222,7 @@ is_valid_mac(_, _ , #ssh{recv_mac_size = 0}) ->
true;
is_valid_mac(Mac, Data, #ssh{recv_mac = Algorithm,
recv_mac_key = Key, recv_sequence = SeqNum}) ->
- Mac == mac(Algorithm, Key, SeqNum, Data).
+ crypto:equal_const_time(Mac, mac(Algorithm, Key, SeqNum, Data)).
format_version({Major,Minor}, SoftwareVersion) ->
"SSH-" ++ integer_to_list(Major) ++ "." ++