diff options
author | Hans Nilsson <[email protected]> | 2015-10-15 18:44:11 +0200 |
---|---|---|
committer | Hans Nilsson <[email protected]> | 2015-10-19 12:37:19 +0200 |
commit | 6af1014df69b4b2c019aead2435e537c20a39f15 (patch) | |
tree | c811e1121c35d601a5a06f6493ec5ca4a7753c17 | |
parent | 255f36937752404038f32ca67f438f13ef8ce4fb (diff) | |
download | otp-6af1014df69b4b2c019aead2435e537c20a39f15.tar.gz otp-6af1014df69b4b2c019aead2435e537c20a39f15.tar.bz2 otp-6af1014df69b4b2c019aead2435e537c20a39f15.zip |
ssh: Implemented ssh_transport:ecdh_validate_public_key (partly)
Defined in http://www.secg.org/sec1-v2.pdf '3.2.2 Validation of Elliptic Curve Public Keys'
according to RFC 5656 ch 4.
More to be done: check singularities, implement reading compressed points....
-rw-r--r-- | lib/ssh/src/ssh_transport.erl | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index d8574877f2..8b65806dc6 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -625,7 +625,61 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey, end. -ecdh_validate_public_key(_, _) -> true. % FIXME: Far too many false positives :) +%%%---------------------------------------------------------------- +%%% +%%% Standards for Efficient Cryptography Group, "Elliptic Curve Cryptography", SEC 1 +%%% Section 3.2.2.1 +%%% + +ecdh_validate_public_key(Key, Curve) -> + case key_size(Curve) of + undefined -> + false; + + Sz -> + case dec_key(Key, Sz) of + {ok,Q} -> + case crypto:ec_curve(Curve) of + {{prime_field,P}, {A, B, _Seed}, + _P0Bin, _OrderBin, _CoFactorBin} -> + on_curve(Q, bin2int(A), bin2int(B), bin2int(P)) + end; + + {error,compressed_not_implemented} -> % Be a bit generous... + true; + + _Error -> + false + end + end. + + +on_curve({X,Y}, A, B, P) when 0 =< X,X =< (P-1), + 0 =< Y,Y =< (P-1) -> + %% Section 3.2.2.1, point 2 + (Y*Y) rem P == (X*X*X + A*X + B) rem P; +on_curve(_, _, _, _) -> + false. + + +bin2int(B) -> + Sz = erlang:bit_size(B), + <<I:Sz/big-unsigned-integer>> = B, + I. + +key_size(secp256r1) -> 256; +key_size(secp384r1) -> 384; +key_size(secp521r1) -> 528; % Round 521 up to closest 8-bits. +key_size(_) -> undefined. + + +dec_key(Key, NBits) -> + Size = 8 + 2*NBits, + case <<Key:Size>> of + <<4:8, X:NBits, Y:NBits>> -> {ok,{X,Y}}; + <<4:8, _/binary>> -> {error,bad_format}; + _ -> {error,compressed_not_implemented} + end. %%%---------------------------------------------------------------- handle_new_keys(#ssh_msg_newkeys{}, Ssh0) -> |