aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2015-05-08 15:39:38 +0200
committerHans <[email protected]>2015-05-29 15:00:21 +0200
commit59b5884dfef313c09d79f3c18063297c81fb67d5 (patch)
tree964b651ac9039dec900176bb173456ebf57ffe4f
parent979b94a3f31697fe06f329660f2ea9e48944490a (diff)
downloadotp-59b5884dfef313c09d79f3c18063297c81fb67d5.tar.gz
otp-59b5884dfef313c09d79f3c18063297c81fb67d5.tar.bz2
otp-59b5884dfef313c09d79f3c18063297c81fb67d5.zip
ssh: Check e and f parameters in kexdh
rfc 4253 says in section 8 that: "Values of 'e' or 'f' that are not in the range [1, p-1] MUST NOT be sent or accepted by either side. If this condition is violated, the key exchange fails." This commit implements the reception check.
-rw-r--r--lib/ssh/src/ssh_transport.erl50
1 files changed, 34 insertions, 16 deletions
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 34b76f1b08..6c0873fd9e 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -240,20 +240,30 @@ key_exchange_first_msg('diffie-hellman-group-exchange-sha1', Ssh0) ->
handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
{G, P} = dh_group1(),
- {Private, Public} = dh_gen_key(G, P, 1024),
- K = ssh_math:ipow(E, Private, P),
- Key = get_host_key(Ssh0),
- H = kex_h(Ssh0, Key, E, Public, K),
- H_SIG = sign_host_key(Ssh0, Key, H),
- {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_reply{public_host_key = Key,
- f = Public,
- h_sig = H_SIG
- }, Ssh0),
-
- {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}},
- shared_secret = K,
- exchanged_hash = H,
- session_id = sid(Ssh1, H)}}.
+ if
+ 1=<E, E=<(P-1) ->
+ {Private, Public} = dh_gen_key(G, P, 1024),
+ K = ssh_math:ipow(E, Private, P),
+ Key = get_host_key(Ssh0),
+ H = kex_h(Ssh0, Key, E, Public, K),
+ H_SIG = sign_host_key(Ssh0, Key, H),
+ {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_reply{public_host_key = Key,
+ f = Public,
+ h_sig = H_SIG
+ }, Ssh0),
+
+ {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}},
+ shared_secret = K,
+ exchanged_hash = H,
+ session_id = sid(Ssh1, H)}};
+ true ->
+ Error = {error,bad_e_from_peer},
+ Disconnect = #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, 'f' out of bounds",
+ language = "en"},
+ throw({Error, Disconnect})
+ end.
handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) ->
{Private, Public} = dh_gen_key(G,P,1024),
@@ -277,7 +287,7 @@ handle_new_keys(#ssh_msg_newkeys{}, Ssh0) ->
%% %% Select algorithms
handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F,
h_sig = H_SIG},
- #ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) ->
+ #ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) when 1=<F, F=<(P-1)->
K = ssh_math:ipow(F, Private, P),
H = kex_h(Ssh0, HostKey, Public, F, K),
@@ -293,7 +303,15 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F,
description = "Key exchange failed",
language = "en"},
throw({Error, Disconnect})
- end.
+ end;
+handle_kexdh_reply(#ssh_msg_kexdh_reply{}, _SSH) ->
+ Error = {error,bad_f_from_peer},
+ Disconnect = #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, 'f' out of bounds",
+ language = "en"},
+ throw({Error, Disconnect}).
+
handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = _Min,
n = _NBits,